http中的长连接和短连接你真的了解吗?

做web开发的老铁应该都知道http协议,它是前后端通信中非常常用的一种通信协议,HTTP(HyperText Transfer Protocol)即超文本传输协议,是互联网上应用最为广泛的一种网络协议。

HTTP协议是一个基于请求-响应模型的协议,客户端(浏览器、移动客户端等)发起请求,服务端接收请求后进行处理并返回响应。

在HTTP协议中,有两种连接方式:长连接和短连接,它们主要区别在于连接的持续时间和资源利用率。

长/短 连接到底是啥

长连接,又称持久连接(Persistent Connection),是指在一个TCP连接上可以连续发送多个请求和响应报文,在通信双方的任何一方主动关闭连接之前,连接一直保持。长连接在HTTP/1.1中是默认启用的,通过设置请求头部的Connection字段为Keep-Alive来实现,

短连接,又称非持久连接(Non-Persistent Connection),是指客户端与服务器每进行一次HTTP操作,就建立一次连接,任务结束后则断开连接。在HTTP/1.0中,短连接是默认的连接方式。

该用哪个

虽然我们知道了长连接和短连接是什么了,但是在实际的使用场景中,该如何选择呢?

下面我们来对比一下,长连接和短连接各自的使用场景。

使用长连接

可以减少了TCP连接的建立和关闭次数,降低了网络资源消耗。例如,对于一个网站,用户在浏览多个页面时,使用长连接可以避免频繁建立和关闭连接,节省了网络资源。

同时可以提高数据传输效率,减少了网络延迟。例如,在一个文件传输过程中,使用长连接可以避免每次传输一个文件都需要重新建立连接,从而提高了文件传输的效率。

当然长连接也有一些不足之处:

长连接会占用更多的服务器资源,如内存、文件描述符等。例如,当有大量客户端同时连接到服务器时,服务器需要为每个客户端保持一个连接,可能导致服务器资源耗尽。

当客户端数量较多时,可能导致服务器资源耗尽。

使用短连接

短连接相对长连接,不会长时间的占用服务器资源。适用于请求量较小、连接数较多的场景。例如,在一个物联网应用中,大量设备定时向服务器发送数据,短连接可以避免长时间占用服务器资源。

短连接的不足之处也很明显:

短连接需要频繁建立和关闭TCP连接,增加了网络资源消耗。例如,在一个网站中,用户访问多个页面时,使用短连接需要为每个页面重新建立连接,消耗了较多的网络资源。

如何管理长连接

上文说了,长连接和短连接的使用场景和不足之处,那么我们具体该怎么使用呢?

其实在平时的业务开发的过程中,我们经常使用的方案是这样的:

如果并发量不大的系统中可以使用长连接,同时设置长连接的超时过期时间,

超时过期:如果一个链接上长时间没有请求的话,那么就断开这个链接, 比如,nginx 提供的 keepalive_timeout 参数

如果是并发量比较大的系统,那么就要使用长连接了,因为在大并发的情况下,使用短连接需要频繁建立和断开连接,产生很多不必要的消耗,除此之外,链接断开的过程中会在 time_wait 状态下停留2MSL的时间间隔,这段时间链接使用的四元组会被占用,这个对客户端和服务端都有一定的影响,但是这种状态对服务端和客户端的影响是不一样的,有老铁知道其中的差异吗?

而且这里还要注意一点,很多服务端在实现长连接的过程中会控制单个长连接上请求的个数,也是说,一个链接上请求个数超过一定数量后,服务端就会强制断开这个连接,比如 nginx 的 keepalive_requests 参数

如果并发量比较大,同时这限制的阈值比较小的话,还是会存在大量的 time_wait状态的链接。

实操一下

下面我们使用java语言中的技术栈,通过一个简单的例子来模拟一下,长连接和短连接。

短连接实现

客户端
   public static void main(String[] args) {HttpClient client = HttpClients.createDefault();for (int i = 0; i < 10; i++) {InputStream in = null;HttpGet httpGet = new HttpGet("http://127.0.0.1:8086/req");Header[] headerArrays = new Header[]{new BasicHeader("Connection", "close")};httpGet.setHeaders(headerArrays);try {HttpResponse response = client.execute(httpGet);System.out.println(EntityUtils.toString(response.getEntity(), "UTF-8"));in = response.getEntity().getContent();} catch (Exception e) {e.printStackTrace();} finally {IOUtils.closeQuietly(in);}}}
服务端
    @GetMapping(value = "/req")public String req(HttpServletRequest request){String remoteHost = request.getRemoteHost(); // client ipint remotePort = request.getRemotePort(); // client portSystem.out.println( remoteHost + ":" + remotePort);return "req";}

在上述代码中

服务端使用spring-boot中自带的tomcat作为http服务器,处理请求的逻辑也比较简单,当收到客户端的请求后,打印出客户端发送请求时,创建链接使用的ip和端口号。

客户端使用http-client作为http的客户端。

实现短连接的关键在于客户端发送请求使用如下的http请求头:

"Connection", "close"

该请求头的含义表示,告诉服务端:我这次发送的http请求使用的是短连接,你处理完请求后,主动断开连接。

通过查看服务端的日志可以发现,每次请求使用的端口号,都是不同的,表示每次发起请求都是新建的链接。

在这里插入图片描述

长连接实现

客户端
    public static void main(String[] args) {HttpClient client = HttpClients.createDefault();for (int i = 0; i < 10; i++) {InputStream in = null;HttpGet httpGet = new HttpGet("http://127.0.0.1:8086/req");Header[] headerArrays = new Header[]{new BasicHeader("Connection", "Keep-Alive")};httpGet.setHeaders(headerArrays);try {HttpResponse response = client.execute(httpGet);System.out.println(EntityUtils.toString(response.getEntity(), "UTF-8"));in = response.getEntity().getContent();} catch (Exception e) {e.printStackTrace();} finally {IOUtils.closeQuietly(in);}}}
服务端
    @GetMapping(value = "/req")public String req(HttpServletRequest request){String remoteHost = request.getRemoteHost(); // client ipint remotePort = request.getRemotePort(); // client portSystem.out.println( remoteHost + ":" + remotePort);return "req";}

上面实现长连接的代码和实现短连接时基本相同,差异的地方在于客户端发送请求使用的请求头做了调整:

"Connection", "Keep-Alive"

再次观察服务端打印的日志,输出的客户端端口号都是一样的:

在这里插入图片描述

管理长连接

上文说了,长连接长时间保持着,会占用系统资源,所以tomcat等众多http服务器提供了一些参数,来控制长连接的“长度”,

1.长连接有效时间:

如果一个链接上一定时间内没有请求的话,那么服务端就会主动断开连接。
可以在服务端添加tomcat相关的配置:

server:port: 8086servlet:context-path: /tomcat:keep-alive-timeout: 2s

上述配置 keep-alive-timeout 来配置长连接的空闲超时时间。

我们可以修改客户端程序进行验证,修改后的客户端程序如下:

public static void main(String[] args) {HttpClient client = HttpClients.createDefault();for (int i = 0; i < 10; i++) {InputStream in = null;HttpGet httpGet = new HttpGet("http://127.0.0.1:8086/req");Header[] headerArrays = new Header[]{new BasicHeader("Connection", "Keep-Alive")};httpGet.setHeaders(headerArrays);try {HttpResponse response = client.execute(httpGet);System.out.println(EntityUtils.toString(response.getEntity(), "UTF-8"));in = response.getEntity().getContent();Thread.sleep(3000); // 等待3s} catch (Exception e) {e.printStackTrace();} finally {IOUtils.closeQuietly(in);}}}

客户端程序每隔3s发送一次请求,间隔时间超过长连接空闲超时时间2s。

重新启动客户端和服务端程序,服务端程序打印日志如下:
在这里插入图片描述

2.长连接上请求个数限制:

如果长连接上通过请求超过一定的数量,那么服务端也会主动断开连接。可以在服务端添加tomcat相关的配置:

server:port: 8086servlet:context-path: /tomcat:max-keep-alive-requests: 2

上述配置 max-keep-alive-requests 来配置长连接最大请求个数,这里配置为2,表示一个长连接上最多可以通过2个请求。

重新启动服务端和客户端程序,服务端程序打印日志如下:
在这里插入图片描述

从日志可以看出,只有连续两个请求的链接端口号是相同的。

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

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

相关文章

都2024年了,你还在用两个手指在电脑键盘上打字吗?

前言 前段时间突然想起来一件很有意思的事情&#xff1a;一个找平面设计岗位的应届生&#xff0c;使用电脑的时候居然还在用两个手指打字。 想起这个事情的时候&#xff0c;并不是想嘲笑谁。 准备步入大学或者准备步入职场的小伙伴们&#xff0c;既然找的工作基本上是要接触电…

技术干货 | JMeter实现参数化的4种方式

参数化释义 什么是参数化&#xff1f;从字面上去理解的话&#xff0c;就是事先准备好数据&#xff08;广义上来说&#xff0c;可以是具体的数据值&#xff0c;也可以是数据生成规则&#xff09;&#xff0c;而非在脚本中写死&#xff0c;脚本执行时从准备好的数据中取值。 参数…

新秀小将京东云随身WiFi挑战华为、格行两位行业大哥,谁才是随身WiFi排行榜第一名?移动随身WiFi哪个品牌信号稳定?

要说近期通讯界最火的新闻&#xff0c;那一定是京东云随身WiFi杀入战场&#xff0c;企图挑战华为随身WiFi老大哥的位置&#xff0c;争夺随身WiFi排行榜第一名的位置。如果再加上老牌悍将格行随身WiFi&#xff0c;那将又是精彩纷呈的三国杀局面。那么三方混战之下&#xff0c;谁…

力扣L13--- 409.最长回文串(JAVA版)-2024年3月1日

1.题目描述 2.知识点 注1&#xff1a;向下取整是将一个数值向下舍入到最接近的整数&#xff0c;但不超过这个数值的整数。具体规则如下&#xff1a; 对于正数&#xff0c;向下取整后得到的整数是不大于原数值的最大整数&#xff1b; 对于负数&#xff0c;向下取整后得到的整数…

Leet code 179 最大数

解题思路 贪心算法 贪心算法就是走一步看一步 每一步都取当前位置的最优解 这题我们该如何贪呢&#xff1f; 我们先把int数组转换为string数组 以示例2为例 3 30 34 5 9 排序哪个在前哪个在后&#xff1f; 3 30 &#xff08;330&#xff09;> 30 3 &#xff08;30…

给Python初学者的一些技巧

以下是一些Python实用技巧和工具&#xff0c;希望能对大家学习有所帮助。 交换变量 x 6 y 5 x, y y, x print x >>> 5 print y >>> 6 if 语句在行内 print "Hello" if True else "World" >>> Hello 连接 下面的最后一种方…

[WUSTCTF2020]朴实无华

查看robots.txt 找到/fAke_flagggg.php 显然这是个假的flag&#xff0c;但是我们在header处发现了fl4g.php 近来发现中文全部变成了乱码 插件转成utf8后正常显示 <?php header(Content-type:text/html;charsetutf-8); error_reporting(0); highlight_file(__file__);//leve…

LeetCode每日一题——移除元素

移除元素OJ链接&#xff1a;27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 思路&#xff1a; 题目给定要求只能使用O(1)的额外空间并且原地修改输入数组&#xff0c;然后返回移除后的数组行长度。那 么我们就可以确我没有办法建立临时的数组存放我…

unicloud update 修改

update 修改 使用腾讯云时更新方法必须搭配doc、where方法使用&#xff0c;db.collection(‘test’).update()会报如下错误&#xff1a;param should have required property ‘query’ collection.doc().update(Object data)未使用set、remove更新操作符的情况下&#xff0c…

螺旋阵思维与代码

1.思维 56789419202110318252211217242312116151413观察上面的螺旋阵,你就会发现数字从小到大,按照贝壳的螺旋形依次排列. 走到头就要换一个方向. 看到螺旋数组可以让人想象到贪吃蛇,拿出一个字符串设置为方向,碰到头方向改变,这样循环模拟,直到格子里的数>行和列数(n) .…

Fork - 将 GitHub 的某个特定仓库复制到自己的账户下

Fork - 将 GitHub 的某个特定仓库复制到自己的账户下 1. ForeverStrongCheng/OpenCV-tutorials2. Fork -> ForeverStrongCheng/R2CNN_Faster-RCNN_TensorflowReferences 访问仓库页面&#xff0c;点击 Fork 按钮创建自己的仓库。 Fork 是将 GitHub 的某个特定仓库复制到自己…

说下你对TCP以及TCP三次握手四次挥手的理解?

参考自简单理解TCP三次握手四次挥手 什么是TCP协议&#xff1f; TCP( Transmission control protocol )即传输控制协议&#xff0c;是一种面向连接、可靠的数据传输协议&#xff0c;它是为了在不可靠的互联网上提供可靠的端到端字节流而专门设计的一个传输协议。 面向连接&a…