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

相关推荐
怕什么真理无穷3 小时前
C++面试4-线程同步
java·c++·面试
拉不动的猪5 小时前
# 关于初学者对于JS异步编程十大误区
前端·javascript·面试
熊猫钓鱼>_>7 小时前
Java面向对象核心面试技术考点深度解析
java·开发语言·面试·面向对象··class·oop
进击的野人10 小时前
CSS选择器与层叠机制
css·面试
T___T12 小时前
全方位解释 JavaScript 执行机制(从底层到实战)
前端·面试
9号达人12 小时前
普通公司对账系统的现实困境与解决方案
java·后端·面试
勤劳打代码13 小时前
条分缕析 —— 通过 Demo 深入浅出 Provider 原理
flutter·面试·dart
努力学算法的蒟蒻13 小时前
day10(11.7)——leetcode面试经典150
面试
进击的野人14 小时前
JavaScript 中的数组映射方法与面向对象特性深度解析
javascript·面试
南山安14 小时前
以腾讯面试题深度剖析JavaScript:从数组map方法到面向对象本质
javascript·面试