socket: 自动 LuaSocket/cosockets 兼容模块
安装
如果您尚未设置 RPM 仓库订阅,请 注册。然后您可以继续以下步骤。
CentOS/RHEL 7 或 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
要在 NGINX 中使用此 Lua 库,请确保已安装 nginx-module-lua。
本文档描述了 lua-resty-socket v1.0.0,于 2019 年 1 月 18 日发布。
这是一个用于 lua-resty 模块的 cosocket/LuaSocket 自动兼容模块,旨在与普通 Lua 或 OpenResty 的 init 上下文兼容。
此库的使用场景是:您正在开发一个依赖于 cosockets 的 lua-resty 模块,但您希望它也能在 OpenResty 的 init 上下文中使用,甚至在普通 Lua 中使用。该模块旨在始终为您的库提供与当前上下文兼容的套接字,节省您的时间和精力,并扩展 LuaSocket 的 API 以匹配 cosockets,从而允许您始终像在 cosocket 兼容的 OpenResty 上下文中一样编写代码。
特性
- 允许您的 lua-resty 模块自动使用 cosockets/LuaSocket
- 在使用 LuaSocket 时提供
sslhandshake代理,依赖于 LuaSec - 如果在 ngx_lua
init中加载,则不会阻止在进一步上下文中使用 LuaSocket(这是一个容易犯的错误) - 为性能缓存底层套接字方法
- 当在 OpenResty 中使用 LuaSocket 生成套接字时,为您的用户输出警告日志
动机
该模块的目的是在 [ngx_lua] 的 cosockets 不可用时提供自动回退到 LuaSocket。即:
- 当不在 ngx_lua 中使用时
- 在 ngx_lua 上下文中不支持 cosockets 的情况下(init、init_worker 等)
当回退到 LuaSocket 时,它为仅 cosocket 函数提供了适配器,例如 getreusedtimes、setkeepalive 等。
当开发旨在与 ngx_lua 和 普通 Lua 兼容的模块/库,或 在 ngx_lua 上下文中(如 init)时,这非常方便。
使用它的库
以下是此模块的一些具体使用示例。您可以看到我们只需编写代码,就像我们始终处于一个 cosocket 兼容的 OpenResty 上下文中,这大大简化了我们的工作,并提供了开箱即用的普通 Lua 兼容性。
- lua-cassandra:查看 cassandra 模块如何在 OpenResty 和普通 Lua 中兼容,而无需努力或特殊代码路径来区分 cosockets 和 LuaSocket。
重要说明
由于 LuaSocket 的阻塞特性,非常强烈不建议在 ngx_lua 中使用它。然而,在 init 上下文中使用它是可以的,因为阻塞不会被认为是有害的。
未来,只有 init 阶段将允许回退到 LuaSocket。
它目前仅支持 TCP 套接字。
使用
所有可用的函数都遵循与 cosocket API 相同的原型,允许此示例在任何 ngx_lua 上下文中或完全在 ngx_lua 外部运行:
local socket = require 'resty.socket'
local sock = socket.tcp()
getmetatable(sock) == socket.luasocket_mt ---> true/false 取决于底层套接字
sock:settimeout(1000) ---> 1000ms 如果是 LuaSocket 则转换为 1s
sock:getreusedtimes(...) ---> 如果是 LuaSocket 则为 0
sock:setkeepalive(...) ---> 如果是 LuaSocket 则调用 close()
sock:sslhandshake(...) ---> LuaSec 依赖如果是 LuaSocket
因此,可以编写一个依赖于 TCP 套接字的模块,例如:
local socket = require 'resty.socket'
local _M = {}
function _M.new()
local sock = socket.tcp() -- 类似于 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() -- cosocket API
if not times then
return nil, err
elseif times == 0 then
-- 处理连接
end
end
return _M
这样的模块用户可以在支持 cosocket 的上下文中使用它,或在 ngx_lua 的 init 阶段中使用,开发者几乎不需要付出额外的努力。
GitHub
您可以在 nginx-module-socket 的 GitHub 仓库 中找到此模块的其他配置提示和文档。