HTTP的长链接,你不知道的链接。。。

 

 

    

长链接起源

 

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

 

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

 

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

 

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

 

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

 

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

 

演示长链接

 

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

 

    准备工做以下:并发

 

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

 

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

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

扫一扫,加关注:

相关文章
相关标签/搜索