HTTP长连接实现原理

1. HTTP长连接和短连接的定义

  • HTTP长连接
    • 浏览器向服务器进行一次HTTP会话访问后,并不会直接关闭这个连接,而是会默认保持一段时间,那么下一次浏览器继续访问的时候就会再次利用到这个连接。
    • 在HTTP/1.1版本中,默认的连接都是长连接,我们可以通过Connection: keep-alive字段进行指定。
  • HTTP短连接
    • 浏览器向服务器每进行一次HTTP操作都要建立一个新的连接。
    • 在HTTP/1.0版本中默认是短链接

2.  HTTP长连接本质

HTTP协议本质是OSI七层参考模型中的应用层协议,而网络进行通信的时候都是通过上层协议封装头部后作为下层协议的数据部分进行封装的,而实际中我们经常接触的是TCP/IP协议簇,也就是传输层利用TCP协议和网络层利用IP协议。因此HTTP协议的长连接本质上就是TCP的长连接。

2.1 TCP建立连接回顾

上面我们提到了TCP,那么回顾一下,通信双方在进行通信的时候就是要通过“三次握手“来建立连接的,握手的过程大致如图1所示:

8a617202309281028326356.png

那么通过上图我们就可以清楚的看到,服务器和客户端都建立了一个TCB传输控制块,这里就是我们进行socket编程的时候管理连接的地方,在这里我们先标记这个TCB,在后续的文章,我们会详细介绍在Linux中TCB是怎么样管理连接的。

2.2  TCP释放连接回顾

在回顾了TCP连接建立之后,我们不妨再来看看TCP四次挥手,如图2所示:

9b86f20230928102908677.png

TCP连接的释放是看通信双方谁是主动关闭的一方,谁是被动关闭的一方来决定各自状态的,具体的内容大家依然可以参考《TCP/IP详解》,这里就不再赘述了。

2.3 TCP长连接

在建立了TCP连接之后,这也就到了这篇文章中比较核心的问题,就是说TCP连接建立之后,并不会在完成一次数据通信后就关闭连接,而是要保持一段时间,那么这个时间是怎么样保证,又是谁保证的呢?

2.3.1 TCP保活机制
  • 为什么要有保活机制?
    • 第一点自然是我们这篇文章的主题,通过保活机制,我们可以保证通讯双方的连接不被释放掉
    • 第二点就是在另一些情况下,如果客户端或者服务器发生了错误或者宕机,那么就可以依靠这种保活机制探测出网络通信出现了问题,进而可以释放掉这种错误连接。
  • 保活机制

首先保活机制的工作原理就是,通过在服务器端设置一个保活定时器,当定时器开始工作后就定时的向网络通信的另一端发出保活探测的TCP报文,如果接收到了ACK报文,那么就证明对方存活,可以继续保有连接;否则就证明网络存在故障。

上面只是在原理层面简单的介绍,根据文献[1],我们可以了解到详细的内容:

如果一个给定的连接在两个小时之内没有任何动作,则服务器就向客户发送一个探查报文段。客户主机必须处于以下 4个状态之一。

状态1:客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常工作的。服务器在两小时以后将保活定时器复位。如果在两个小时定时器到时间之前有应用程序的通信量通过此连接,则定时器在交换数据后的未来2小时再复位。

状态2:客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务器将不能够收到对探查的响应,并在75秒后超时。服务器总共发送10个这样的探查,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。

状态3:客户主机崩溃并已经重新启动。这时服务器将收到一个对其保活探查的响应,但是这个响应是一个复位,使得服务器终止这个连接。

状态4:客户主机正常运行,但是从服务器不可达。这与状态2相同,因为TCP不能够区分状态4与状态2之间的区别,它所能发现的就是没有收到探查的响应。

  • 实际应用

那么我们在了解了理论上TCP长连接是通过保活机制来实现的,但是保活机制并不是RFC规定的TCP协议的内容,因此有时候在不支持保活机制的机器上,往往我们也需要先看一下内核层面是否支持,如果不支持需要在应用层自己去实现这个功能。

在这里我们就来看一下Linux相关的TCP保活参数

tcp_keepalive_time,单位:秒,表示发送的探测报文之前的连接空闲时间,默认是7200s。

tcp_keepalive_intvl,单位:秒,表示两次探测报文之间的间隔时间,默认是75s

tcp_keepalive_probes,单位,秒,表示探测的次数,默认是9

接下来如果我们需要在应用层写自己的心跳机制,那么就需要其他方面的一些内容了。

2.3.2 TCP长连接和短链接比较
  • TCP短链接
    • 优点
      • 短链接不占服务器的内存,服务器能处理的连接数量会比较多
    • 缺点
      • 在有实际的资源要进行数据通信的时候才建立连接,那么在客户端发送完数据释放连接之后当服务器有向客户端发送数据时就不能做到发送消息的实时性。
      • 频繁地建立连接、释放连接会耗费大量的CPU和网络带宽资源。
  • TCP长连接[2]
    • 优点
      • 通信双方因为在保活机制的保证下可以保证数据收发的实时性
    • 缺点
      • 因为服务器需要一直保存和客户端的这条链接,因为是有状态的,那么在大量并发连接请求过来时,系统资源可能就不够了。
    • 什么时候需要长连接
      • 服务器需要主动发送资源给客户端时
      • 客户端和服务器通信很频繁时
      • 客户端宕机或者掉线时需要服务器做一些处理时
    • TCP长连接设计时需要考虑的问题
      • 默认的keep-alive时间比较长,一般的业务可能不需要这么久的时间
      • socket proxy会让TCP的保活失效:多有的proxy应用只能转发TCP的应用数据,不能转发TCP协议内部的包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/130154.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue-7-vuex

一、Vuex 概述 目标:明确Vuex是什么,应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具,状态就是数据。 大白话:Vuex 是一个插件,可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如:购…

Jmeter 链接MySQL测试

1.环境部署 1.1官网下载MySQL Connector https://dev.mysql.com/downloads/connector/j/ 1.2 解压后,将jar放到jmeter/lib目录下 1.3 在测试计划中添加引用 2.脚本设置 2.1设置JDBC Connection Configuration 先添加一个setUp线程中,在setUp中添加“…

MongoDB 笔记

1 insert 、create、save区别 insert: 主键不存在则正常插入;主键已存在,抛出DuplicateKeyException 异常 save: 主键不存在则正常插入;主键已存在则更新 insertMany:批量插入,等同于批量执行 insert create&#x…

黑马点评-05缓存穿透问题及其解决方案,缓存空字符串或使用布隆过滤器

缓存穿透问题(缓存空) 缓存穿透的解决方案 缓存穿透(数据穿透缓存直击数据库): 缓存穿透是指客户端请求访问缓存中和数据库中都不存在的数据,此时缓存永远不会生效并且用户的请求都会打到数据库 数据库能够承载的并发不如Redis这么高,如果大量的请求同时访问这种…

vue使用localstorage超出限制解决方法

最近在项目中,遇到一个报错,QuotaExceededError: The quota has been exceeded。如图: 搜索了一下,结合项目代码,得到的结论是localStorage超出5M限制了,项目中使用了vuex-persistedstate插件,…

Redis-双写一致性

双写一致性 双写一致性解决方案延迟双删(有脏数据的风险)分布式锁(强一致性,性能比较低)异步通知(保证数据的最终一致性,高并发情况下会出现短暂的不一致情况) 双写一致性 当修改了数…

10_10C++

X-mid #include <iostream> using namespace std; class Kun {//算术运算符friend const Kun operator(const Kun &k1,const Kun &k2);friend const Kun operator-(const Kun &k1,const Kun &k2);friend const Kun operator*(const Kun &k1,const Ku…

[nltk_data] Error loading stopwords: <urlopen error [WinError 10054]

报错提示&#xff1a; >>> import nltk >>> nltk.download(stopwords) 按照提示执行后 [nltk_data] Error loading stopwords: <urlopen error [WinError 10054] 找到路径C:\\Users\\EDY\\nltk_data&#xff0c;如果没有nltk_data文件夹&#xff0c;在…

【算法|双指针系列No.4】leetcode11. 盛最多水的容器

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

解决:yarn 无法加载文件 “C:\Users\XXXXX\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本“ 的问题

1、问题描述&#xff1a; 报错的整体代码为&#xff1a; yarn : 无法加载文件 C:\Users\admin\AppData\Roaming\npm\yarn.ps1&#xff0c;因为在此系统上禁止运行脚本 // 整体的报错代码为 &#xff1a; yarn : 无法加载文件 C:\Users\admin\AppData\Roaming\npm\yarn.ps1&…

vue3学习(一)---新特性

文章目录 vue3和vue2的区别重写双向数据绑定优化Vdom性能瓶颈patch flag 优化静态树 FragmentTree shaking组合式API写法 vue3和vue2的区别 重写双向数据绑定 vue2 基于Object.defineProperty()实现vue3 基于Proxy proxy与Object.defineProperty(obj, prop, desc)方式相比有以…

[idekCTF 2022]Paywall - LFI+伪协议+filter_chain

[idekCTF 2022]Paywall 一、解题流程&#xff08;一&#xff09;、分析&#xff08;二&#xff09;、解题 二、思考总结 一、解题流程 &#xff08;一&#xff09;、分析 点击source可以看到源码&#xff0c;其中关键部分&#xff1a;if (isset($_GET[p])) {$article_content…