http keepalive
In the early days of http, each http request required opening a tpc socket connection, and the tcp connection was disconnected after one use. Using keep-alive can improve this situation, that is, multiple copies of data can be sent continuously in one TCP connection without disconnecting. By using the keep-alive mechanism, the number of TCP connection establishment times can be reduced, which also means that the time_wait status connection can be reduced, thereby improving performance and increasing the throughput rate of the httpd server (fewer TCP connections means fewer system kernel calls, socket accept() and close() calls). However, keep-alive is not a free lunch. Long-term TCP connections can easily lead to invalid use of system resources. Improperly configured keep-alives can sometimes cause greater losses than reusing connections. Therefore, it is very important to set the keep-alive timeout correctly.
keepalvie timeout
httpd daemon generally provides keep-alive timeout time setting parameters. For example, nginx's keepalive_timeout, and apache's keepalivetimeout. This keepalive_timout time value means that after a tcp connection generated by http transmits the last response, it needs to hold keepalive_timeout seconds before starting to close the connection. When the httpd daemon finishes sending a response, it should immediately actively close the corresponding tcp connection. After setting keepalive_timeout, the httpd daemon will want to say: "Wait a little longer and see if there are any more requests from the browser." Wait. , which is the keepalive_timeout time. If the daemon process does not receive an http request from the browser during this waiting time, the http connection will be closed.
I wrote a script to facilitate testing
<?php sleep(60); //为了便于分析测试,会根据测试进行调整 echo "www.jb51.net"; ?>
1. When the keepalive_timeout time is 0, that is, when keep-alive is not enabled, the life cycle of a tcp connection
#tcpdump -n host 218.1.57.236 and port 80
20:36:50.792731 ip 218.1.57.236.43052 > 222.73.211.215.http: s 1520902589:1520902589(0) win 65535 20:36:50.792798 ip 222.73.211.215.http > 218.1.57.236.43052: s 290378256:290378256(0) ack 1520902590 win 5840 20:36:50.801629 ip 218.1.57.236.43052 > 222.73.211.215.http: . ack 1 win 3276820:36:50.801838 ip 218.1.57.236.43052 > 222.73.211.215.http: p 1:797(796) ack 1 win 32768 20:36:50.801843 ip 222.73.211.215.http > 218.1.57.236.43052: . ack 797 win 5920:37:50.803230 ip 222.73.211.215.http > 218.1.57.236.43052: p 1:287(286) ack 797 win 59 20:37:50.803289 ip 222.73.211.215.http > 218.1.57.236.43052: f 287:287(0) ack 797 win 59 20:37:50.893396 ip 218.1.57.236.43052 > 222.73.211.215.http: . ack 288 win 32625 20:37:50.894249 ip 218.1.57.236.43052 > 222.73.211.215.http: f 797:797(0) ack 288 win 32625 20:37:50.894252 ip 222.73.211.215.http > 218.1.57.236.43052: . ack 798 win 59
Lines 1 to 3 establish a tcp three-way handshake and establish a connection. It takes 8898μs
Lines 4 to 5 send the first http request through the established connection, and the server confirms receipt of the request. Time 5μs
Lines 5~6, you can know that the script execution time is 60s1387μs, which is consistent with the PHP script.
In lines 6 and 8, the server sends an http response. It took 90166μs to send the response.
Line 7 indicates that the server daemon actively closes the connection. Combined with lines 6 and 8, it shows that once the http response is sent, the server immediately closes the tcp connection
Lines 7, 9, and 10 show that the tcp connection is closed sequentially, taking 90963μs. It should be noted that the socket resource here is not released immediately, and it needs to wait for 2msl (60s) before it is actually released.
It can be seen that when keepalive_timeout is not set, the time it takes for a socket resource to be created and released is: establishing a tcp connection, transmitting an http request, executing a php script, transmitting an http response, and closing the tcp connection 2msl. (Note: The time here can only be used as a reference. The specific time is mainly determined by network bandwidth and response size)
2. When the keepalive_timeout time is greater than 0, that is, when keep-alive is enabled, the life cycle of a tcp connection . In order to facilitate analysis, we set keepalive_timeout to 300s
#tcpdump -n host 218.1.57.236 and port 80
21:38:05.471129 ip 218.1.57.236.54049 > 222.73.211.215.http: s 1669618600:1669618600(0) win 65535 21:38:05.471140 ip 222.73.211.215.http > 218.1.57.236.54049: s 4166993862:4166993862(0) ack 1669618601 win 5840 21:38:05.481731 ip 218.1.57.236.54049 > 222.73.211.215.http: . ack 1 win 32768 21:38:05.481976 ip 218.1.57.236.54049 > 222.73.211.215.http: p 1:797(796) ack 1 win 32768 21:38:05.481985 ip 222.73.211.215.http > 218.1.57.236.54049: . ack 797 win 59 21:38:07.483626 ip 222.73.211.215.http > 218.1.57.236.54049: p 1:326(325) ack 797 win 59 21:38:07.747614 ip 218.1.57.236.54049 > 222.73.211.215.http: . ack 326 win 32605 21:43:07.448454 ip 222.73.211.215.http > 218.1.57.236.54049: f 326:326(0) ack 797 win 59 21:43:07.560316 ip 218.1.57.236.54049 > 222.73.211.215.http: . ack 327 win 32605 21:43:11.759102 ip 218.1.57.236.54049 > 222.73.211.215.http: f 797:797(0) ack 327 win 32605 21:43:11.759111 ip 222.73.211.215.http > 218.1.57.236.54049: . ack 798 win 59
Let’s take a look at lines 6 to 8 first. The difference from the last example is that after the server httpd daemon finishes sending the response, The tcp connection is not actively closed immediately.
Line 8, combined with line 6, we can see that after 5 minutes (300s), the server actively closes the tcp connection. This time is exactly the time we set keepalive_timeout.
It can be seen that when the keepalive_timout time is set, the time required from the establishment of a socket to its release is longer than the keepalive_timeout time.
3. When the keepalive_timeout time is greater than 0, and multiple http responses are sent on the same tcp connection. To facilitate analysis here, we set keepalive_timeout to 180s
Through this test, we want to figure out whether keepalive_timeout starts timing from the end of the first response or starts timing from the end of the last response. The test results confirmed that it is the latter. Here, we sent a request every 120s and sent 3 requests through a tcp connection.
# tcpdump -n host 218.1.57.236 and port 80
22:43:57.102448 ip 218.1.57.236.49955 > 222.73.211.215.http: s 4009392741:4009392741(0) win 65535 22:43:57.102527 ip 222.73.211.215.http > 218.1.57.236.49955: s 4036426778:4036426778(0) ack 4009392742 win 5840 22:43:57.111337 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 1 win 3276822:43:57.111522 ip 218.1.57.236.49955 > 222.73.211.215.http: p 1:797(796) ack 1 win 32768 22:43:57.111530 ip 222.73.211.215.http > 218.1.57.236.49955: . ack 797 win 59 22:43:59.114663 ip 222.73.211.215.http > 218.1.57.236.49955: p 1:326(325) ack 797 win 59 22:43:59.350143 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 326 win 3260522:45:59.226102 ip 218.1.57.236.49955 > 222.73.211.215.http: p 1593:2389(796) ack 650 win 32443 22:45:59.226109 ip 222.73.211.215.http > 218.1.57.236.49955: . ack 2389 win 83 22:46:01.227187 ip 222.73.211.215.http > 218.1.57.236.49955: p 650:974(324) ack 2389 win 83 22:46:01.450364 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 974 win 3228122:47:57.377707 ip 218.1.57.236.49955 > 222.73.211.215.http: p 3185:3981(796) ack 1298 win 32119 22:47:57.377714 ip 222.73.211.215.http > 218.1.57.236.49955: . ack 3981 win 108 22:47:59.379496 ip 222.73.211.215.http > 218.1.57.236.49955: p 1298:1622(324) ack 3981 win 108 22:47:59.628964 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 1622 win 3276822:50:59.358537 ip 222.73.211.215.http > 218.1.57.236.49955: f 1622:1622(0) ack 3981 win 108 22:50:59.367911 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 1623 win 32768 22:50:59.686527 ip 218.1.57.236.49955 > 222.73.211.215.http: f 3981:3981(0) ack 1623 win 32768 22:50:59.686531 ip 222.73.211.215.http > 218.1.57.236.49955: . ack 3982 win 108
第一组,三个ip包表示tcp三次握手建立连接,由浏览器建立。
第二组,发送第一次http请求并且得到响应,服务端守护进程输出响应之后,并没马上主动关闭tcp连接。而是启动keepalive_timout计时。
第三组,2分钟后,发送第二次http请求并且得到响应,同样服务端守护进程也没有马上主动关闭tcp连接,重新启动keepalive_timout计时。
第四组,又2分钟后,发送了第三次http请求并且得到响应。服务器守护进程依然没有主动关地闭tcp连接(距第一次http响应有4分钟了,大于keepalive_timeout值),而是重新启动了keepalive_timout计时。
第五组,跟最后一个响应keepalive_timeout(180s)内,守护进程再没有收到请求。计时结束,服务端守护进程主动关闭连接。4次挥手后,服务端进入time_wait状态。
这说明,当设定了keepalive_timeout,一个socket由建立到释放,需要时间是:tcp建立 + (最后一个响应时间 – 第一个请求时间) + tcp关闭 + 2msl。红色加粗表示每一次请求发送时间、每一次请求脚本执行时间、每一次响应发送时间,还有两两请求相隔时间。进一步测试,正在关闭或者 time_wait状态的tcp连接,不能传输http请求和响应。即,当一个连接结束keepalive_timeout计时,服务端守护进程发送第一 个fin标志ip包后,该连接不能再使用了。
http keep-alive与tcp keep-alive
http keep-alive与tcp keep-alive,不是同一回事,意图不一样。http keep-alive是为了让tcp活得更久一点,以便在同一个连接上传送多个http,提高socket的效率。而tcp keep-alive是tcp的一种检测tcp连接状况的保鲜机制。tcp keep-alive保鲜定时器,支持三个系统内核配置参数:
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time echo 15 > /proc/sys/net/ipv4/tcp_keepalive_intvl echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes
keepalive是tcp保鲜定时器,当网络两端建立了tcp连接之后,闲置idle(双方没有任何数据流发送往来)了 tcp_keepalive_time后,服务器内核就会尝试向客户端发 送侦测包,来判断tcp连接状况(有可能客户端崩溃、强制关闭了应用、主机不可达等等)。如果没有收到对方的回答(ack包),则会在 tcp_keepalive_intvl后再次尝试发送侦测包,直到收到对对方的ack,如果一直没有收到对方的ack,一共会尝试 tcp_keepalive_probes次,每次的间隔时间在这里分别是15s, 30s, 45s, 60s, 75s。如果尝试tcp_keepalive_probes,依然没有收到对方的ack包,则会丢弃该tcp连接。tcp连接默认闲置时间是2小时,一般 设置为30分钟足够了。也就是说,仅当nginx的keepalive_timeout值设置高于tcp_keepalive_time,并且距此tcp连接传输的最后一 个http响应,经过了tcp_keepalive_time时间之后,操作系统才会发送侦测包来决定是否要丢弃这个tcp连接。一般不会出现这种情况, 除非你需要这样做。
keep-alive与time_wait
使用http keep-alvie,可以减少服务端time_wait数量(因为由服务端httpd守护进程主动关闭连接)。道理很简单,相较而言,启用keep-alive,建立的tcp连接更少了,自然要被关闭的tcp连接也相应更少了。
The above is the detailed content of How to configure HTTP keepalive in Nginx. For more information, please follow other related articles on the PHP Chinese website!