被抛弃的八股文之keep-alive

205 阅读5分钟

还记得在我毕业面试时,经常看到碰到的面试题中都有着TCP中的keep-alive和HTTP中的keep-alive有什么区别。但是现在的八股文中已经再也见不到了(燕子,我们还会再见吗)

话说回来,这两个不同的协议中,keep-alive分别代表什么意思呢?

TCP中的keep-alive

我们先来看看TCP协议的报文格式长什么样的先,具体格式文档:datatracker.ietf.org/doc/html/rf…

能看到,在报文格式中并没有keep-alive这个属性或参数。但是在文档中数据传输那一节中,说明了keep-alive的作用:

TCP中的keep-alive是操作系统对于TCP协议的一种附加功能,用于检测本条TCP连接的状态。但这个附件功能并不是TCP协议中强制要求实现的部分,而且keep-alive功能在TCP中是默认关闭的。

keep-alive会在TCP连接空闲时间到达某个阈值时,开启keep-alive一方会向另一方发送一个空的数据包,如果另一方在多次发送空数据包均无响应后,TCP则会通知应用层连接失效。

简单来说,TCP中的keep-alive是一种由操作系统实现连接检测机制,但该机制检测出来的异常连接并非一定准确,在TCP文档中着重介绍了这一点。

简单示例

在Windows中变更keep-alive探测时间需要修改注册表,路径:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

对应有几个参数:

参数描述默认值单位
KeepAliveTimeTCP空闲触发时间7200000 2小时毫秒
KeepAliveInterval没有收到探测包响应时,重新发送keep-alive探测包的间隔时间1000毫秒
TcpMaxDataRetransmissions重试次数5次数

为了便于测试,我将触发时间缩短成50秒。

需要显示声明使用keep-alive,否则该功能不会开启。

测试服务端:

public class ServerMain {

    public static void main(String[] args) throws IOException, InterruptedException {
        try (ServerSocket serverSocket = new ServerSocket(18888)) {
            Socket accept = serverSocket.accept();
            accept.setKeepAlive(true);
            System.out.println("客户端已连接!");
            Thread.sleep(1000000000L);
        }
    }
}

测试客户端:

public class ClientMain {

    public static void main(String[] args) throws IOException, InterruptedException {
        Socket socket = new Socket("127.0.0.1", 18888);
        System.out.println("client connected");
        Thread.sleep(10 * 60 * 1000);
    }
}

使用Wireshark进行抓包后,可以看到在TCP连接后的50秒后,发送了keep-alive的探测包,并且每隔50秒都会进行发送。

这就是TCP中keep-alive的作用,监测并维持空闲TCP连接。

HTTP中的keep-alive

在HTTP1.0中就已经有keep-alive的请求头了,但这个请求头只是部分服务器支持,并且也不在协议的标准之内。于是,在HTTP1.1中则新开了一个章节,着重说明了keep-alive请求头的作用。

datatracker.ietf.org/doc/html/rf…

在协议中,说明了当Connection请求头为keep-alive时,客户端以及服务器都需要复用本条TCP连接。


浏览器中无法显式关闭keep-alive(想关也不给你关😢),只能在服务器中通过控制keep-alive参数进行关闭,例如tomcat的maxKeepAliveRequests。关闭之后,可以从控制台中,看到关闭前,只需要第一次请求需要连接服务器,其余请求无需再次连接服务器,正是连接复用的作用。

关闭之后,每次请求都需要跟服务器进行连接,虽然时间也不长,但是也会消耗服务器资源的。在响应头中也能看到Connectionclose

总结

差异点TCPHTTP
定义操作系统在TCP协议上添加的连接检测机制,用于检测连接状态HTTP请求头中的字段,表示复用同一条TCP连接
功能检测TCP连接是否仍然有效,通过空闲时发送探测包来验证连接状态允许在同一TCP连接上发送多个HTTP请求,减少连接建立的开销
是否为协议标准不是TCP协议的强制标准,且默认关闭协议的标准,默认开启

题外话-时代的落幕

1996年5月HTTP1.0协议正式发布,第二年HTTP1.1随之发布。但是HTTP2.0却是在2015年5月才正式发布,并且2.0还是基于Google2009年11月份发布的实验性SPDY协议**。**

那为什么Google要发布SPDY协议呢,归根结底,还是由于HTTP1.1在当时已经不满足于愈发发展的互联网了。最经典的例子,HTTP1.1在请求时会阻塞当前TCP连接,在请求数少时还能接受,当请求数高的时候,延迟就十分严重了。

现在我们在请求一个网站的时候,按下F12可以看到在请求的协议中,大部分都已经是HTTP2了。协议的升级不仅使我们访问网页的速度变快,同时也说明了时代的变革了。

SPDY协议的推出:blog.chromium.org/2009/11/2x-…

使用 SPDY 和 HTTP/2 提高 Web 速度:blog.chromium.org/2013/11/mak…

Chromium优先先使用HTTP2.0进行连接:blog.chromium.org/2015/02/hel…


TCP虽然没有像HTTP协议一样发布了多个版本,但是也一直进行着多次改进。传输层协议也推出很多新的协议,最出名的就是HTTP3使用的GoogleQUIC协议,以及特斯拉最新发布的TTPOE

TTPOE:www.servethehome.com/tesla-dojo-…