http keep-alive 实验
之前一篇讲道客户端和服务端是如何处理 http keep-alive 的, 其中很多都是一笔带过. 本篇补充一些细节.
版本
对于 http keep-alive 的概念, 这里的讨论只局限于 http 1.0, http 1.1. 对于 HTTP/2, HTTP/3 这里的讨论不适用.
http header - Connection & Keep-Alive
http 1.1 里面默认是持久连接. 但是我们可以看到下面的默认情况:
Chrome:
- 默认发送
Connection: keep-alive
头, 但是不发Keep-Alive
.
curl:
- Ubuntu 上的 curl 7.81.0 默认连
Connection
都没发. - Mac 上的 curl 8.6.0 也没发
Connection
header.
python requests:
GET / HTTP/1.1
Host: www.henu.edu.cn
User-Agent: python-requests/2.31.0
Connection: keep-alive
Java:
GET / HTTP/1.1
User-Agent: Java/17.0.4.1
Host: www.henu.edu.cn
Connection: keep-alive
JDK 里面的 Java client 默认的处理细节
Keep-Alive
header 里面的 timeout 和 max 分别对应 JDK HttpClient
里面的字段: timeout
- keepAliveTimeout
max
- keepAliveConnections
.
keepAliveTimeout
首先, 在 HttpClient 里面定义了一个 keepAliveTimeout
字段. JDK 21 到链接:
https://github.com/openjdk/jdk/blob/jdk-21%2B35/src/java.base/share/classes/sun/net/www/http/HttpClient.java#L136C9-L136C25.
这个字段有4种取值可能:
- 正值 - timeout 的秒数, 对应
Keep-Alive
header 里面的timeout
值. - 0 - 对方明确不需要
Keep-Alive
. - -1: 需要保持连接, http 1.1 设置或者不设
Connection: keep-alive
, 但是没有设置 timeout 值. - -2: 明确在
Keep-alive
header 里面设置了 timeout: 0 这个值.
如果把我们上面实验的客户端的结果反过来看成对方发来的response 来看, 都属于上面的第3种: -1 类型.
真实的JDK java 客户端的解析过程在这些代码中:
https://github.com/openjdk/jdk/blob/jdk-21%2B35/src/java.base/share/classes/sun/net/www/http/HttpClient.java#L907-L917
真正的使用这个值的地方
keepAliveConnections
这个值全部都是在 HttpClient 里面使用的.
parse:
- 若头部带来了
Keep-Alive
有max
则使用这个值. - 若没带来
max
, 则如果使用代理, 则是50, 否则是5.
细节代码: https://github.com/openjdk/jdk/blob/jdk-21%2B35/src/java.base/share/classes/sun/net/www/http/HttpClient.java#L902-L904