使用官方的redis库连接redis,https://github.com/openresty/lua-resty-redis
即使在 TCP 连接上启用了 keep-alive,再次调用 sock:connect() 也不会复用原先的连接。TCP Kepp-Alive 仅用于在连接空闲时发送探测包以确保连接的活跃状态,并不会影响到连接的创建和销毁。
但是在 lua 里面使用 ngx.socket.tcp 创建tcp连接时,设置了 Keep-Alive选项后,如果再次调用相同的 ngx.socket.tcp 对象的 connect 方法,会尝试复用原先的连接。因为在 openresty 中,ngx.socket.tcp 对象实际上是基于 nginx的内置连接池来管理连接的,当你使用 ngx.socket.tcp 创建连接时,实际上会从nginx的连接池中获取连接,如果连接池中已经存在可用的连接,会复用这些连接而不是创建新的连接。
因此在openresty 中,设置了 keep-alive 选项后,再次调用相同的 ngx.socket.tcp 对象的 connect 方法会尝试复用原先的连接,从而实现连接的复用。
测试步骤:
- 启动 openresty 容器
docker run -p 18001:18000 -v /luaobj:/alben -itd --name lua_test bitnami/openresty:1.21
- 编写lua脚本
- redis-utils.lua
local _M = {}
local redis = require("resty.redis")
local red_config = require('./redis-config')
local ip = red_config.redis['ip']
local port = red_config.redis['port']
local database = red_config.redis['database']
local auth = red_config.redis['auth']
local timeout = red_config.redis['timeout']
local max_idle_time = red_config.redis['max_idle_time']
local pool_size = red_config.redis['pool_size']
local unpack = unpack or table.unpack
function _M.exec(func)
local red = redis:new()
red:set_timeout(timeout)
local ok, err = red:connect(ip, port)
if not ok then
ngx.say("redis","Cannot connect, host: " .. ip .. ", port: " .. port)
ngx.log(ngx.ERR, "redis","Cannot connect, host: " .. ip .. ", port: " .. port)
return nil, err
end
local count, err = red:get_reused_times()
if 0 == count then
ok, err = red:auth(auth)
if not ok then
ngx.say("failed to auth: ", err)
ngx.log(ngx.ERR,"failed to auth: ", err)
return
end
elseif err then
ngx.say("failed to get reused times: ", err)
ngx.log(ngx.ERR,"failed to get reused times: ", err)
return
end
red:select(database)
local res, err = func(red)
if res then
local ok, err1 = red:set_keepalive(max_idle_time, pool_size)
if not ok then
red:close()
end
end
ngx.log(ngx.ERR,"redis resposne: ", res)
return res, err
end
local res, err = _M.exec(
function(red)
return red:get("alben")
end
)
ngx.say(res)
return _M
-
- redis-config.lua
local _M = { redis={ip="192.168.213.69",port="6379",database=1,timeout=100000,max_idle_time=60000,pool_size=5, auth=""} } return _M
- 修改openresty的nginx配置
- 在nginx.conf 里 http 下添加如下配置
lua_package_path "/alben/?.lua;;";
-
- 在 /opt/bitnami/openresty/nginx/conf 路径下新建目录 server_blocks,并在其中添加如下 配置 demo.conf
server {
listen 18000;
# 设置访问日志路径
access_log /alben/access.log;
error_log /alben/error.log;
# 设置错误页面
error_page 404 /404.html;
location = /404.html {
internal;
}
# 静态文件根目录
location /redis {
default_type 'text/plain';
content_by_lua_file /alben/redis-utils.lua;
}
}
- 测试在注释掉 redis-utils 里面 set_keepalive 和 不注释掉 set_keepalive 相关代码的情况下,对nginx的性能的影响,测试使用 apache 下 的ab测试工具:ab -n 10000 -c 10 http://127.0.0.1:18001/redis
- 不注释掉 set_keepalive:此时观察主机上和6379建立tcp连接的数量大约在50多(备注:设置的 pool_size 数目为5也可能会建立50多个连接)
-
- 注释掉 set_keepalive相关逻辑,openresty -s reload 重新加载配置,可以观察到测试结果如下,其中建立tcp连接的数量达到了6000多,且访问延时明显增大