首先我們來看一下websocket協議和http有什麼關係呢?
本質上說,websocket和http就不是乙個協議,層級不一樣。但是為了相容現有瀏覽器的握手規範,必須借助http協議建立連線。
這是乙個websocket的握手請求
sec-websocket-extensions: permessage-deflate; client_max_window_bits這裡面有幾個和一般http request不一樣的地方,
connection: upgrade
upgrade: websocket
sec-websocket-version: 13
sec-websocket-key: fffilfcwulsamqacrabs2a==
sec-websocket-extensions: permessage-deflate; client_max_window_bits
這是告訴服務端這不是乙個普通的請求,而是websocket協議。sec-websocket-key 是乙個base64 encode的值,是瀏覽器隨機生成的,用於讓服務端知道這是乙個全新的socket客戶端。
服務端如果開啟了socket監聽,那麼就會返回這樣的response
sec-websocket-accept: i/tcy92jmoxiozwgi8roh6cguwk=表示接收了請求,並且即將切換到websocket協議,所以code是101。sec-websocket-accept 這個則是經過伺服器確認,並且加密過後的 sec-websocket-key。到這裡http協議的任務就已經完成,之後的通訊都是基於websocket協議了。
本質上說握手請求就是乙個特殊的http request,只是需要加一些上文提到的特殊內容,從nignx官方介紹可以看到
只是在request header加了兩個屬性,並且強制公升級到http 1.1,原因是http 1.0不支援keep alive。如果使用http 1.0發握手請求,服務端返回101以後就會直接結束這次http會話了。這一點也為之後的坑埋下了伏筆。
自從上線了websocket服務之後,就會經常發現socket無法建立,獲得504的超時響應。
connection: keep-alive而且這一響應只有在經過slb(負載均衡)時才有,如果直接請求到我們自己的nginx是沒有問題的。但是基於對阿里的信任,還是覺得問題應該還是我們自己這兒。從code review到nginx配置,折騰了五六個小時。
最後只有自己搭建的nginx access log上尋找蛛絲馬跡,一開始抓到一些響應都是499的返回,並且request_time時間都在60s上下。
[09/mar/2018:15:04:51 +0800] 100.97.89.10 - - - 10.0.21.11 to: 10.0.20.11:8011: get /ws/?id=168451&url=就考慮是不是socket服務端建立連線後響應不及時,讓slb發現60s沒有報文互動直接就切斷請求了。http: http/1.0 upstream_response_time - msec 1520579091.139 request_time
但是因為我們在前端是做了心跳的,即使服務端不響應,只要socket建立通過心跳肯定也會在60s內進行互動。不應該出現上面的場景。
之後我們把access log中socket建立成功的請求和不成功的請求分開放到一起對比,發現不成功的都是http 1.0的協議。
http/1.0upstream_response_time - msec 1520579072.716 request_time 36.755 s|就好像這兩個請求,同乙個頁面發出的,但是乙個成功乙個失敗。失敗的正好就是http/1.0,為什麼會有兩個版本的協議呢,
為了證據更加「確鑿」,我們對請求進行了抓包分析,並將sec-websocket-key列印到nginx的access log中方便trace同乙個請求。
可以看到都是8+qdyekjgftwkb2ov4p5ta==的請求,但是在經過slb進入nginx時候協議降級到了1.0.這叫乙個酸爽,趕緊給阿里雲開了工單,經過大概3~4個小時的交流。最終獲得乙個鏈結,裡面有這樣的描述
如何在阿里雲負載均衡上啟用ws/wss支援?這個大坑就在"注意"那一段,我們的slb是效能共享型而不是效能保障型。看來也不是阿里雲的問題,是我們的slb檔次不夠高啊。知道原因後,立刻付費公升級了保障型。實測一下所有問題都解決了。無需配置,當選用http監聽時,預設支援無加密版本websocket協議(ws協議);當選擇https監聽時,預設支援加密版本的websocket協議(wss協議)。
注意:需要將例項公升級為效能保障型例項。詳細參見如何使用負載均衡效能保障型例項。
雖然問題解決了,但是其實很難理解廠商的邏輯,為什麼效能共享型中某些slb節點就會降級http協議版本呢,要知道1.0版本已經是乙個相當落後的版本了。
在此記錄一下心路歷程,為了讓其他使用阿里雲的同學不要重蹈覆轍。
rp filter引數 及 阿里雲SLB使用注意
rp filter引數用於控制系統是否開啟對資料報源位址的校驗。參考文件 中文 即rp filter引數有三個值,0 1 2,具體含義 1 開啟嚴格的反向路徑校驗。對每個進來的資料報,校驗其反向路徑是否是最佳路 徑。如果反向路徑不是最佳路徑,則直接丟棄該資料報。參考 linux使用lvs dr或者阿...
填坑系列之更新CocoaPods
cocoapods的具體使用方法網上有很多,這裡不再贅述。在使用pod install安裝第三方庫時,可能會出現以下錯誤 出現這個問題是由於在swift3以後,很多框架需要在cocoapods1.1.0版本以上才能正常使用,因此我們需要更新cocoapods。終端輸入 curl l get.rvm....
採坑系列之JPA查詢
最近在研究spring的jpa的動態查詢,使用比較方便,但是著實也踩了不少的坑,簡單的總結一下。com.github.wenhao jpa spec 2.2.1 兩個關聯表 user和address 配置 引用lombok依賴便可以利用註解省略setter和getter方法,下面 是兩個關聯表多對多...