Http的Keep-Alive和TCP的Keepalive有什么区别

部分参考:小林coding

  • HTTP的Keep-Alive,是由应用层(用户态)实现的,称为HTTP长连接
  • TCP的Keepalive,是有TCP层(内核态)实现的,称为TCP保活机制

HTTP的Keep-Alive

由于HTTP是基于TCP传输协议实现的,客户端与服务端要进行HTTP通信前,需要先建立TCP连接,然后客户端发送送HTTP请求,服务端收到后就返回响应。

浏览器输入一个URL后发生了什么?

短连接

就是每次请求都要经历:建立TCP->请求资源->响应资源->释放资源 的过程

长连接

HTTP的header头中的Connection:Keep-Alive,可以使用同一个TCP连接来发送和接收多个HTTP请求/应答,避免了连接建立和释放的开销

HTTP长连接的特点是:只要任意一端没有明确提出断开要求,则保持TCP的连接状态

如何使用HTTP的Keep-Alive功能

在HTTP 1.0中,长连接默认是关闭的,必须在请求头和响应头中都包含

ruby 复制代码
Connection:Keep-Alive

连接才不会中断

在HTTP 1.1中,默认开始Keep-Alive,所以如果要关闭Keep-Alive,需要在HTTP请求的包头中加入

arduino 复制代码
Connection:close

现在大多数浏览器都是默认使用HTTP/1.1,所以Keep-Alive是默认打开的,一旦客户端和服务端达成协议,那么长链接就建立好了

长连接的好处

HTTP长连接不仅减少了TCP资源的开销 ,而且这给HTTP流水线技术提供了可实现的基础

HTTP流水线

客户端可以先一次性发送多个请求,而在发送过程中,不需要先等待服务器的回应 ,以减少整体的响应时间。服务器按照顺序响应,先回应A请求,完成后再回应B请求。

但是,要等服务端响应完客户端第一批发送的请求后,客户端才能发出下一批请求,也就是说如果服务端响应第一批请求的过程中发生了阻塞,那么客户端就无法发出下一批的请求,此时就造成了「队头阻塞」的问题

keepalive_timeout参数

为了避免资源浪费的情况(在长连接中,客户端完成一个HTTP请求后,就不再发起新的请求,此时这个TCP连接一直占用的情况),web服务软件(比如nginx) 一帮都会提供keepalive_timeout参数,用来指定HTTP长连接的超时时间

若设置的HTTP长连接的超时时间是60s,web服务软件就会启动一个定时器,如果客户端在收到最后一个HTTP响应后,在60s内都没有再发起新的请求,定时器的时间一到,就会触发毁掉函数来释放该链接

TCP的Keepalive

TCP的Keepalive是TCP的保活机制,即如果两端的TCP连接一直没有数据交互,达到了触发TCP保活机制的条件(超过了设置的idle时间),那么内核里的TCP协议栈就会发送探测报文。

  • 如果对端程序是正常工作的,当TCP爆火的探测报文发送给对端,对端会正常响应,这样TCP保活时间会被重置,等待下一个TCP保活时间的到来
  • 如果对端主机奔溃,或对端由于其它原因导致报文不可达。当TCP保活的探测报文发送给对端后,没有响应,连续几次,达到保活探测次数后,TCP会报告该TCP连接已经死亡

keepAlive默认情况下是关闭的,如果应用程序想要使用TCP保活机制,需要通过socket接口设置SO_KEEPALIVE选项才能够生效(在Java中,应用程序一般通过设置 java.net.SocketOptions 来开启TCP连接的KeepAlive),如果没有设置,那么就无法使用TCP保活机制

如果HTTP没有设置Keep Alive,则关闭连接时,由于是两端主动发的FIN报文,因此即使TCP已经设置了KeepAlive,TCP连接也会被正常关闭

那么只开启HTTP长链接而不开启TCP长连接的话,HTTP的KeepAlive还起作用吗

此时HTTP的KeepAlive还会正常起作用,TCP连接还会复用,但是被复用的TCP连接出现故障的概率会高很多。 由于没有开启TCP的KeepAlive,防火墙或负载转发服务等中间设备可能因为该TCP空闲太长而悄悄关闭该链接,当HTTP从自己的连接池中拿出该TCP链接时,可能并不知道该链接被关闭,继续使用就会出现错误,所以一般来说,开启HTTP的KeepAlive的应用都会开启TCP的KeepAlive

mac中可以使用sysctl -A | grep net.inet.tcp来查看本机tcp的一些配置

通过man 4 tcp可以看到

默认的保活时间为 7200秒(两小时)

总结

1、HTTP的Keep-Alive也叫HTTP长连接,该功能是由应用程序实现的,在Header头中添加Connect:Keep-Alive,只有到了keepalive 头部规定的timeout,或者携带Connect:Close,才会关闭该TCP连接,可以使得用同一个TCP连接来发送和接收多个HTTP请求/应答,减少了HTTP端链接带来的多次TCP连接建立的释放和开销

2、TCP的Keepalive也叫TCP保活机制,该功能是由内核实现的,通过keep-alive报文来防止TCP连接被对端、防火墙或其他中间设备意外中断,和上层应用没有任何关系,只负责维护单个TCP连接的状态,其上层应用可以复用该TCP长链接,也可以关闭该TCP长连接

注意

和TCP连接不同,一个完整的HTTP事务,可能会横跨多个TCP连接,比如浏览器请求某个网页,请求可能先通过浏览器与负载均衡之间的TCP连接传输,再经过负载均衡到Nginx的TCP连接,最后在经过Nginx与业务Tomcat服务器的TCP连接,Tomcat处理完请求并返回响应后,响应沿着同样的TCP连接路线返回

因此HTTP的头部被分为了两部分:End-to-end 头部和 Hop-by-hop 头部,End-to-end 头部会被中间的代理原样转发,比如浏览器请求报文中的 host 头部,会被负载均衡、反向代理原样转发到Tomcat里,除非特意修改。而 Hop-by-hop 头部则只在当前TCP连接里有效,大部分头部都是 End-to-end ,但KeepAlive相关头部很明显和TCP连接有密切关系,因此是 Hop-by-hop 的

也就是说,即使浏览器请求时携带了 Connection: Keep-Alive ,也只表示浏览器到负载均衡之间是长连接,但负载均衡到nginx、nginx到tomcat是否是长连接则需要具体分析。比如Nginx虽然支持HTTP的Keep-Alive,但由Nginx发起的HTTP请求默认不是长连接,此时如果需要的话,我们可能要手动设置一下nginx和tomcat的TCP长链接

相关推荐
呆呆的心2 小时前
JavaScript 深入理解闭包与柯里化:从原理到实践 🚀
javascript·面试
请你吃div2 小时前
JavaScript 实用函数大全(超实用)
前端·javascript·面试
Baihai_IDP2 小时前
vec2text 技术已开源!一定条件下,文本嵌入向量可“近乎完美地”还原
人工智能·面试·llm
知其然亦知其所以然3 小时前
JVM社招面试题:队列和栈是什么?有什么区别?我在面试现场讲了个故事…
java·后端·面试
前端小巷子3 小时前
跨域问题解决方案:CORS(跨域资源共享)
前端·网络协议·面试
顾林海3 小时前
Android ClassLoader加载机制详解
android·面试·源码
FairyDiana4 小时前
【JavaScript】一篇文章,带你拿捏JS中的类型判断
javascript·面试
然我4 小时前
打工人必看!Flex “驯服” 前端面试,让代码像整理工位一样顺
前端·面试·html
崎岖Qiu5 小时前
【Spring篇08】:理解自动装配,从spring.factories到.imports剖析
java·spring boot·后端·spring·面试·java-ee
心平愈三千疾11 小时前
通俗理解JVM细节-面试篇
java·jvm·数据库·面试