| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> HTTP 长连接原理 -> 正文阅读 |
|
[网络协议]HTTP 长连接原理 |
目录 1. HTTP长连接原理????????HTTP属于 TCP/IP模型中的应用层协议,HTTP长连接和HTTP短连接,指的是传输层的TCP连接是否被多次使用。 ????????一般来说,用户通过浏览器输入URL回车,浏览器会通过DNS解析域名得到服务器的IP地址,然后通过解析出来的 IP和URL中的端口(默认为 80)发起建立 TCP连接请求,通过三次握手之后,建立TCP连接。 1.1 HTTP长连接和短连接????????默认情况下,HTTP的1.0版本协议中,HTTP在每次请求结束后都会主动释放TCP连 接,因此HTTP连接是一种“短连接”。客户端与服务端通过HTTP短连接的交互过程,具体如下图所示。 ????????在高并发场景使用HTTP“短连接”通信,会出现两个问题: ????????(1)性能较差:传输层的TCP连接不会复用,每一次请求,都需要建立和拆除一次 TCP连接,也即是说,每次请求均需要TCP三次握手建立连接,TCP四次挥手关闭连接,性 能较差。 ????????(2)很容易出现端口被占满:在主动断开方,系统会出现大量的TIME_WAIT状态的 TCP连接,只有等2个MSL后,TCP连接才会进行关闭掉,在高并发场景中,如果服务器主动断开连接,则很容易发生端口耗尽。当然,如果连接被设置了SO_RESUSEADDR特性,其端口可能被其他连接复用,尽管如此,还是会存在不少的约束条件影响到端口复用。出于以上两个原因,在高并发场景使用HTTP“短连接”进行通信肯定是不行的。 ????????HTTP长连接,也叫HTTP持久连接,指的是TCP连接建立后,该传输层连接不再进行释放,供应用层反复使用。客户端与服务端通过HTTP长连接的交互过程,具体如下图所示: ???????? ????????HTTP长连接的特点是: ????????(1)性能较高,不需要重复建立TCP连接或者关闭TCP连接; ????????(2)TCP数据传输连接基本上不会出现CLOSE_WAIT和TIME_WAIT的问题,系统资源的使用效率会大大提升。 HTTP长连接也有缺点:一般需要一个连接池来对可供复用的TCP长连接进行管理和监测。常见的数据库连接池、HTTP连接池,本质上都属于TCP连接池。 1.2 HTTP/1.1 协议支持的长连接????????HTTP/1.1默认使用长连接而不是短连接,除非显式关闭TCP连接。如果要显式关闭连 接,需要在HTTP报文首部加上“Connection:Close”请求头,也就是说在HTTP/1.1协议 中,默认情况下,所有的TCP连接都可以进行复用的。 ????????当然,不发送“Connection:Close”请求头,不意味着服务器承诺TCP连接永远保持打开。空闲的TCP连接也可以被客户端与服务端关闭。 2. 服务端HTTP长连接技术????????本节对主流的反向代理服务器Nginx和应用服务器Tomcat的服务端长连接配置进行介绍。 2.1 Tomcat的长连接配置????????生产环境所用的Java应用服务器不一定是Tomcat,可能是JBoss、Jetty或者其他的应用 服务器。无论使用哪一种服务器,其HTTP长连接配置的原理是类似的,所以,这里以 Tomcat为例进行应用服务器的长连接配置介绍。服务器端Tomcat的长连接配置,主要分为两种场景: ????????(1)独立部署的Tomcat ????????在传统的Nginx+Tomcat架构的Web应用中,一般使用独立部署的Tomcat作为Web服务器。 ????????(2)内嵌部署的Tomcat ????????在目前主流的Spring Boot应用,一般使用内嵌的Tomcat作为Web服务器。 ????????以上两种细分场景的Tomcat使用,具体如下图所示: 图:Tomcat使用的两种细分场景 ????????1. 独立部署 Tomcat 的长连接配置 ????????针对于细分场景一中的独立部署Tomcat,其长连接配置是通过修改Tomcat配置文件中 Connector(连接器)的配置完成的。一个使用HTTP长连接的Connector连接器的配置示例大致如下(Tomcat版本假定8.0或以上):
????????对以上配置示例中用到的三个长连接配置选项,介绍如下: ????????(1)keepAliveTimeout ????????此选项为TCP连接保持时长,单位为毫秒。表示在下次请求过来之前,该连接将被Tomcat保持多久。在keepAliveTimeout时间范围内,假如客户端不断有新的请求过来,则该连接将一直被保持。KeepAliveTimeout选项决定一个不活跃的连接能保持多少时间。 ????????(2)maxKeepAliveRequests ????????此选项表示长连接最大支持的请求数。超过该请求数的连接将被关闭,关闭的时候 Tomcat会返回一个带“Connection: close”响应头的给客户端。 当maxKeepAliveRequests的值为-1时,表示没有最大请求数限制;如果其值被设置为 1,将会禁用掉HTTP长连接。 ????????默认情况下Tomcat是使用长连接的,如果要关闭长连接,只要将maxKeepAliveRequests设置为1即可。 ????????(3)maxConnections ????????Tomcat在任意时刻能接收和处理的最大连接数。如果其值被设置为-1,则连接数不受限制。由于Linux的内核默认限制了单进程最大打开文件句柄数为1024,因此,如果此配置 项的值超过1024,则相应的需要对Linux系统的单进程最大打开文件句柄数限制进行修改。 ????????以上是对Tomcat的HTTP长连接配置选项的介绍。总的来说,使用长连接能提高服务性 能,不过,如果使用不当,也会带来一些不利的结果。 ????????使用长连接意味着,一个TCP连接在当前请求结束后,如果没有新的请求到来, Socket连接不会立马释放,而是等keepAliveTimeout到期之后才被释放,如果一个高负载的 Tomcat服务器建立的很多长连接,将无法继续建立新的连接,无法为新的客户端提供服 务。所以,对于Tomcat长连接的配置需要慎重,错误的参数可能导致严重的性能问题,需要根据具体的负载,配置合适的KeepAliveTimeout和MaxKeepAliveRequests的选项值。 ????????2. 内嵌式部署 Tomcat 的长连接配置 ????????针对于细分场景二中的内嵌式Tomcat,其长连接配置可以通过一个自动配置类完成。 在自动配置类中,可以配置一个TomcatServletWebServerFactory容器工厂Bean实例, SpringBoot将通过该工厂实例,在运行时获取内嵌式Tomcat容器实例。在容器工厂配置代 码中,可以对Tomcat的Connector的三个长连接相关属性进行具体的配置。 ????????一段简单的定制化TomcatServletWebServerFactory容器工厂的配置代码大致如下:
????????以上示例是SpringBoot2.0.8中的内嵌式Tomcat长连接配置,具体的三个配置选项的语义和独立Tomcat的配置是相同的,仅仅是形式上的不同。 2.2 Nginx承担服务端角色时的长连接设置????????无论在传统的Nginx+Tomcat架构中,还是在目前主流的Nginx+SpringCloud架构中,反 向代理Nginx都承担了两种角色:对于下游客户端来说Nginx承担了服务端角色,对于上游 的WEB服务来说Nginx承担了客户端角色。Nginx承担的两种角色,具体如下图所示: ????????Nginx承担服务端角色时的长连接,主要通过keepalive_timeout和keepalive_requests两个指令完成相关设置。一段简单的Nginx承担服务端角色时的长连接配置代码,大致如下
????????对以上配置代码中涉及的两个长连接相关指令,具体介绍如下: ????????(1) keepalive_requests ????????此指令设置同一个长连接可以处理的最大请求数,请求数超过此值,长连接将关闭。 其格式如下: ????????语法:keepalive_requests number ????????默认值:keepalive_requests 100 ????????上下文:http、server、location ????????keepalive_requests指令用于设置一个长连接上可以服务的最大请求数量,当最大请求 数量达到时,长连接将被关闭,Nginx中其默认值是100。一个长连接建立之后,Nginx就会为这个连接设置一个计数器,记录这个长连接上已经接收并处理的客户端请求的数量。如果达到这个参数设置的最大值时,则Nginx会强行关闭这个长连接,逼迫客户端不得不重新建立新的长连接。 ????????(2)keepalive_timeout ????????此指令用于设置长连接的空闲保持时长,表示在下次请求过来之前,该连接将被Nginx 保持多久。在keepalive_timeout时间范围内,假如客户端不断有新的请求过来,则该连接将 一直被保持。 ????????语法:keepalive_timeout timeout [header_timeout]; ????????默认值:keepalive_timeout 60s; ????????上下文:http、server、location ????????keepalive_timeout指令的第一个参数,用于设置客户端的长连接在服务器端保持的最长 时间(默认60秒),如果值设置为0,会禁用HTTP长连接。对于一些并发量较高的内部服务器通讯的场景,其值可以适当加大,比如增加到120秒甚至300秒。 ????????keepalive_timeout指令的第二个参数,是一个可选参数,其作用为HTTP响应报文增加 一个“Keep-Alive: timeout=time”头部选项,用于告知客户端长连接的保持时间,通常可 以不用设置。该响应头可以被Mozilla 浏览器识别和处理,Mozilla浏览器会在timeout空闲 时间之后,关闭TCP长连接;而MSIE浏览器则在大约60秒后会关闭长连接。 2.3 服务端长连接设置的注意事项????????在进行服务端长连接设置时,keepalive_timeout和keepalive_requests的值,并不是越大越好,而是要根据具体场景而定。 ????????场景一:单个客户端的 HTTP 请求数较少时 ????????比如在客户端是普通用户时,客户端是网页浏览器,当用户通过浏览器在访问服务端 时,其单个用户的请求数是比较有限的,1分钟之内所发出的请求数之多在百位数左右。在这种场景下,如果Nginx的服务端长连接设置如下:
????????上述设置会导致大量的长连接由于请求数达不到1000,一直在空闲等待,需要等到65秒结束 之后才被关闭,造成服务器资源的浪费。所以,需要减少长连接最大处理请求数和长连接 保持时长,初步优化后的配置大致如下:
?????????但是,如果配置得极端,将长连接最大处理请求数减小得太多,可能会导致另外的问 题。比如,将长连接最大处理请求数减到10,其配置如下:
????????当QPS=10000时,假定一共100个用户,单个客户端每秒发出100个请求。由于以上配 置中每个连接只能最多处理10次请求,单个客户端每秒发出100个请求相当于每个用户需要10个连接,在总体100个用户的情况下,意味着平均每秒钟就会有1000个长连接将被Nginx主动关闭。在这个情况下,了解前面介绍的TCP连接四次挥手知识的读者就会知道,服务端Nginx就会有大量的TIME_WAIT的Socket连接。 ????????所以,keepalive_requests的值,不能比单个客户端在keepalive_timeout时间范围的实际请求数少太多,如果少太多,在QPS较高的场景,会出现大量连接被服务端主动关闭而出现大量TIME_WAIT连接。 ????????当然,keepalive_requests的值,也不能比单个客户端在keepalive_timeout时间范围实际请求数多太多,这样会导致大量的TCP长连接出现空闲等待。 ????????总体而言,keepalive_requests的值与单客户端在keepalive_timeout时间范围的实际请求 数量,要做到基本的匹配。 ????????场景二:单个客户端的请求数较多时 ????????比如在客户端不是普通用户,而是下游的代理服务器。在这种场景下,客户端数量是 很少的,而单个客户端与服务器之间的请求数是非常多的。 ????????这种场景的设置比较简单,可以尽可能的对长连接进行复用,keepalive_requests值可 以设置偏大,示例的配置如下:
????????当然,在此场景中,选项keepalive_timeout可以配置一个较大的值。但是,对于Nginx 来说,不能对单个连接的处理请求数不做限制,必须定期关闭连接,才能释放每个连接的所分配的内存。由于使用过大请求数可能会导致内存占用过度,因此不建议为 keepalive_requests设置太大的值,当然更不能不做keepalive_requests设置。 ????????无论是Nginx、Tomcat还是其他的服务器,有关服务端长连接的设置,其原理是类似 的,仅仅是具体参数的命名规则不同,或者是配置形式稍微有点不同。 参考资料:《Java高并发核心编程 卷1:NIO、Netty、Redis、ZooKeeper》 |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/29 11:58:18- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |