worker_processes 1;
daemon off;
events {
worker_connections 10240;
}
http {
resolver 8.8.8.8;
log_format access '[$time_local] [$remote_addr] [$uri] [|$http_user_agent]';
server {
listen 9000;
server_name test.me;
index index.html;
root /opt/project/lomemo/html;
access_log /tmp/test_access.log access;
error_log /tmp/test_error.log debug;
error_page 404 500 502 503 504 /50x.html;
location /coordinate_google_2_baidu {
internal;
proxy_pass_request_headers off;
proxy_connect_timeout 200ms;
proxy_read_timeout 200ms;
proxy_send_timeout 200ms;
proxy_pass http://api.map.baidu.com/ag/coord/convert?from=2&to=4&x=$arg_lon&y=$arg_lat;
}
location /baidu_place {
internal;
proxy_pass_request_headers off;
proxy_connect_timeout 2s;
proxy_read_timeout 2s;
proxy_send_timeout 1s;
proxy_pass http://api.map.baidu.com/place/search?&query=$arg_place®ion=$arg_region&output=json&key=$arg_key;
}
location /test {
content_by_lua '
local cjson = require("cjson");
local json_encode = cjson.encode;
local json_decode = cjson.decode;
local capture = ngx.location.capture;
local decode_base64 = ngx.decode_base64;
local spawn = ngx.thread.spawn;
local wait = ngx.thread.wait;
local region = ngx.var.arg_region;
local place = ngx.var.arg_place;
local lat = ngx.var.arg_lat or 0;
local lon = ngx.var.arg_lon or 0;
local function coord_baidu_2_google(lat, lon)
local res = capture("/coordinate_google_2_baidu", { args = { lat = lat, lon = lon }});
if res.status ~= 200 then
return nil;
end
local err, coord = pcall(json_decode, res.body);
if err == false or coord.error ~= 0 then
return nil;
end
local lat2 = decode_base64(coord.y);
local lon2 = decode_base64(coord.x);
return {lat=lat2, lon=lon2}
end
if place == nil then
ngx.say(json_encode({ret = ngx.HTTP_BAD_REQUEST, msg = "parameters miss"})); return;
end
local res = capture("/baidu_place?place="..place.."®ion="..region, {args = {key = "5233c0b420207c386a6f35bac943fd27"}});
if res.status ~= 200 then
ngx.say(json_encode({ret = 502, msg = "place query fail"})); return;
end
local err, geo = pcall(json_decode, res.body);
if err == false or geo.status ~= "OK" then
ngx.say(json_encode({ret = 502, msg = "place query fail"})); return;
end
local threads = {};
local t = {ret = ngx.HTTP_OK, msg = "success", place = {}};
local place = t.place;
if #geo.results > 0 then
for i = 1, #geo.results do
local p = {};
p["addr"] = geo.results[i].address;
p["name"] = geo.results[i].name;
p["lat"] = geo.results[i].location.lat;
p["lon"] = geo.results[i].location.lng;
table.insert(place, p);
table.insert(threads, spawn(coord_baidu_2_google, p["lat"], p["lon"]));
end
for i = 1, #threads do
local ok, res = wait(threads[i]);
if not ok or res == nil then
place[i]["addr"] = ""; -- 清除本条记录
else
place[i]["lat"] = res["lat"];
place[i]["lon"] = res["lon"];
end
end
ngx.say(json_encode(t)); return;
end
ngx.say(json_encode({ret = ngx.HTTP_NOT_FOUND, msg = "place not found"}));
';
}
}
}
1.ngx_openresty 的版本是:1.2.4.7 uname:Linux ubuntu 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:32:08 UTC 2012 i686 i686 i386 GNU/Linux
2/3上面提供了一个精简版nginx.conf
4.谢谢指正
5.ngx.thread.wait能否与
capture_multi一样,在传入进程数不定的时候,传入table..On Tuesday, November 27, 2012 3:53:53 AM UTC+8, agentzh wrote:
Hello!On Mon, Nov 26, 2012 at 1:59 AM, junwei shi wrote:
> 现在我的问题是geo.results的记录数较少的时候(如3个),可以顺利返回。
> 但测试数量较多(例如5个),上面代码92行,wait就阻塞住了(ngx.say只打印出1),
> 从tcpdump的结果来看,请求都返回的...
>
多谢你的报告!但我需要更多的信息来修正这个问题。对此我有如下建议:
1. 请总是提供你使用的 ngx_openresty 的版本以及操作系统的信息(uname -a):)
2. 请启用 nginx 的调试日志,并把问题请求对应的所有调试日志信息贴给我们。具体启用调试日志的方法是使用 ./configure
--with-debug 命令重新编译你的 openresty,然后在 nginx.conf 中配置
error_log logs/error.log debug;
3. 如果可能的话,请把你的应用简化为一个最小化的可以复现问题的完整示例。如果我能在我本地复现你看到的问题,那么可以大大节约我们之间的沟通成本,并更快地修复问题
:)
4. 值得一提的是,你把 thread(线程)这个单词拼写成了 thead(貌似英语里面没这个词):)
5. 还有就是,你的 ngx.thread 用法和 ngx.location.capture_multi 的语义并无区别:
http://wiki.nginx.org/HttpLuaModule#ngx.location.capture_multi
性能上只会更慢不会更快。如果实现为先返回的子请求就先输出,性能上会更好一些(如果语义上允许的话),而这是
ngx.location.capture_multi 做不到的。
Thanks!
-agentzh