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

掃一掃,加關注:

相關文章
相關標籤/搜索