长连接起源

什么样的连接才能称之为长连接?要多长。。。。

http是一种无状态的协议,也就是stateless协议,而http协议又是建立在tcp/ip协议的基础之上的。

无状态表示每次请求都是一次独立的http事务,也就是发送http 请求(request)过去,然后web服务器或者application服务器进行响应,发送一个http response回来,这样就是结束了一次http事务。

http建立在tcp/ip的基础之上,从而会遵循tcp协议的规则,在每次进行连接的时候,必须先进行三次握手,数据交换之后,进行四次断开。

每次请求的时候,都要进行三次握手,四次断开,从性能上来说,满足不了大并发的需要,从而也就有了长连接,在进行请求的时候,不需要再次进行三次握手和四次断开,直接使用原来的连接进行传输数据。

长连接能实现的前提就是,在同一个客户端进行多次的请求,如果不是同一客户端的话,那么还是需要进行三次握手和四次断开。每一个客户端在访问一个网页的时候,可能会发出几百个请求,请求各种web服务器的资源,例如图片,超链接,js和css等,请求过后,浏览器将所有的对象组织在一个页面中,然后显示在客户端。

演示长连接

在这里演示使用的是apache的web服务器,使用最简单的方式,然后使用telnet进行查看连接是否断开。

准备工作如下:

[root@mogilenode1 ~]# yum -y install httpd (安装httpd服务)

[root@mogilenode1 ~]# service httpd start (启动httpd服务)

Starting httpd:                                            [  OK  ]

[root@mogilenode1 ~]# netstat -ntlp|grep httpd(查看httpd监听的端口)

tcp        0      0 :::80                       :::*                        LISTEN      2810/httpd

[root@mogilenode1 ~]# echo "welcome the index (创建首页文件)page">/var/www/html/index.html

在默认情况下,httpd是没有长连接的,查看配置文件如下所示:

[root@mogilenode1 ~]# grep  "KeepAlive" /etc/httpd/conf/httpd.conf

# KeepAlive: Whether or not to allow persistent connections (more than

KeepAlive Off

# MaxKeepAliveRequests: The maximum number of requests to allow

MaxKeepAliveRequests 100

# KeepAliveTimeout: Number of seconds to wait for the next request from the

KeepAliveTimeout 15

从而可以使用telnet来进行测试查看连接的情况,如下所示:

[root@mogilenode1 ~]# telnet 192.168.1.236 80(使用telnet连接服务器的80端口,也就是三次握手的连接)

Trying 192.168.1.236...

Connected to 192.168.1.236.

Escape character is '^]'. (开始构建http请求,起始行为请求的方法,请求的url,http的协议版本,第二行为请求的主机,第三行为空白行)

GET / http/1.1

Host:192.168.1.236

HTTP/1.1 200 OK (得到的响应内容,http协议的版本,状态码,原因短语)

Date: Wed, 30 Aug 2017 10:08:22 GMT

Server: Apache/2.2.15 (Red Hat)

Last-Modified: Wed, 30 Aug 2017 10:05:40 GMT

ETag: "41b03-17-557f5ab897618"

Accept-Ranges: bytes

Content-Length: 23

Connection: close

Content-Type: text/html; charset=UTF-8

welcome the index page (响应的内容)

Connection closed by foreign host.(在请求得到响应之后,请求被断开)

修改httpd的配置文件,只要将长连接开启即可,如下:

[root@mogilenode1 ~]# grep  "KeepAlive" /etc/httpd/conf/httpd.conf

# KeepAlive: Whether or not to allow persistent connections (more than

KeepAlive On

# MaxKeepAliveRequests: The maximum number of requests to allow

MaxKeepAliveRequests 100

# KeepAliveTimeout: Number of seconds to wait for the next request from the

KeepAliveTimeout 15

[root@mogilenode1 ~]# service httpd reload

Reloading httpd:

再次使用telnet进行测试连接,如下所示:

[root@mogilenode1 ~]# telnet 192.168.1.236 80(测试请求了一个资源,连接未断开,可以再次请求资源,过了一段时间后,连接被关闭)

Trying 192.168.1.236...

Connected to 192.168.1.236.

Escape character is '^]'.

GET / http/1.1

Host:192.168.1.236

HTTP/1.1 200 OK

Date: Wed, 30 Aug 2017 10:16:55 GMT

Server: Apache/2.2.15 (Red Hat)

Last-Modified: Wed, 30 Aug 2017 10:05:40 GMT

ETag: "41b03-17-557f5ab897618"

Accept-Ranges: bytes

Content-Length: 23

Content-Type: text/html; charset=UTF-8

welcome the index page(客户端得到响应之后,未断开,可以再次进行请求其他的资源,从而不用进行三次握手和四次断开,提高了性能)

GET / http/1.1

Host:192.168.1.236

HTTP/1.1 200 OK

Date: Wed, 30 Aug 2017 10:17:16 GMT

Server: Apache/2.2.15 (Red Hat)

Last-Modified: Wed, 30 Aug 2017 10:05:40 GMT

ETag: "41b03-17-557f5ab897618"

Accept-Ranges: bytes

Content-Length: 23

Content-Type: text/html; charset=UTF-8

welcome the index page

Connection closed by foreign host.

其他长连接参数

在进行长连接的时候,的确是进行了优化了性能,提高了客户端的访问体验,提升了网站的访问速度,但是,可能存在这么一种情况。。。

有的人占着茅坑不拉屎,就是一直占用这个连接,我就是不断开,如果存在大量的这种人,后果就是http服务不可用,其他的用户都在排队,等待有多难受,取决于你在坑里还是在坑外。。。。

有的人不是占着茅坑不拉屎,他是一会拉一点,一会拉一点,这种和上面的也是一样的,都是占用服务器的资源,耗费了httpd连接数,服务器支持的连接数是有上限的。。。。

为了解决上面的问题,在开启长连接之后,另外需要配置两个控制的参数,一个是连接的超时时间,也就是这个连接只能持续多少秒,然后服务器强行断开连接;一个是连接的请求数,当请求的数量到了一定的数量之后,也会强行的断开连接,相当于我今天只服务多少人,服务了多少,我就该休息,可以使用这种理解。

在httpd中参数为如下:

# MaxKeepAliveRequests: The maximum number of requests to allow

MaxKeepAliveRequests 100 (一个连接最大的请求数到100的时候,断开连接)

# KeepAliveTimeout: Number of seconds to wait for the next request from the

KeepAliveTimeout 15 (一个连接到了15秒之后,断开连接)

两个参数,只要一个条件满足,那么就会断开连接。在进行设置这两个参数的时候,必须根据压测的结果来进行设置,主要看的是响应的大小等情况。

拓展

在进行连接的时候,服务段由于是tcp连接,从而有不同的状态,使用浏览器访问的时候,可以查看服务端的连接状态如下所示:

[root@mogilenode1 ~]# netstat -tnp|grep 80 (开始的状态为established,也就是建立连接,一直到长连接被关闭)

tcp        0      0 ::ffff:192.168.1.236:80     ::ffff:192.168.1.1:51084    ESTABLISHED 2851/httpd

[root@mogilenode1 ~]# netstat -tnp|grep 80(关闭之后的状态,表示服务端主动断开连接,仅仅关闭了服务端到客户端的连接,半关闭状态)

tcp        0      0 ::ffff:192.168.1.236:80     ::ffff:192.168.1.1:51084    FIN_WAIT2   -

使用telnet连接的时候:

[root@mogilenode1 ~]# telnet 192.168.1.236 80

Trying 192.168.1.236...

Connected to 192.168.1.236.

Escape character is '^]'.

Connection closed by foreign host.

服务端状态变化如下所示:

[root@mogilenode1 ~]# netstat -tnp|grep 80(开始的状态为established,也就是连接)

tcp        0      0 192.168.1.236:52095         192.168.1.236:80            ESTABLISHED 3445/telnet

tcp        0      0 ::ffff:192.168.1.236:80     ::ffff:192.168.1.236:52095  ESTABLISHED 2850/httpd

[root@mogilenode1 ~]# netstat -tnp|grep 80(四次断开已完成)

tcp        0      0 ::ffff:192.168.1.236:80     ::ffff:192.168.1.236:52095  TIME_WAIT   -

使用抓包的先是如下:

[root@mogilenode1 ~]# tcpdump -nn port 80

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

——三次握手开始——

07:42:53.138211 IP 192.168.1.1.55597 > 192.168.1.236.80: Flags [S], seq 960992918, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0

07:42:53.138255 IP 192.168.1.236.80 > 192.168.1.1.55597: Flags [S.], seq 852217171, ack 960992919, win 14600, options [mss 1460,nop,nop,sackOK,nop,wscale 5], length 0

07:42:53.138603 IP 192.168.1.1.55597 > 192.168.1.236.80: Flags [.], ack 1, win 16425, length 0

——三次握手结束——

——客户端发送http request请求——

07:42:53.145706 IP 192.168.1.1.55597 > 192.168.1.236.80: Flags [P.], seq 1:572, ack 1, win 16425, length 571

07:42:53.145768 IP 192.168.1.236.80 > 192.168.1.1.55597: Flags [.], ack 572, win 492, length 0

——客户端发送http请求结束——

——服务端发送response开始——

07:42:53.147925 IP 192.168.1.236.80 > 192.168.1.1.55597: Flags [P.], seq 1:188, ack 572, win 492, length 187

07:42:53.346735 IP 192.168.1.1.55597 > 192.168.1.236.80: Flags [.], ack 188, win 16378, length 0

——服务端发送response结束——

——服务端主动关闭——

07:42:54.150698 IP 192.168.1.236.80 > 192.168.1.1.55597: Flags [F.], seq 188, ack 572, win 492, length 0

07:42:54.151209 IP 192.168.1.1.55597 > 192.168.1.236.80: Flags [.], ack 189, win 16378, length 0

——服务端关闭——

07:43:39.157705 IP 192.168.1.1.55597 > 192.168.1.236.80: Flags [.], seq 571:572, ack 189, win 16378, length 1

07:43:39.157745 IP 192.168.1.236.80 > 192.168.1.1.55597: Flags [.], ack 572, win 492, length 0

07:44:24.156207 IP 192.168.1.1.55597 > 192.168.1.236.80: Flags [.], seq 571:572, ack 189, win 16378, length 1

07:44:24.156256 IP 192.168.1.236.80 > 192.168.1.1.55597: Flags [R], seq 852217360, win 0, length 0

使用抓包工具来查看tcp的状态,主要是在并发响应的时候,可能会出现大量的time_wait连接,而这个属于正常状态。

可以使用如下的内核参数来解决,也就是重用tcp连接,如下参数:

net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30

扫一扫,加关注:

HTTP的长连接,你不知道的连接。。。的更多相关文章

  1. MySQL 线程池&连接池&长连接&短连接

    线程池 简介 1.mysql每连接每线程,mysql都分配一个单独的线程,该线程处理客户端发来的所有命令 2.每个线程会占用一定的系统资源,线程数越多消耗的系统资源也越多 3.线程的创建和销毁有一定的 ...

  2. nginx 代理tcp长连接短连接配置

    https://blog.csdn.net/tayinyinyueyue/article/details/78932697 nginx使用ngx_stream_core_module模块代理tcp长连 ...

  3. MySQL之长连接、短连接、连接池

    当数据库服务器和客户端位于不同的主机时,就需要建立网络连接来进行通信.客户端必须使用数据库连接来发送命令和接收应答.数据.通过提供给客户端数据库的驱动指定连接字符串后,客户端就可以和数据库建立连接了. ...

  4. [PHP] time_wait与长连接短连接

    服务端上查看tcp连接的建立情况,直接使用netstat命令来统计,看到了很多的time_wait状态的连接.这些状态是tcp连接中主动关闭的一方会出现的状态.该服务器是nginx的webserver ...

  5. java原生程序redis连接(连接池/长连接和短连接)选择问题

    最近遇到的连接问题我准备从重构的几个程序(redis和mysql)长连接和短连接,以及连接池和单连接等问题用几篇博客来总结下. 这个问题的具体发生在java原生程序和redis的交互中.这个问题对我最 ...

  6. 长连接 短连接 RST报文

    https://baike.baidu.com/item/短连接 短连接(short connnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数 ...

  7. redis的连接方法|连接池|操作

    1.先看下redis的连接 import redis # 连接服务端 r = redis.Redis(host="127.0.0.1",port=6379) #获取所有的key值 ...

  8. 安卓Socket连接实现连接实现发送接收数据,openwrt wifi转串口连接单片机实现控制

    安卓Socket连接实现连接实现发送接收数据,openwrt wifi转串口连接单片机实现控制 socket 连接采用流的方式进行发送接收数据,采用thread线程的方式. 什么是线程?  详细代码介 ...

  9. 解决Mysql连接池被关闭 ,hibernate尝试连接不能连接的问题。 (默认mysql连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池。系统发布第二天访问链接关闭问题。

    解决Mysql连接池被关闭  ,hibernate尝试连接不能连接的问题. (默认MySQL连接池可以访问的时间为8小时,如果超过8小时没有连接,mysql会自动关闭连接池. 所以系统发布第二天访问会 ...

  10. 通过MSSQL连接服务器连接至Oracle数据库

    前言 有很多时候,我们需要MSSQL与Oracle进行跨库查询或数据交互.本篇随笔将阐述如何通过MSSQL的连接服务器连接至Oracle数据库,并且读取数据的示例. 具体步骤 首先需要到Oracle的 ...

随机推荐

  1. 好用的Google漏洞爬虫:Google Mass Explorer

    这是一款基于谷歌搜索引擎的自动化爬虫. 爬虫介绍 爬虫大体机制就是: 先进行一次谷歌搜索,将结果解析为特定格式,然后再提供给exp使用. 大家可以尝试使用–help来列出所有参数. 这个项目笔者会持续 ...

  2. 《Discuz安装时候出现乱码 -- 问题解决方法》

    自我安装discuz时出现安装界面乱码的情况,跟链接所说一样,经过原作的分享,加上我自己的实验,明白了,什么时候修改/usr/local/php/etc/php.ini里面的default_chars ...

  3. Linux下绝对经典的命令

    1.使用远程终端时,可以使用如下命令: screen tmux 2.下载文件可以使用如下命令: curl wget 3.压缩解压缩可以使用: tar .zip.rar 4.使用抓包工具 tcpdump ...

  4. MySQL数据库基础(MySQL5.7安装、配置)

      写在前面: MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品.MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQ ...

  5. 使用docker搭建wordpress

    前言 去年在学习docker,在看完菜鸟教程和第一本docker书后,一直想实战用一下这个技术,多用用才能熟能生巧,真正体验它的利弊.正好傅老板用docker搭完了wordpress,我也就手痒跟着搭 ...

  6. CentOS7关闭/开启防火墙出现 Unit iptables.service failed to load

    在vm中安装好tomcat,而且在liunx中使用nc命令可以返回成功,但是更换到window中访问不到tomcat的情况,是由于linux防火墙的问题造成的,传统的解决方式有2中 第一种解决方案: ...

  7. ASP.NET根据当前时间获取,本周,本月,本季度等时间段

    DateTime dt = DateTime.Now; //当前时间 DateTime startWeek = dt.AddDays(1 - Convert.ToInt32(dt.DayOfWeek. ...

  8. java学习笔记(详细)

    java平台 1.J2SE java开发平台标准版 2.J2EE java开发平台企业版 java程序需要在虚拟机上才可以运行,换言之只要有虚拟机的系统都可以运行java程序.不同系统上要安装对应的虚 ...

  9. Docker MariaDB 10.3 Galera Cluster 集群同步复制 多主 Docker Haproxy 负载均衡

    mariadb 现有动态列,支持json格式存储,类似mongodb的bson,但是操作能力较为尴尬,中间件有spider,我非常感兴趣的一个东西 关于spider 这里有一篇很好的博文,有时间一定得 ...

  10. 总结MySQL大数据量下如何进行优化

    写在建库前: 在确定数据库业务后.建立数据库表格时,就应对一些常见问题有所考虑,以避免在数据增长一段时间后再做应对,可能造成时间及维护成本增加: 数据的月增量,年增量 数据的快速增长点 是否需要触发器 ...