深入解析HTTP长连接原理

讲解长连接前,需要先了解短链接的原理,以及存在的问题

HTTP/1.0短链接
HTTP/1.0短链接机制

HTTP/1.0默认采用短链接,工作流程如下:

  1. **客户端发起连接请求:**客户端与服务端建立TCP连接(三次握手)

  2. **发起HTTP请求:**哭护短通过已建立的TCP连接发送HTTP请求报文

  3. **服务器处理请求:**服务器接收到请求,处理并生成HTTP响应报文

  4. **发起HTTP响应:**服务器通过同一个TCP连接发送响应报文给客户端

  5. 关闭TCP连接: 服务器或客户端在发送完响应或接受完响应后,立即关闭TCP连接(四次挥手)

  6. **重复上述步骤:**如果客户端需要获取更多资源,它必须重复上述所有步骤,重新建立TCP连接

短链接性能瓶颈
  1. TCP连接建立和关闭的开销

    • **三次握手:**每次建立TCP连接都需要客户端和服务端之间进行三次报文交互,一定程度上会带来网络消耗,同时连接的建立也需要消耗时间

    • **四次挥手:**同样,关闭TCP连接也需要多次报文交互,消耗时间

    • **慢启动:**TCP协议为避免网络阻塞,在建立连接初期会限制发送速率,导致一开始网络传输速率较慢,无法充分利用带宽

      慢启动原理详见另一篇博客:TCP如何实现流量控制-CSDN博客

  2. 服务器资源消耗

    • 每次建立和关闭连接,服务器都需要频繁进行套接字(socket)的创建和销毁,这会消耗大量CPU和内存资源
  3. 带宽利用率低下

    • 受连接频繁建立和关闭,以及慢启动的影响,TCP连接很难达到最大吞吐量,导致带宽利用率不高

这些问题最终会导致网页加载缓慢,用户体验差

HTTP/1.1长连接

长连接指在客户端和服务端建立一个TCP连接后,连接在完成一次请求后并不会立即关闭,而是保证开放状态,等待后续的HTTP请求。

长连接原理
  1. **客户端发起请求:**客户端与服务器建立TCP连接(三次握手)

  2. **发送HTTP请求:**客户端发送HTTP请求报文

  3. 服务器处理与响应: 服务器处理请求,发送HTTP响应报文

  4. **TCP连接保持开放:**服务器在发送完响应之后,不会立即关闭TCP连接,而是通过协商好的超时时间和最大请求数,保持连接开放

  5. **后续请求和复用连接:**客户端在需要获取其他资源时,可以通过这个已经建立的TCP连接发送新的HTTP请求,无需再进行TCP三次握手

  6. **连接关闭:**当客户端或服务端不再需要此链接(达到超时时间、客户端所有资源已获取,服务器资源限制等),会发起关闭TCP连接请求(四次挥手)

如何启用长连接

Connection:keep-alive

在HTTP/1.1中,长连接是默认的,客户端和服务器之间通过HTTP请求头 中包含的Connection:keep-alive来显式地协商是否保持连接,虽然HTTP/1.1规范中规定长连接是默认开启的,但为了兼容老旧客户端或代理,或者在某些特殊场景下,仍然会看到这个头部。

  • 客户端请求头

    复制代码
    GET /index.html HTTP/1.1
    Host: www.example.com
    Connection: keep-alive
  • 服务器响应头

    复制代码
    HTTP/1.1 200 OK
    Content-Type: text/html
    Content-Length: 1234
    Connection: keep-alive
    Keep-Alive: timeout=5, max=100

    服务器响应头中的Keep-Alive字段提供了详细的连接管理信息:

    • timeout:指定服务器保持连接的秒数,如果在指定时间内没有接收到新的请求,服务器将关闭连接

    • max:指定此次连接上允许发送的最大请求数量,到达此数量后,服务器关闭连接

如何关闭长连接
  1. 显式关闭

    • 客户端或服务器发送 Connection: close 头部

    • 任何一方都可以主动决定关闭连接

  2. 超时关闭

    服务器可以通过 Keep-Alive 头部设置超时时间和最大请求数,比如 `Keep-Alive: timeout=5, max=1000` 这表示连接在空闲5秒后会被关闭,或者最多处理1000个请求后关闭

  3. 错误或意外关闭

    • TCP连接本身出现错误、超时或中断

    • 一方意外崩溃

长连接优势
  1. 减少延迟:

    • 避免频繁三次握手和四次挥手:对于后续请求,不需要重新建立连接

    • **减少TCP慢启动影响:**TCP连接刚建立时,会有一个慢启动过程,限制发送速率,之后再慢慢提高发送速率,复用连接可以避免多次慢启动,保持较大的传输速率

  2. 降低服务器资源消耗:

    • 减少服务器频繁创建和销毁套接字的开销,降低服务器CPU和内存压力

    • TCP连接复用意味着服务器不需要进行频繁的状态切换,有助于服务器处理更多并发连接

  3. 提高带宽利用率:

    • 连接在较长时间内允许数据传输,能更好利用可用网络带宽
长连接局限性
  • 请求的队头阻塞: 在HTTP/1.1中,即使使用了长连接,客户端也必须严格按照请求的顺序发送。也就是说,在一个TCP连接上,客户端发送完第一个请求后,必须等待服务器的响应,才能发送第二个请求。如果第一个请求的处理时间较长,或者传输过程中某个响应丢失,那么后续的所有请求都将被阻塞

  • 管道化尝试与失败: HTTP/1.1引入了管道化机制,试图缓解队头阻塞。它允许客户端在收到前一个响应之前,就发送多个请求。服务器也会按顺序处理这些请求并发送响应。然而,管道化在实际应用中遇到了很多问题:

    • 服务器响应顺序必须与请求顺序一致: 如果服务器处理第一个请求耗时很长,即使它已经处理完了后续的请求,也必须等待第一个请求的响应发送完成后才能发送。这实际上是将队头阻塞从客户端请求端转移到了服务器响应端。

    • 代理和中间件的兼容性问题: 很多老的代理服务器和中间件不支持HTTP管道化,或者实现不完善,导致其普及度非常低。

    • 连接断开后的重试复杂性: 如果管道化发送了多个请求,但连接在某个响应返回前断开,客户端很难判断哪些请求已经成功,哪些需要重试,增加了实现的复杂性。

    • 由于这些限制,HTTP/1.1最终没有被广泛应用,对头阻塞问题,成为推动HTTP协议进一步演进的重要动力

相关推荐
g***B7382 小时前
Java 工程复杂性的真正来源:从语言设计到现代架构的全链路解析
java·人工智能·架构
期待のcode4 小时前
MyBatisX插件
java·数据库·后端·mybatis·springboot
醇氧6 小时前
【Windows】优雅启动:解析一个 Java 服务的后台启动脚本
java·开发语言·windows
sunxunyong7 小时前
doris运维命令
java·运维·数据库
菜鸟起航ing7 小时前
Spring AI 全方位指南:从基础入门到高级实战
java·人工智能·spring
古城小栈7 小时前
Docker 多阶段构建:Go_Java 镜像瘦身运动
java·docker·golang
华仔啊7 小时前
这 10 个 MySQL 高级用法,让你的代码又快又好看
后端·mysql
MapGIS技术支持7 小时前
MapGIS Objects Java计算一个三维点到平面的距离
java·开发语言·平面·制图·mapgis
Coder_Boy_7 小时前
业务导向型技术日志首日记录(业务中使用的技术栈)
java·驱动开发·微服务
码事漫谈7 小时前
国产时序数据库崛起:金仓凭什么在复杂场景中碾压InfluxDB
后端