Socket,http长连接与短连接

Socket,http长连接与短连接,第1张

在网络层有IP协议,ICMP协议,ARP协议,RARP协议和BOOTP协议.

在传输层中有:TCP协议与UDP协议.

在应用层有:通过TCP协议来通信的应用层协议包括FTP,HTTP,TELNET,SMTP协议. 通过UDP协议来通信的应用层协议包括DNS,TFTP等

连接->数据传输->关闭连接

HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,单任务结束后就中断连接.也可以这样说:短连接是指Socket连接后发送后接收完数据后马上断开连接.

连接->传输数据->保持连接->传输数据->….->关闭连接

长连接指建立socket连接后不管是否使用都保持连接,但安全性较差.

http的长连接

HTTP也可以建立长连接的,使用Connection:keep-alive,HTTP1.1默认进行持久连接,HTTP1.1和HTTP1.0相比较而言最大的区别就是添加了持久连接支持(貌似最新的http1.0可以显示的指定keep-alive)但还是无状态的,或者说是不可信任的.

长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况.每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接在操作的话那么处理时间会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用再次建立连接.例如即使通讯环信底层用的就是长连接聊天过程中为了保证消息的实时性,保持长连接进行会话!

而web网站的http服务一般用短连接,因为长连接对于服务端来说会耗费一定的资源,而像web网站这样频繁成千上万甚至上亿客户端的连接用短连接会更省资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,并发数会很大,这样后台服务器有承受很大的压力,所以这种情况小用短连接会比较好.

Socket是应用层与TCP/IP协议通讯的中间软件抽象层,它是一组接口,在设计模式中,socket其实就是一个门面模式,它把复杂的TCP/IP组协议隐藏在了socket接口后面,对用户来说简单的接口就是全部,让socket去组织数据,以符合指定的协议.

主机A的应用程序要和主机B的应用程序进行通信,必须通过socket建立连接,而建立socket连接必须通过底层的TCP/IP协议建立TCP连接,建立TCP连接需要底层IP协议来寻址网络中的主机.我们知道网络中的IP协议可以帮助我们根据IP地址来找到目标主机但是一台主机上可能运行着多个应用程序,如何才能与指定的应用程序通信就要通过TCP和UDP的地址也就是端口号来指定,这样就可以通过socket实例唯一代表一个主机上的一个应用程序的通信链路了.

(1)第一次握手:Client(客户端)将标识位SYN(发起一个新连接)置为1,随机产生一个(序号:发送数据对其标识)seq=J,并将该数据发送给server(服务器),Client(客户端)进入SYN_SENT状态,等待Server确认.

(2)第二次握手:Server收到数据包后由SYN=1知道Client请求建立连接,Server将SYN和ACK都置为1,ack=J+1.随机产生一个seq=k,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态.

(3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标识位ACK置为1,ack=k+1并将数据包发送给Server,Sever检查ack是否为k+1,ACK是否为1,如果正确则建立连接Client和server进入ESTABLISHED状态,完成三次握手,随后Client和Server之间可以开始传输数据了.

(1)第一次挥手:Client发送一个FIN(释放一个连接),用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。

(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。

(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK(确认序号有效)状态.

(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

Q1 : HTTP Socket TCP UDP都是什么?

HTTP 全称是超文本传输协议,是一个应用层的协议。用于客户端和服务端之间进行通讯。

TCP/UDP 都是传输层协议。TCP是可靠的,我们常说的三次握手连接,四次握手断开都是说的TCP。而UDP是不可靠的。

Socket 则是从传输层抽象出来的接口层。

Q2 : HTTP连接和Socket连接有什么区别?分别在什么情况下使用?

HTTP 是基于TCP的短连接。需要经过三次握手建立连接,且无法保持始终连接。

Socket 是长连接。基于TCP的Socket连接,一旦建立三次握手,除非一方主动断开,否则连接状态一直保存。也可以基于UDP进行Socket连接。

HTTP连接,服务端无法主动发消息,采用的是'请求-响应'机制。客户端没有发消息给服务端,服务端无法推送消息给客户端。

Socket连接,一方可以随时向另一方发起会话。

双方不需要时刻保持连接在线用HTTP。eg : 客户端资源获取、上传文件等。

即时通讯应用需要用Socket连接。eg : 微信、苹果的APNs等。

Q3 : HTTPS是什么?和HTTP有什么区别?

HTTPS就是HTTP加上SSL/TLS。TLS(Transport Layer Security)传输层安全协议,作用是在传输层对网络连接加密。SSL就是TLS的前身。

HTTP端口是80,是无状态的。HTTPS端口是443,是可以进行加密传输、身份认证的网络协议。

nginx中http模块使用http长连接的相关配置(主要是keepalive指令)和http长连接的原理解释。

连接管理是一个 HTTP 的关键话题:打开和保持连接在很大程度上影响着网站和 Web 应用程序的性能。在 HTTP/1.x 里有多种模型:短连接, 长连接, 和 HTTP 流水线。在解释这三种模型之前,我们需要先明确一些前提知识:

接下来我们开始解释。

在早期,HTTP 使用一个简单的模型来处理这样的连接。这些连接的生命周期是短暂的:每发起一个请求时都会创建一个新的连接,并在收到应答时立即关闭。这就是类似上面说的三次握手,在互联网发展的早期一个网页的资源并没有现在这么多,很多可能只是一个简单的静态页面而已,所以这样的模型显然很OK。客户端获取完所需资源之后,就断开连接,不再占用服务器的资源。

HTTP 短连接模型是最早期的模型,也是 HTTP/1.0 的默认模型。每一个 HTTP 请求都由它自己独立的连接完成;这意味着发起每一个 HTTP 请求之前都会有一次 TCP 握手,而且是连续不断的。 实际上,TCP 协议握手本身就是耗费时间的,所以 TCP 可以保持更多的热连接来适应负载。短连接破坏了 TCP 具备的能力,新的冷连接降低了其性能。

后来,网页需要请求的资源越来越多,短连接模型显然已经十分吃力了。因为短连接有两个比较大的问题:创建新连接耗费的时间尤为明显(三次握手很耗费时间),另外 TCP 连接的性能只有在该连接被使用一段时间后(热连接)才能得到改善。因此在HTTP/1.1中引入了长连接模型和流水线模型。

一个长连接会保持一段时间,重复用于发送一系列请求,节省了新建 TCP 连接握手的时间,还可以利用 TCP 的性能增强能力。当然这个连接也不会一直保留着:连接在空闲一段时间后会被关闭(服务器可以使用 Keep-Alive 协议头来指定一个最小的连接保持时间)。

长连接也还是有缺点的;也就是前面提到的资源占用问题,就算是在空闲状态,它还是会消耗服务器资源,也更容易被DDoS攻击。 本质上长连接是因为不断地三次握手建立连接消耗的资源要大于维持连接所需要的资源才使用的 ,如果服务器处于高负载时段或者被DDoS,可以使用非长连接,即尽快关闭那些空闲的连接,也能对性能有所提升。

流水线模型的实现要复杂很多,而已效果也并不是特别好,主要还要考虑到各种兼容性,所以默认是不启用这个流水线模型的,而在HTTP/2中,流水线已经被更好的算法给代替,如 multiplexing 。

默认情况下,HTTP 请求是按顺序发出的。 下一个请求只有在当前请求收到应答过后才会被发出。 由于会受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间。 流水线是在同一条长连接上发出连续的请求,而不用等待应答返回。这样可以避免连接延迟。 理论上讲,性能还会因为两个 HTTP 请求有可能被打包到一个 TCP 消息包中而得到提升。就算 HTTP 请求不断的继续,尺寸会增加,但设置 TCP 的 MSS(Maximum Segment Size) 选项,仍然足够包含一系列简单的请求。

并不是所有类型的 HTTP 请求都能用到流水线:只有 idempotent 方式,比如 GET 、 HEAD 、 PUT 和 DELETE 能够被安全的重试:因为有故障发生时,流水线的内容要能被轻易的重试,即出现了问题重试的成本要尽可能低,否则还不如使用长连接模型。

正确的实现流水线是复杂的:传输中的资源大小,多少有效的 RTT 会被用到,还有有效带宽,流水线带来的改善有多大的影响范围。不知道这些的话,重要的消息可能被延迟到不重要的消息后面。这个重要性的概念甚至会演变为影响到页面布局!因此 HTTP 流水线在大多数情况下带来的改善并不明显。此外,流水线受制于 HOL 问题。

我们还是使用上面的例子来进行解释,这次的握手请求就变了,A一次向B发出了三个请求:

最后这里补充一张图片来对比三种模型之间的差别:

了解了上面的原理之后,Nginx中的keepalive指令我们就非常好理解了,相关的指令主要有三个,我们逐个进行解释:

在upstream模块中配置,启用连接到upstream中的服务器的缓存, connections 参数的主要作用是设定每个Nginx的 单个worker进程(each worker process) 对于upstream中的server的最大空闲连接数,当超过该数字的时候,会关闭使用得最少的连接。

需要注意的是,keepalive指令并不会限制Nginx的 所有worker 进程能开启的连接到upstream服务器中的 连接总数(total number) 。也就是如果设得太大了,会导致过多的空闲连接占满了upstream中的server资源,导致新的连接无法建立,因此这个数值的设定需要根据worker进程数量来调整。

keepalive_requests 设定可以通过一个连接(connection)发送的请求(request)数量,超过最大请求数量之后,该连接会被关闭。为了释放每个连接的内存分配,定期关闭连接是很有必要的。因此,不建议将 keepalive_requests 设定过大,否则可能会导致过高的内存占用。

设定连接超时时间,在此设定的时间内,client与upstream中的server的空闲keepalive连接将保持打开状态(open)。此外,虽然官方文档说的默认值是60s,但是1.17.9版本的Nginx在安装之后配置文件nginx.conf上面设定的是65s。

如果需要在JMeter通过http长连接发送请求,首先需要选择了Use KeepAlive 长连接协议,虽然默认是勾选的,但也需要确认一下。

除了选择了Use KeepAlive 长连接协议,还需要在Advanceed高级选项面板,选择HttpClient4类型的HttpRequest请求实现。

在即使选择了Use KeepAlive 长连接协议,还选择了HttpClient4类型的HttpRequest请求外,还差一步:需要配置JMeter.properties中的时间空闲等待时间,设置默认为0,默认情况下,不会对长连接进行空闲等待,一旦连接空闲,则立马断开了,这也是导致大家压测中出现了失败的一种情形。所以,需要进行空闲等待时间的修改,这个时间,建议尽量和后端服务器的空闲等待时间保持一致。

具体的修改办法是:在jmeter.property文件,找到 httpclient4.idletimeout 空闲等待时间选项,进行合适的修改即可。由于前面使用了60s,所以在这里修改为 60000ms,也就是60s。

改完后,要使得修改生效的话,还需要重启一下jmeter。再一次启动高并发测试,与之前的结果进行对比,可以发现:修改完成之后,会发现错误率显著的下降,1000个线程每个请求10次,错误率直接0%。这个结果,对比没有修改之前30%以上的错误率,提升的效果还是非常显著的,所以,建议大家去试一试。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/270278.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-19
下一篇2023-04-19

发表评论

登录后才能评论

评论列表(0条)

    保存