IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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长连接原理

1.1 HTTP长连接和短连接

1.2 HTTP/1.1 协议支持的长连接

2. 服务端HTTP长连接技术

2.1 Tomcat的长连接配置

2.2 Nginx承担服务端角色时的长连接设置

2.3 服务端长连接设置的注意事项


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或以上):

<Connector port="8080" redirectPort="8443"
    protocol="org.apache.coyote.http11.Http11NioProtocol"
    connectionTimeout="20000"
    URIEncoding="UTF-8"
    keepAliveTimeout="15000"
    maxKeepAliveRequests="-1"
    maxConnections="3000"
    maxThreads="1000"
    maxIdleTime="300000"
   minSpareThreads="200"
   acceptCount=”100″
   enableLookups="false" />

????????对以上配置示例中用到的三个长连接配置选项,介绍如下:

????????(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容器工厂的配置代码大致如下:

package com.crazymaker.springcloud.standard.config;

//....省略 import
@Configuration
@ConditionalOnClass({Connector.class})
public class TomcatConfig<HttpConnectionProperties> {
    @Autowired
    private HttpConnectionProperties httpConnectionProperties;

    @Bean
    public TomcatServletWebServerFactory
    createEmbeddedServletContainerFactory() {
        TomcatServletWebServerFactory tomcatFactory =
                new TomcatServletWebServerFactory();

        //增加连接器的定制配置
        tomcatFactory.addConnectorCustomizers(connector -> {
            Http11NioProtocol protocol =
                    (Http11NioProtocol) connector.getProtocolHandler();
            // 定制 keepAliveTimeout,确定下次请求过来之前 Socket 连接保持多久
            // 设置 600 秒内没有请求则服务端自动断开 socket 连接
            protocol.setKeepAliveTimeout(600000);
            // 当客户端发送超过 10000 个请求,强制关闭掉 socket 连接
            protocol.setMaxKeepAliveRequests(1000);

            //设置最大连接数
            protocol.setMaxConnections(3000);
            //...省略其他配置
        });
        return tomcatFactory;
    }
}

????????以上示例是SpringBoot2.0.8中的内嵌式Tomcat长连接配置,具体的三个配置选项的语义和独立Tomcat的配置是相同的,仅仅是形式上的不同。

2.2 Nginx承担服务端角色时的长连接设置

????????无论在传统的Nginx+Tomcat架构中,还是在目前主流的Nginx+SpringCloud架构中,反 向代理Nginx都承担了两种角色:对于下游客户端来说Nginx承担了服务端角色,对于上游 的WEB服务来说Nginx承担了客户端角色。Nginx承担的两种角色,具体如下图所示:

????????Nginx承担服务端角色时的长连接,主要通过keepalive_timeout和keepalive_requests两个指令完成相关设置。一段简单的Nginx承担服务端角色时的长连接配置代码,大致如下

#...
http{
    include mime.types;
    default_type application/octet-stream;
    #长连接保持时长
    keepalive_timeout 65s;
    #长连接最大处理请求数 
    keepalive_requests 1000;
    #...
    server{
        listen 80;
        server_name openresty localhost;
        #长连接保持时长
        keepalive_timeout 10s;
        #长连接最大处理请求数
        keepalive_requests 10;
        location/{  
            root html;
            index index.html index.htm;
        }
        #...
    }
}

????????对以上配置代码中涉及的两个长连接相关指令,具体介绍如下:

????????(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的服务端长连接设置如下:

#长连接保持时长
keepalive_timeout 65s;
#长连接最大处理请求数
keepalive_requests 1000;

????????上述设置会导致大量的长连接由于请求数达不到1000,一直在空闲等待,需要等到65秒结束 之后才被关闭,造成服务器资源的浪费。所以,需要减少长连接最大处理请求数和长连接 保持时长,初步优化后的配置大致如下:

#长连接保持时长
keepalive_timeout 10s;
#长连接最大处理请求数
keepalive_requests 100;

?????????但是,如果配置得极端,将长连接最大处理请求数减小得太多,可能会导致另外的问 题。比如,将长连接最大处理请求数减到10,其配置如下:

#长连接保持时长
keepalive_timeout 10s;
#长连接最大处理请求数
keepalive_requests 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 65s;
#长连接最大处理请求数
keepalive_requests 100000;

????????当然,在此场景中,选项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地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-05-24 18:32:39  更:2022-05-24 18:32:45 
 
开发: 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年11日历 -2024/11/26 1:50:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码