問題:
公司的某項業(yè)務(wù)是通過nginx反向代理到ws協(xié)議的服務(wù),用ws協(xié)議的目的是保持長連接,持續(xù)性提供服務(wù)。但是服務(wù)經(jīng)常出現(xiàn)卡頓現(xiàn)象,猜測可能是沒有保持長連接,出現(xiàn)超時連接斷開的問題。
解決方案:
ws協(xié)議是支持心跳機制的。
- 心跳機制即:
在使用websocket的過程中,有時候會遇到網(wǎng)絡(luò)斷開的情況,但是在網(wǎng)絡(luò)斷開的時候服務(wù)器端并沒有觸發(fā)onclose的事件。這樣會有:服務(wù)器會繼續(xù)向客戶端發(fā)送多余的鏈接,并且這些數(shù)據(jù)還會丟失。所以就需要一種機制來檢測客戶端和服務(wù)端是否處于正常的鏈接狀態(tài)。因此就有了websocket的心跳了。還有心跳,說明還活著,沒有心跳說明已經(jīng)掛掉了。 - 原理
心跳機制是每隔一段時間會向服務(wù)器發(fā)送一個數(shù)據(jù)包,告訴服務(wù)器自己還活著,同時客戶端會確認服務(wù)器端是否還活著,如果還活著的話,就會回傳一個數(shù)據(jù)包給客戶端來確定服務(wù)器端也還活著,否則的話,有可能是網(wǎng)絡(luò)斷開連接了。需要重連
檢查了代碼發(fā)現(xiàn)心跳超時間設(shè)置了5秒,也就是說每5秒就會發(fā)送數(shù)據(jù)包檢測客戶端和服務(wù)端運行狀態(tài)。在客戶端和服務(wù)端沒有出現(xiàn)網(wǎng)絡(luò)問題的情況下會一直保持長連接,不會出現(xiàn)卡頓的現(xiàn)象。排除網(wǎng)絡(luò)問題,問題可能出現(xiàn)在nginx反向代理上。檢查了配置發(fā)現(xiàn)有幾個參數(shù)有一些問題。
proxy_connect_timeout 5s;
proxy_read_timeout 5s;
在官方文檔上查找了參數(shù)的含義如下:
Syntax: proxy_connect_timeout time;
Default:
proxy_connect_timeout 60s;
Context: http, server, location
Defines a timeout for establishing a connection with a proxied server. It should be noted that this timeout cannot usually exceed 75 seconds.
定義了與代理服務(wù)器建立連接時的超時時間。這個設(shè)置5秒也是足夠了,可以排除。
Syntax: proxy_read_timeout time;
Default:
proxy_read_timeout 60s;
Context: http, server, location
Defines a timeout for reading a response from the proxied server. The timeout is set only between two successive read operations, not for the transmission of the whole response. If the proxied server does not transmit anything within this time, the connection is closed.
定義從代理服務(wù)器讀取響應(yīng)的超時時間,也就是5秒內(nèi)沒有響應(yīng)即斷開連接。
問題就出現(xiàn)在這里,這個參數(shù)設(shè)置的5秒正好和心跳超時時間一樣。這有可能會導致心跳機制還沒發(fā)送數(shù)據(jù)包進行心跳測試,代理服務(wù)器發(fā)現(xiàn)超時就斷開連接了。只要把代理服務(wù)器nginx的read_timeout參數(shù)設(shè)置成遠大于心跳的超時時間就可以解決問題。我設(shè)置了默認的60秒解決了卡頓問題。