梳理nginx的keepalive

这里回顾一下nginx的keepalive,nginx要启用keepalive,即client—>nginx是keepalive同时nginx到upstream的后端server也是keepalive。

client-nginx开启keepalive

  • 默认已开启,在HTTP上下文中设置,参数可调整:
http {
    keepalive_timeout  120s 120s;
    keepalive_requests 10000;
}
  • keepalive_timeout: keep-alive的client在服务器端保持开启的超时值,0则禁用client长连接。一般75秒够了,较大可设置120或300s
  • keepalive_requests: 设置一个keep-alive连接上可以服务的请求的最大数量,当最大请求数量达到时,连接被关闭,默认是100.

keepalive_requests的设置

该值需根据QPS来设置,比如QPS是10000,如果keepalive_requests=100,则代表每秒需关闭100个连接,迫使client再重新建立长连接,这样将导致client端有较多的timewait(即便此时keepalive已经在client和nginx之间生效。) 因此对于QPS较高的场景,非常有必要加大这个参数,以避免出现大量连接被生成再抛弃的情况,减少TIME_WAIT。

保持nginx到后端upstream的长连接(启用keepalive)

upstream上下文中配置:

  • keepalive 32; (默认值是32) 设置到upstream服务器的空闲keepalive连接的最大数量.0则不启用长连接。 例子:QPS是10000,后台upstream的响应时间如100ms,那么每秒将有1000个连接被使用。nginx为此建立连接池,请求结束时回收连接到连接池,此时的连接状态为idle,这个参数管理的就是处于idle状态的连接最大数量。 假如keepalive设置的是10,并假如外部请求都是均匀平稳的,那么这1000个连接应该一放到池子中就会被申请使用,线程池中的idle线程会非常少,趋近0,
  • 每10毫秒有100个新请求,需要100个连接
  • 每10毫秒有100个请求结束,需要释放100个连接
  • 如果请求和应答都均匀,则10毫秒内释放的连接刚好够用,不需要新建练级,连接池空闲连接为0

但假如:应答是平稳的,请求不平稳

  • 第1个10毫秒内有100个请求
  • 第2个10毫秒内有50个请求
  • 第3个10毫秒内有150个请求。

在第2个10毫秒里,第1个10毫秒内的100个连接被释放,但此时只需50个连接,那么就会有50个闲置的(idle)连接在连接池中,超过keepalive=10的40个会被回收。 在第3个10毫秒里,第2个10毫秒内的50个连接被释放,加上闲置的10个,一共是60个,但此时需要150个连接,那么就需新建90个连接, 这种情况下20毫秒里回收、新建了较多连接。

再假如:请求是平稳的(100/10ms),应答不平稳均匀

  • 第1个10毫秒只有50个请求结束
  • 第3个10毫秒有150个请求结束

分析:

  • 第1个10毫秒里,只结束50个请求,导致还有50个没回收,但此时又来100个请求,就需要额外再开50个连接
  • 第2个10毫秒里,结束150个请求结束,即有150个连接回收,此时来100个请求,还剩下50个连接,这些连接要被回收。

而且请求不均匀也会导致应答不均匀。理论上的大概1000个连接在反复的回收和再分配的过程中,必然出现两种非常矛盾场景在短时间内反复: 1. 连接不够用,造成新建连接 2. 连接空闲,造成关闭连接。从而使得总连接数出现反复震荡,不断的创建新连接和关闭连接,使得长连接的效果被大大削弱。

造成连接数量反复震荡的一个推手,就是这个keepalive 这个最大空闲连接数。毕竟连接池中的1000个连接在频繁利用时,出现短时间内多余10个空闲连接的概率实在太高。因此为了避免出现上面的连接震荡,必须考虑加大这个参数,比如上面的场景如果将keepalive设置为100或者200,就可以非常有效的缓冲请求和应答不均匀。

keepalive 这个参数一定要小心设置,尤其对于QPS比较高的场景,推荐先做一下估算,根据QPS和平均响应时间大体能计算出需要的长连接的数量。比如前面10000 QPS和100毫秒响应时间就可以推算出需要的长连接数量大概是1000. 然后将keepalive设置为这个长连接数量的10%到30%。

比较懒的同学,可以直接设置为keepalive=1000之类的,一般都OK的了。(感觉是越大越好)

在location上下文中,需要几个配置:

  • proxy_http_version 1.1
  • proxy_set_header Connection “";

第一个参数是说HTTP协议中对长连接的支持是从1.1版本之后才有的,因此最好通过proxy_http_version指令设置为"1.1”, 第二个参数是说,“Connection” header应该被清理。是清理从client过来的http header,因为即使是client和nginx之间是短连接,nginx和upstream之间也是可以开启长连接的。这种情况下必须清理来自client请求中的"Connection” header。

我们的参数设置多少合理

单台nginx的QPS是多少?

根据日志分析0.9版本的ingress-nginx的QPS是3900,而0.25.1实例QPS是5300,后端的平均响应时间假设是100ms,那么需要的长连接数量是:600 按照10-30%的计算,keepalive设置为 60-180就行。 即在ingress-nginx的configmap中把upstream-keepalive-connections设置为如100,对应在nginx的templ中就是cfg.UpstreamKeepaliveConnections