[openresty]反向代理时出现大量ESTABLISHED连接

291 views
Skip to first unread message

王曦

unread,
Jul 8, 2013, 6:30:25 AM7/8/13
to openresty
项目中需要向外部服务器发起请求,配置文件大致如下:
http {
    ...

   upstream dsp {
       123.126.53.4:80;
       123.126.53.5:80;
       
       keepalive 16;
   }

    proxy_http_version 1.1;
    proxy_ignore_client_abort on;

    location /bid {
        internal;

        proxy_pass_request_headers off;
        proxy_set_header Content-Type "application/json";
        proxy_set_header Content-Length $http_content_length;
        proxy_pass_request_body on;

        proxy_connect_timeout 100ms;
        proxy_read_timeout 100ms;
        proxy_send_timeout 100ms;

        proxy_pass http://dsp/rtb/bid;
    }
}

在代码中通过capture /bid来向外部服务器发起请求,因为是外部的服务器,查看日志看到经常有超时发生,运行一段时间后,使用netstat看到有大量的ESTABLISHED连接出现:
tcp        0    0 10.78.96.27:26833           123.126.53.5:80            ESTABLISHED
这些sockete既没有传输数据也没有被关闭,当线上流量大时,运行几个小时候会出现几万个这样的连接,关掉进程后,发现这些连接会处于FIN_WAIT1状态而非TIME_WAIT状态一段时间后才消失掉

自己尝试解决这个问题,发现如果在upstream中只配置一个服务器,则不会出现上面的问题,最后偶然发现如果配置上proxy_next_upstream off;这条指令,配置2个服务器也不会出现上面的问题

请问大家碰到过类似的问题吗,究竟是nginx的bug还是我少配了指令导致的?

jie123108

unread,
Jul 8, 2013, 8:57:04 AM7/8/13
to openresty
如下代码,我在 location /test 中设置了参数name为name001,在 /test中 输出 name参数可以提到name001.
当进行rewrite后,在 /t2中,再输出 name后,客户端显示为空。
看起来ngx.req.set_uri_args设置的参数只在当前location有效,跳转后就失效了。
有何解决办法?
 
location ~ /test {
rewrite_by_lua "
ngx.req.set_uri_args('name=name001')
";
#echo $arg_name;
rewrite /test /t2;
}
location = /t2 {
echo $arg_sex;
echo $arg_name;
}

王曦

unread,
Jul 8, 2013, 9:04:05 AM7/8/13
to openresty
我用的openresty版本是1.2.3.8

Yichun Zhang (agentzh)

unread,
Jul 8, 2013, 5:34:21 PM7/8/13
to openresty
Hello!

2013/7/8 jie123108:
> 如下代码,我在 location /test 中设置了参数name为name001,在 /test中 输出 name参数可以提到name001.
> 当进行rewrite后,在 /t2中,再输出 name后,客户端显示为空。
> 看起来ngx.req.set_uri_args设置的参数只在当前location有效,跳转后就失效了。
> 有何解决办法?
>

这里并不是因为跳转后失效,而是因为 rewrite_by_lua 总是运行在 rewrite 指令之后,即使你把前者写在前面。所以当
rewrite 指令执行跳转时,你的 rewrite_by_lua 指令压根还没来得及运行。

有两种解法,推荐第 1 种:

1. 在 Lua 里面执行跳转,比如通过 ngx.req.set_uri 函数:

http://wiki.nginx.org/HttpLuaModule#ngx.req.set_uri

利用这个 Lua 接口可以实现 rewrite 指令的所有功能。而且不用担心配置指令的运行顺序方面的问题。

2. 在 http {} 配置块中添加下面这条配置指令以禁用 rewrite_by_lua 指令推迟到 ngx_rewrite
模块的指令运行完之后再执行的行为:

rewrite_by_lua_no_postpone on;

这样 rewrite_by_lua 指令便总是运行在 rewrite 指令之前。更多细节可以参见 ngx_lua 的官方文档:

http://wiki.nginx.org/HttpLuaModule#rewrite_by_lua_no_postpone

Regards,
-agentzh

Yichun Zhang (agentzh)

unread,
Jul 9, 2013, 6:46:09 PM7/9/13
to openresty
Hello!

2013/7/8 王曦:
> 项目中需要向外部服务器发起请求,配置文件大致如下:
[...]
> 在代码中通过capture
> /bid来向外部服务器发起请求,因为是外部的服务器,查看日志看到经常有超时发生,运行一段时间后,使用netstat看到有大量的ESTABLISHED连接出现:
> tcp 0 0 10.78.96.27:26833 123.126.53.5:80
> ESTABLISHED
> 这些sockete既没有传输数据也没有被关闭,当线上流量大时,运行几个小时候会出现几万个这样的连接,关掉进程后,发现这些连接会处于FIN_WAIT1状态而非TIME_WAIT状态一段时间后才消失掉
>

这里的 netstat 输出里哪个是你运行 nginx 的“本机”?是 10.78.96.27 还是
123.126.53.5?你能区分一下这些连接是上游连接还是下游连接么?

可以尝试使用 Nginx Systemtap Toolkit 中的工具对你的问题 nginx worker 进程进行分析,特别是其中的
ngx-active-reqs 工具:

https://github.com/agentzh/nginx-systemtap-toolkit#ngx-active-reqs

或许我们还应该再编写一个 ngx-conn-pools 工具对 nginx 自己的连接池进行实时监视。

另外,可以考虑升级到最新的 openresty 1.2.8.6:

http://openresty.org/#Download

Best regards,
-agentzh

王曦

unread,
Jul 9, 2013, 10:32:52 PM7/9/13
to openresty
10.79.96.27是运行nginx的本机,这些ESTABLISHED状态的连接都是下游连接

我来试试用工具分析一下这个问题,或者升级openresty看能否解决这个问题,多谢春哥

Yichun Zhang (agentzh)

unread,
Jul 10, 2013, 12:51:30 AM7/10/13
to openresty
Hello!

2013/7/9 王曦:
> 10.79.96.27是运行nginx的本机,这些ESTABLISHED状态的连接都是下游连接
>
> 我来试试用工具分析一下这个问题,或者升级openresty看能否解决这个问题,多谢春哥
>

如果是下游连接,使用我之前提到的 ngx-active-reqs 工具可以很好地分析这些连接在 nginx 内部的当前状态。

另外,请确保你恰当地配置了 ngx_proxy 模块的各项超时设置。当启用 proxy_next_upstream
时,超时上限会被成倍放大。另外,启用 TCP keepalive 也可以较为可靠检测客户端连接提前断开的情形,避免出现 half-open
状态的连接(在你服务器端看这样的连接永远是 ESTABLISHED 状态)。

Best regards,
-agentzh
Reply all
Reply to author
Forward
0 new messages