什麼樣的鏈接才能稱之爲長鏈接?要多長。。。。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
掃一掃,加關注: