2025年4月8日 星期二 乙巳(蛇)年 正月初九 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 服务器 > 网络服务

HTTP 的会话保持 Keep-Alive 信息咋看不到呢?

时间:12-14来源:作者:点击数:10

KEEP-ALIVE

为啥服务端返回没有 Connection: keep-alive 的信息

使用 curl -v 查看 keep alive,服务端没有返回任何 keep-alive 的信息,比较疑惑,于是补充了一下知识。

  • $ curl -v http://127.0.0.1:8812 http://127.0.0.1:8812
  • * Trying 127.0.0.1...
  • * TCP_NODELAY set
  • * Connected to 127.0.0.1 (127.0.0.1) port 8812 (#0)
  • > GET / HTTP/1.1
  • > Host: 127.0.0.1:8812
  • > User-Agent: curl/7.64.1
  • > Accept: */*
  • >
  • < HTTP/1.1 200 OK
  • < Date: Tue, 31 Dec 2019 03:52:27 GMT
  • < Content-Length: 6
  • < Content-Type: text/plain; charset=utf-8
  • <
  • Hello
  • * Connection #0 to host 127.0.0.1 left intact
  • * Found bundle for host 127.0.0.1: 0x7fda13614800 [can pipeline]
  • * Could pipeline, but not asked to!
  • * Re-using existing connection! (#0) with host 127.0.0.1
  • * Connected to 127.0.0.1 (127.0.0.1) port 8812 (#0)
  • > GET / HTTP/1.1
  • > Host: 127.0.0.1:8812
  • > User-Agent: curl/7.64.1
  • > Accept: */*
  • >
  • < HTTP/1.1 200 OK
  • < Date: Tue, 31 Dec 2019 03:52:27 GMT
  • < Content-Length: 6
  • < Content-Type: text/plain; charset=utf-8
  • <
  • Hello
  • * Connection #0 to host 127.0.0.1 left intact
  • * Closing connection 0
  • http-upload-benchmark git:(master)

left intact 意思是 保留不变的,例句:when the nest is upset no egg is left intact [idiom.] — 覆巢之下无完卵

什么是 Keep-Alive 模式?

HTTP 协议采用 请求-应答 模式,当使用普通模式,即非 KeepAlive 模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP 协议为无连接的协议);当使用 Keep-Alive 模式(又称持久连接、连接重用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。来源

在 HTTP 1.1 中 所有的连接默认都是持续连接,除非特殊声明不支持。

根据 Wiki HTTP 持久连接

在 HTTP 1.0 中, 没有官方的 keepalive 的操作。通常是在现有协议上添加一个指数。如果浏览器支持 keep-alive,它会在请求的包头中添加:

  • > Connection: Keep-Alive

然后当服务器收到请求,作出回应的时候,它也添加一个头在响应中:

  • > Connection: Keep-Alive

这样做,连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个连接。这一直继续到客户端或服务器端认为会话已经结束,其中一方中断连接。

在 HTTP 1.1 中 所有的连接默认都是持续连接,除非特殊声明不支持。HTTP 持久连接不使用独立的 keepalive 信息,而是仅仅允许多个请求使用单个连接

按照这个思路,我做了一下验证:

HTTP/1.0,果然发完,服务端主动关闭连接了

  • $ telnet 127.0.0.1 8812
  • Trying 127.0.0.1...
  • Connected to localhost.
  • Escape character is '^]'.
  • GET / HTTP/1.0
  • Host: 127.0.0.1:8812
  • HTTP/1.0 200 OK
  • Date: Tue, 31 Dec 2019 03:59:34 GMT
  • Content-Length: 6
  • Content-Type: text/plain; charset=utf-8
  • Hello
  • Connection closed by foreign host.
  • $

HTTP/1.0,加上 Connection: Keep-Alive,服务器端没关闭连接

  • http-upload-benchmark git:(master) telnet 127.0.0.1 8812
  • Trying 127.0.0.1...
  • Connected to localhost.
  • Escape character is '^]'.
  • GET / HTTP/1.0
  • Host: 127.0.0.1:8812
  • Connection: Keep-Alive
  • HTTP/1.0 200 OK
  • Date: Tue, 31 Dec 2019 04:00:38 GMT
  • Content-Length: 6
  • Content-Type: text/plain; charset=utf-8
  • Connection: keep-alive
  • Hello
  • GET / HTTP/1.0
  • Host: 127.0.0.1:8812
  • HTTP/1.0 200 OK
  • Date: Tue, 31 Dec 2019 04:00:48 GMT
  • Content-Length: 6
  • Content-Type: text/plain; charset=utf-8
  • Hello
  • Connection closed by foreign host.
  • ➜ http-upload-benchmark git:(master)

HTTP/1.1,默认连接保持了

  • ➜ http-upload-benchmark git:(master) telnet 127.0.0.1 8812
  • Trying 127.0.0.1...
  • Connected to localhost.
  • Escape character is '^]'.
  • GET / HTTP/1.1
  • Host: 127.0.0.1:8812
  • HTTP/1.1 200 OK
  • Date: Tue, 31 Dec 2019 04:02:11 GMT
  • Content-Length: 6
  • Content-Type: text/plain; charset=utf-8
  • Hello
  • GET / HTTP/1.1
  • Host: 127.0.0.1:8812
  • HTTP/1.1 200 OK
  • Date: Tue, 31 Dec 2019 04:02:12 GMT
  • Content-Length: 6
  • Content-Type: text/plain; charset=utf-8
  • Hello
  • ^[
  • HTTP/1.1 400 Bad Request
  • Content-Type: text/plain; charset=utf-8
  • Connection: close
  • 400 Bad RequestConnection closed by foreign host.

通过 netstat 查看端口监听情况

  • $ netstat -an | grep 8812
  • tcp4 0 0 127.0.0.1.8812 127.0.0.1.52493 ESTABLISHED
  • tcp4 0 0 127.0.0.1.52493 127.0.0.1.8812 ESTABLISHED
  • tcp46 0 0 *.8812 *.* LISTEN

HTTP 头中的 Keep-Alive

服务端可以这么告知客户端:Keep-Alive: timeout=15, max=100 15 秒内还可以再发 100 个请求,然后就会关闭连接了。

  1. The Keep-Alive header is a hop-by-hop header that provides information about a persistent connection. Both client and server are able to provide information independently. Hypertext Transfer Protocol (HTTP) Keep-Alive Header
  2. 客户端不能设置 keep-alive 的超时时间,这个由服务器端配置。The client cannot specify the timeout, it is the server configuration that determines the maximum timeout value. The extra Keep-Alive header can inform the client how long the server is willing to keep the connection open (timeout=N value) and how many requests you can do over the same connection (max=M) before the server will force a close of the connection.

抓个包玩玩

  • $ sudo tcpdump -i lo0 -s 0 -n tcp -c 1000 -w /tmp/p1.pcap
  • tcpdump: listening on lo0, link-type NULL (BSD loopback), capture size 262144 bytes
  • 1000 packets captured
  • 1032 packets received by filter
  • 0 packets dropped by kernel
  • ~

再用 wireshark 打开 p1.pcap,指定过滤条件 tcp.port == 8087,过滤 src 或 dst port 是 8087 的,就是我们感兴趣的tcp包

go-http-client 关闭 keep-alive 再抓包试试:

  • $ go-http-client -sleep 1s -keepalive=false
  • 2019/12/31 13:18:46 server http://127.0.1:8812
  • 2019/12/31 13:18:46 sleep 1s
  • 2019/12/31 13:18:46 keepalive false
  • 2019/12/31 13:18:46 retry mode false
  • 2019/12/31 13:18:46 dumpResponse HTTP/1.1 200 OK
  • Connection: close
  • Content-Length: 6
  • Content-Type: text/plain; charset=utf-8
  • Date: Tue, 31 Dec 2019 05:18:46 GMT
  • Hello
  • 2019/12/31 13:18:46 start sleep 1s
  • 2019/12/31 13:18:47 dumpResponse HTTP/1.1 200 OK
  • Connection: close
  • Content-Length: 6
  • Content-Type: text/plain; charset=utf-8
  • Date: Tue, 31 Dec 2019 05:18:47 GMT
  • Hello

从图中,就可以看出每次都是从头三次握手。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐