Pular para conteúdo

socket: Módulo de compatibilidade automática LuaSocket/cosockets

Instalação

Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Em seguida, você pode prosseguir com os seguintes passos.

CentOS/RHEL 7 ou Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-socket

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-socket

Para usar esta biblioteca Lua com NGINX, certifique-se de que o nginx-module-lua está instalado.

Este documento descreve lua-resty-socket v1.0.0 lançado em 18 de janeiro de 2019.


Módulo de compatibilidade automática cosocket/LuaSocket para módulos lua-resty que desejam ser compatíveis com Lua simples ou com o contexto init do OpenResty.

O caso de uso para esta biblioteca é: você está desenvolvendo um módulo lua-resty que depende de cosockets, mas deseja que ele também possa ser usado no contexto init do OpenResty ou até mesmo em Lua simples. Este módulo visa sempre fornecer à sua biblioteca sockets que serão compatíveis no contexto atual, economizando tempo e esforço, e estendendo a API do LuaSocket para corresponder à dos cosockets, permitindo que você sempre escreva seu código como se estivesse em um contexto OpenResty compatível com cosockets.

Recursos

  • Permite que seus módulos lua-resty usem automaticamente cosockets/LuaSocket
  • Fornece proxy sslhandshake ao usar LuaSocket, com uma dependência do LuaSec
  • Não fica bloqueado ao usar LuaSocket em outros contextos se carregado no init do ngx_lua (um erro fácil de cometer)
  • Memoiza métodos de socket subjacentes para desempenho
  • Emite um log de aviso para seus usuários ao criar um socket usando LuaSocket enquanto está no OpenResty

Motivação

O objetivo deste módulo é fornecer uma alternativa automática ao LuaSocket quando os cosockets do [ngx_lua] não estão disponíveis. Ou seja: - Quando não utilizado no ngx_lua - Em contextos do ngx_lua onde os cosockets não são suportados (init, init_worker, etc...)

Ao recorrer ao LuaSocket, ele fornece shims para funções exclusivas de cosocket, como getreusedtimes, setkeepalive, etc...

É útil quando alguém está desenvolvendo um módulo/biblioteca que visa ser compatível tanto com ngx_lua quanto com Lua simples, ou em contextos do ngx_lua, como init.

Bibliotecas que o utilizam

Aqui estão alguns exemplos concretos do uso deste módulo. Você pode ver como escrevemos código como se estivéssemos constantemente em um contexto OpenResty compatível com cosocket, o que simplifica muito nosso trabalho e fornece compatibilidade com Lua simples fora da caixa.

  • lua-cassandra: veja como o módulo cassandra é compatível tanto no OpenResty quanto no Lua simples, sem esforços ou caminhos de código especiais que distinguem cosockets e LuaSocket.

Nota importante

O uso do LuaSocket dentro do ngx_lua é fortemente desencorajado devido à sua natureza bloqueante. No entanto, é aceitável usá-lo no contexto init, onde o bloqueio não é considerado prejudicial.

No futuro, apenas a fase init permitirá recorrer ao LuaSocket.

Atualmente, ele suporta apenas sockets TCP.

Uso

Todas as funções disponíveis seguem o mesmo protótipo da API de cosocket, permitindo que este exemplo seja executado em qualquer contexto ngx_lua ou fora do ngx_lua completamente:

local socket = require 'resty.socket'
local sock = socket.tcp()

getmetatable(sock) == socket.luasocket_mt ---> true/false dependendo do socket subjacente

sock:settimeout(1000) ---> 1000ms traduzido para 1s se LuaSocket

sock:getreusedtimes(...) ---> 0 se LuaSocket

sock:setkeepalive(...) ---> chama close() se LuaSocket

sock:sslhandshake(...) ---> dependência do LuaSec se LuaSocket

Assim, pode-se escrever um módulo que depende de sockets TCP, como:

local socket = require 'resty.socket'

local _M = {}

function _M.new()
  local sock = socket.tcp() -- semelhante a ngx.socket.tcp()

  return setmetatable({
    sock = sock
  }, {__index = _M})
end

function _M:connect(host, port)
  local ok, err = self.sock:connect(host, port)
  if not ok then
    return nil, err
  end

  local times, err = self.sock:getreusedtimes() -- API de cosocket
  if not times then
    return nil, err
  elseif times == 0 then
    -- tratar conexão
  end
end

return _M

O usuário de tal módulo poderia usá-lo em contextos com suporte a cosocket ou na fase init do ngx_lua, com pouco esforço do desenvolvedor.

GitHub

Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório do GitHub para nginx-module-socket.