http keepalive
http の初期の頃、http リクエストごとに TPC ソケット接続を開く必要があり、TCP 接続は 1 回使用すると切断されました。キープアライブを使用すると、この状況を改善できます。つまり、データの複数のコピーを切断せずに 1 つの TCP 接続で継続的に送信できます。キープアライブ メカニズムを使用すると、TCP 接続の確立回数を減らすことができます。これは、time_wait ステータスの接続も減らすことができることを意味し、それによってパフォーマンスが向上し、httpd サーバーのスループット レートが向上します (TCP 接続が少ないということは、システムの数が少ないことを意味します)カーネル呼び出し、ソケット accept() および close() 呼び出し)。ただし、キープアライブはフリーランチではないため、TCP 接続が長期間続くと、システム リソースが不正に使用される可能性があります。キープアライブを不適切に構成すると、接続を再利用するよりも大きな損失が発生する場合があります。したがって、キープアライブ タイムアウトを正しく設定することが非常に重要です。
keepalvie timeout
httpd デーモンは通常、キープアライブ タイムアウト時間設定パラメータを提供します。たとえば、nginx の keepalive_timeout や Apache の keepalivetimeout などです。この keepalive_timout 時間値は、http によって生成された TCP 接続が最後の応答を送信した後、接続の終了を開始する前に keepalive_timeout 秒間保持する必要があることを意味します。 httpd デーモンが応答の送信を完了すると、対応する tcp 接続を直ちにアクティブに閉じる必要があります。keepalive_timeout を設定した後、httpd デーモンは「もう少し待って、ブラウザからのリクエストがまだあるかどうか確認してください。」と要求します。 . 、これは keepalive_timeout 時間です。この待機時間中にデーモン プロセスがブラウザから http リクエストを受信しない場合、http 接続は閉じられます。
テストを容易にするスクリプトを書きました
<?php sleep(60); //为了便于分析测试,会根据测试进行调整 echo "www.jb51.net"; ?>
1. keepalive_timeout 時間が 0 の場合、つまりキープアライブが有効になっていない場合、TCP 接続のライフ サイクル
#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
1 行目から 3 行目は、tcp の 3 ウェイ ハンドシェイクを確立し、接続を確立します。 8898μsかかります
行4から5は、確立された接続を通じて最初のhttpリクエストを送信し、サーバーはリクエストの受信を確認します。 Time 5μs
5~6行目より、スクリプトの実行時間が60s1387μsであることが分かります。これはPHPスクリプトと一致しています。
6 行目と 8 行目で、サーバーは http 応答を送信します。応答の送信には 90166μs かかりました。
行 7 は、サーバー デーモンが接続を積極的に閉じることを示しています。行 6 と行 8 を組み合わせると、http 応答が送信されるとサーバーがすぐに tcp 接続を閉じることがわかります。
行 7、9、および 10 は、tcp 接続が 90963μs かかって順番に閉じられることを示しています。ここでのソケット リソースはすぐには解放されず、実際に解放されるまで 2msl (60 秒) 待つ必要があることに注意してください。
keepalive_timeout が設定されていない場合、ソケット リソースの作成と解放にかかる時間は、TCP 接続の確立、http リクエストの送信、php スクリプトの実行、http レスポンスの送信、およびTCP接続を2mslで閉じます。 (注: ここでの時間は参考値としてのみ使用できます。具体的な時間は主にネットワーク帯域幅と応答サイズによって決まります)
2. keepalive_timeout 時間が 0 より大きい場合、つまりキープアライブが有効な場合、TCP 接続のライフサイクル。分析を容易にするために、keepalive_timeout を 300 秒に設定します
#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
まず 6 行目から 8 行目を見てみましょう。最後の例との違いは、サーバー httpd デーモンが応答の送信を完了した後、 TCP 接続はすぐには積極的に閉じられません。
行 8 を行 6 と組み合わせると、5 分 (300 秒) 後にサーバーが TCP 接続をアクティブに閉じていることがわかります。この時間は、まさに keepalive_timeout を設定した時間です。
keepalive_timeout 時間を設定すると、ソケットの確立から解放までにかかる時間が keepalive_timeout 時間よりも長くなることがわかります。
3. keepalive_timeout 時間が 0 より大きく、複数の http 応答が同じ TCP 接続で送信される場合。ここでの分析を容易にするために、keepalive_timeout を 180 秒に設定します。
このテストを通じて、keepalive_timeout が最初の応答の終わりから計時を開始するのか、それとも最後の応答の終わりから計時を開始するのかを把握したいと考えています。テストの結果、後者であることが確認されました。ここでは、120 秒ごとにリクエストを送信し、TCP 接続を介して 3 つのリクエストを送信しました。
# 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连接也相应更少了。
以上がNginx で HTTP キープアライブを構成する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。