后续查redis使用的是thread.spawn的方式来做,代码大致如下,agentzh 大牛帮忙看看,应该是没有问题的。由于只是做性能测试,没做更严谨的检查和处理。
function get_red_server(idx)
local conf = servers[idx]
local red, err = redis:new()
if not red then
ngx.log(ngx.ERR, "failed new redis to %s:%s", conf[1], conf[2])
return nil, err
end
-- timeout 1s
red:set_timeout(20000)
local ok, err = red:connect(conf[1], conf[2])
if not ok then
-- log error
ngx.log(ngx.ERR, string.format("connect redached error:%s:%s, %s",conf[1], conf[2], err))
return nil, err
end
return red
end
local function upstream_query(server_index, query_args, args)
local query_results = {}
local red, err = get_red_server(server_index)
if err then
ngx.exit(500)
end
red:init_pipeline()
for i, query_arg in ipairs(query_args) do
query_results[i] = {hashname=query_arg[1], filed=query_arg[2], result='', err_code=0, err=''}
--ngx.log(ngx.ERR, "query: " .. to_string(query_arg[1]))
if err then
ngx.exit(500)
end
--ngx.say("hset: ", query_arg[1], ", ", query_arg[2], ", ", query_arg[3])
if args.action == "set" then
red:hset(query_arg[1], query_arg[2], query_arg[3])
else
red:hget(query_arg[1], query_arg[2])
end
end
local results, err = red:commit_pipeline()
if not results then
ngx.log(ngx.ERR, "failed to commit the pipelined requests: ", err)
return
end
for i, res in ipairs(results) do
if type(res) == "table" then
if not res[1] then
query_results[i].err_code = -1
query_results[i].err = res[2]
ngx.log(ngx.ERR, "failed to run command ", to_string(query_results[i]))
else
query_results[i].err_code = -2
query_results[i].err = 'unknow.'
ngx.log(ngx.ERR, "failed to run command ", to_string(query_results[i]))
end
else
query_results[i].result = res
end
end
local ok, err = red:set_keepalive(0, 10000)
if not ok then
ngx.log(ngx.ERR, "failed to set keepalive: ", err)
--ngx.exit(500)
end
return query_results
end
local threads = {}
local results = {}
local servers = {{"127.0.0.1", 6379}, {"127.0.0.1", 6380}, {"127.0.0.1", 6381}}
local redis_querys = {
{
{"a", "a", "a"},
{"a_hashname", "a_filed", "a_value"},
{"b_hashname", "b_filed", "b_value"},
},
{
{"c_hashname", "c_filed", "c_value"},
},
{
{"d_hashname", "d_filed", "d_value"},
},
}
for i, query_args in ipairs(redis_querys) do
if next(query_args) ~= nil then
local tf, err = ngx.thread.spawn(upstream_query, i, query_args, args)
if tf then
table.insert(threads, tf)
else
ngx.log(ngx.ERR, "failed to spawn thread f: ", err, ", query: ", to_string(query_args))
ngx.exit(500)
end
end
end
for i = 1, #threads do
local ok, res = ngx.thread.wait(threads[i])
if not ok or not res then
ngx.log(ngx.ERR, "failed to run thread: ", res)
ngx.exit(500)
else
list_concat(results, res)
end
end
ngx.say(cjson.encode(results))
在 2013年3月1日下午4:39,xiaobo lee
<lee.xia...@gmail.com>写道:
谢谢答复,已经启用了连接池, set_keepalive(0, 10000)配置如下,我跑起来以后系统资源占用都不多,所以是说根本没有达到极限?ab 本身测试存在瓶颈?有什么其他工具可测试吗?或者自己写一个多并发的请求测试程序?
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
worker_rlimit_nofile 90000;
events {
worker_connections 120000;
}
http {
lua_package_path "/home/test/test/?.lua;/home/test/installed/lualib/resty/?.lua;;";
lua_package_cpath '/home/test/installed/lualib/?.so;;';
access_log off; # 关闭日志
keepalive_timeout 5;
error_log /home/test/installed/nginx/logs/error.log warn;
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 8361 backlog=5000;
lua_code_cache on;
location = /backend {
content_by_lua_file /home/test/test/redis_backend.lua;
}
}
在 2013年3月1日上午3:41,agentzh
<age...@gmail.com>写道:
Hello!
2013/2/28 xiaobo lee:
>> 2. 同时压测时应启用 ab 的 -k 选项以及 lua-resty-redis 的连接池,否则很容易把系统的临时端口用尽。如果你坚持不使用
>> ab 的 -k 选项以启用 http 1.0 keepalive,则最好配置 lua_http10_buffering off 指令以提高
>> http 1.0 短连接访问下的性能。
>
> nginx 配置 keepalive_timeout 5;其他未配置。
>
启用 lua-resty-redis 的 cosocket 连接池会显著提升性能:
https://github.com/agentzh/lua-resty-redis#set_keepalive
否则在这种测试下 TCP 连接的建立和关闭很容易成为性能瓶颈。
>
> redis 我用自带的bechmark简单测了一下,并发开8000,mset 可以达到 35K,并且运行测试过程中,redis cpu
> 等资源占用不多,应该是没有到达瓶颈。
> ab 可能是个瓶颈?
>
> 另外我测试过程中,ab -k 加上的话,效率反而会下降,不加测试都可以跑到 5000+。
>
如果 ab -k 反而性能下降,说明你的配置有问题,如果你使用 -k 的话,就不应配置 lua_http10_buffering
off,因为那样的话,HTTP 1.0 keepalive 就不支持了。和 lua-resty-redis
一侧不启用连接池的后果一样,你其实在测试你 TCP 建立和关闭连接的性能。
请确保你的 nginx 进程没有在刷日志文件(包括访问日志和错误日志);磁盘 I/O 是非常昂贵的。
仔细观察你的系统各个资源的使用率,确定瓶颈的所在。对于 CPU 占用较高的进程,可以使用“火焰图”工具分析之:
https://github.com/agentzh/nginx-systemtap-toolkit#ngx-sample-bt