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长链接

相关推荐
用户3157476081351 小时前
成为程序员的必经之路” Git “,你学会了吗?
面试·github·全栈
布川ku子2 小时前
[2024最新] java八股文实用版(附带原理)---Mysql篇
java·mysql·面试
有趣的杰克9 小时前
移动端【01】面试系统的MVVM重构实践
面试·职场和发展·重构
saturday-yh16 小时前
性能优化、安全
前端·面试·性能优化
前进别停留1 天前
206面试题(71~80)
面试
不二人生1 天前
SQL面试题——飞猪SQL面试 重点用户
数据库·sql·面试
dream_ready1 天前
四万字长文SpringBoot、Spring、SpringMVC等相关面试题(注:该篇博客将会持续维护 最新维护时间:2024年11月12日)
java·spring boot·后端·spring·面试·1024程序员节
知否&知否1 天前
Kafka面试夺命连环30问(一)
分布式·面试·kafka
百晓生说测试1 天前
15:00面试,15:08就出来了,问的问题有点变态。。。
自动化测试·软件测试·功能测试·程序人生·面试·职场和发展
威哥爱编程2 天前
Java灵魂拷问13个为什么,你都会哪些?
java·面试·javaee