HTTP の Keep-Alive について確認した時のメモです。
参考
そもそも HTTP の Keep-Alive とは
- HTTP の
Keep-Alive
は HTTP の下のレイヤーの TCP/IP 通信を効率化する仕組み -
Keep-Alive
を使わない場合、HTTP のリクエストの都度 TCP/IP の 3way handshake などの TCP/IP の接続開始・終了処理が必要 -
Keep-Alive
を使うことで連続したリクエストの時に接続を再利用する - HTTPS の場合、下のレイヤーの SSL/TLS を利用し、こちらでも handshake 処理が必要な為、効率化の効果がある
- HTTP/1.0 ではリクエストヘッダに
Connection: Keep-Alive
を使いする事でKeep-Alive
の利用が出来る。HTTP/1.1 ではデフォルトで利用する - クライアントかサーバーが
Connection: Close
というヘッダーを付与して接続を切るか、タイムアウトするまで接続が維持される
確認してみる
実際に curl
や httpd
を使って動きを確認してみる
なお、httpd
は 2.4 系で確認した
httpd の Keep-Alive は on(デフォルト状態)
httpd 2.4 ではデフォルトで Keep-Alive は on になっている模様
念の為確認する
curl [host1] [host2]
とリクエストすることで Keep-Alive
を使って複数のリクエストを続けて送れるようなのでこれを利用する
$curl http://localhost http://localhost -v
* Rebuilt URL to: http://localhost/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 26 Aug 2020 21:25:55 GMT
< Server: Apache/2.4.43 ()
< Upgrade: h2,h2c
< Connection: Upgrade
< Last-Modified: Wed, 26 Aug 2020 21:19:15 GMT
< ETag: "6-5adce5f2d1b80"
< Accept-Ranges: bytes
< Content-Length: 6
< Content-Type: text/html; charset=UTF-8
<
Hello
* Connection #0 to host localhost left intact
* Rebuilt URL to: http://localhost/
* Found bundle for host localhost: 0x2269c20 [can pipeline]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 26 Aug 2020 21:25:55 GMT
< Server: Apache/2.4.43 ()
< Last-Modified: Wed, 26 Aug 2020 21:19:15 GMT
< ETag: "6-5adce5f2d1b80"
< Accept-Ranges: bytes
< Content-Length: 6
< Content-Type: text/html; charset=UTF-8
<
Hello
* Connection #0 to host localhost left intact
最後に Connection #0 to host localhost left intact
とあるので2回の HTTP リクエストは都度 TCP/IP の接続は開始・終了せずにやっているように見える。
ただ、よく分からないのでデフォルトで Keep-Alive
が有効ではない HTTP/1.0
を使って比較してみる。
$curl http://localhost http://localhost -v --http1.0
* Rebuilt URL to: http://localhost/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.0
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 26 Aug 2020 21:27:15 GMT
< Server: Apache/2.4.43 ()
< Upgrade: h2,h2c
< Connection: Upgrade, close
< Last-Modified: Wed, 26 Aug 2020 21:19:15 GMT
< ETag: "6-5adce5f2d1b80"
< Accept-Ranges: bytes
< Content-Length: 6
< Content-Type: text/html; charset=UTF-8
<
Hello
* Closing connection 0
* Rebuilt URL to: http://localhost/
* Hostname localhost was found in DNS cache
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#1)
> GET / HTTP/1.0
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 26 Aug 2020 21:27:15 GMT
< Server: Apache/2.4.43 ()
< Upgrade: h2,h2c
< Connection: Upgrade, close
< Last-Modified: Wed, 26 Aug 2020 21:19:15 GMT
< ETag: "6-5adce5f2d1b80"
< Accept-Ranges: bytes
< Content-Length: 6
< Content-Type: text/html; charset=UTF-8
<
Hello
* Closing connection 1
HTTP リクエストの都度 Closing connection 0
及び Closing connection 1
と出力されており、都度 TCP/IP の接続・終了を行っているように見える。
また、HTTP レスポンスについても Connection: Upgrade, close
となっており、通信が接続されている事が分かる。
次に HTTP/1.0
を使いつつ、明示的に HTTP リクエストのヘッダに Connection: Keep-Alive
を付与しててみる。
$curl http://localhost http://localhost -v --http1.0 -H 'Connection:Keep-Alive'
* Rebuilt URL to: http://localhost/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.0
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
> Connection:Keep-Alive
>
< HTTP/1.1 200 OK
< Date: Wed, 26 Aug 2020 21:37:43 GMT
< Server: Apache/2.4.43 ()
< Upgrade: h2,h2c
< Connection: Upgrade, Keep-Alive
< Last-Modified: Wed, 26 Aug 2020 21:19:15 GMT
< ETag: "6-5adce5f2d1b80"
< Accept-Ranges: bytes
< Content-Length: 6
< Keep-Alive: timeout=5, max=100
< Content-Type: text/html; charset=UTF-8
<
Hello
* Connection #0 to host localhost left intact
* Rebuilt URL to: http://localhost/
* Found bundle for host localhost: 0x1742c20 [can pipeline]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.0
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
> Connection:Keep-Alive
>
< HTTP/1.1 200 OK
< Date: Wed, 26 Aug 2020 21:37:43 GMT
< Server: Apache/2.4.43 ()
< Last-Modified: Wed, 26 Aug 2020 21:19:15 GMT
< ETag: "6-5adce5f2d1b80"
< Accept-Ranges: bytes
< Content-Length: 6
< Keep-Alive: timeout=5, max=99
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
<
Hello
* Connection #0 to host localhost left intact
この場合、HTTP/1.1
の場合と同じような挙動となり、この場合も HTTP リクエストの都度 TCP/IP の開始・終了は行ってないようにみえる。
httpd の Keep-Alive は off にする
/etc/httpd/conf/httpd.conf
に以下を追加する
KeepAlive Off
その後、httpd
を再起動してから同じようにリクエストを連続して送る。
$curl http://localhost http://localhost -v
* Rebuilt URL to: http://localhost/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 27 Aug 2020 23:08:38 GMT
< Server: Apache/2.4.43 ()
< Upgrade: h2,h2c
< Connection: Upgrade, close
< Last-Modified: Wed, 26 Aug 2020 21:19:15 GMT
< ETag: "6-5adce5f2d1b80"
< Accept-Ranges: bytes
< Content-Length: 6
< Content-Type: text/html; charset=UTF-8
<
Hello
* Closing connection 0
* Rebuilt URL to: http://localhost/
* Hostname localhost was found in DNS cache
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#1)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 27 Aug 2020 23:08:38 GMT
< Server: Apache/2.4.43 ()
< Upgrade: h2,h2c
< Connection: Upgrade, close
< Last-Modified: Wed, 26 Aug 2020 21:19:15 GMT
< ETag: "6-5adce5f2d1b80"
< Accept-Ranges: bytes
< Content-Length: 6
< Content-Type: text/html; charset=UTF-8
<
Hello
* Closing connection 1
動きとしては HTTP/1.0
と同じ動きとなった。
Keep-Alive
が効いておらず、都度 TCP/IP の接続をしているという状況のように見える。