http keep-alive无效导致短连接的案例总结

本文基于关于nginx的keep-alive配置的安全性分析,结合实际情况的再说几点。

nginx针对upstream配置keep-alive的特殊性

最近反馈生产nginx的TIME_WAIT状态比较多,其中对接ingress的忙时7000左右,担心更多接口接入后可能存在隐患。

在测试环境验证,的确有疑似大量短连接的情况。经分析,是配置有误导致。

当前的配置示例(高度简化过)如下:

http {
  proxy_http_version 1.1;
  proxy_set_header Connection "Keep-Alive";

  upstream app   {
    sticky expires=1h path=/;
    server x.y.z.k:1094 max_fails=2;
  }

  server {
    location /app {
      proxy_pass http://app
      proxy_set_header Host $proxy_host;
      proxy_set_header X-Real-IP $remote_addr;
   }
}

其中最前面两个是用来修改短连接为长连接用的。

但这里有两个情况需要注意:

1.Upstream的keepalive默认是没有设值的。如果需要启动keepalive,需要在upsteram指令块中进行相应配置。参考http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

2.这里有个非常特殊的情况,根据官方文档说明http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header文档中描述,只有当前作用域的配置没有proxy_set_header,才会考虑上级的proxy_set_header指令,否则设置默认(短连接)。所以上面的配置是无效的。需要考虑在location增加指令。

Allows redefining or appending fields to the request header passed to the proxied server. The value can contain text, variables, and their combinations. These directives are inherited from the previous configuration level if and only if there are no proxy_set_header directives defined on the current level. By default, only two fields are redefined:

proxy_set_header Host       $proxy_host;
proxy_set_header Connection close;

jmeter的keep-alive配置如何生效

一般压测机出现端口不足,是由于没有使用keep-alive导致的。如果要使用keep-alive,关注下面三个点:

  1. 在http请求中选中keep-alive。这是必须的。
  2. 修改httpclient4.idletimeout,这个主要在服务端没有返回Keep-Alive来指定超时时间的情况。另外,这个是针对httpclint4(在jmeter http request高级配置中设置)
# Idle connection timeout (Milliseconds) to apply if the server does not send
# Keep-Alive headers (default 0)
# Set this > 0 to compensate for servers that don't send a Keep-Alive header
# If <= 0, idle timeout will only apply if the server sends a Keep-Alive header
httpclient4.idletimeout=60000
  1. 还有个关键的配置,这也是网上很多例子都是无效的主要原因,主要是因为jmeter在5.0做了一个变更
Since JMeter 5.0, when using default HC4 Implementation, JMeter will reset HTTP state (SSL State + Connections) on each thread group iteration. If you don't want this behaviour, set httpclient.reset_state_on_thread_group_iteration=false

所以最关键的地方是要把这个参数调整成false。

httpclient.reset_state_on_thread_group_iteration=false