您当前的位置:首页 > 计算机 > 服务器 > 网络服务

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

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

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

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

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