WebSocket 結合 Nginx 實現網域名稱及 WSS 協議訪問

來源:互聯網
上載者:User

標籤:web

簡單瞭解一下 WebSocket

現在,很多網站為了實現推送技術,所用的技術都是輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對伺服器發出HTTP請求,然後由伺服器返回最新的資料給用戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向伺服器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效資料可能只是很小的一部分,顯然這樣會浪費很多的頻寬等資源。
在這種情況下,HTML5定義了WebSocket協議,能更好的節省伺服器資源和頻寬,並且能夠更即時地進行通訊。
WebSocket一種在單個 TCP 串連上進行全雙工系統通訊的協議。使得用戶端和伺服器之間的資料交換變得更加簡單,允許服務端主動向用戶端推送資料。在 WebSocket API 中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以建立持久性的串連,並進行雙向資料轉送。

以上資訊摘自維基百科(ht t p s: / / z h . w i ki p e d i a .o r g / w i ki / W e b So cket)

簡單點說,WebSocket 就是減小用戶端與伺服器端建立串連的次數,減小系統資源開銷,只需要一次 HTTP 握手,整個通訊過程是建立在一次串連/狀態中,也就避免了HTTP的非狀態性,服務端會一直與用戶端保持串連,直到你關閉請求,同時由原本的用戶端主動詢問,轉換為伺服器有資訊的時候推送。當然,它還能做即時通訊、更好的二進位支援、支援擴充、更好的壓縮效果等這些優點。

推薦一個知乎上叫 Ovear 的網友關於 WebSocket 原理的回答,嘻哈風格科普文,簡直不要更贊了!地址:htt p s :/ / w w w . z hi h u .c o m / q ue s t i o n /2 0 2 1 5 5 61 / a n s w e r/ 4 0 3 1 69 53 

 ws 和 wss 又是什麼鬼?

Websocket使用 ws 或 wss 的統一資源標誌符,類似於 HTTP 或 HTTPS,其中 wss 表示在 TLS 之上的 Websocket ,相當於 HTTPS 了。如:

ws://example.com/chatwss://example.com/chat

預設情況下,Websocket 的 ws 協議使用 80 連接埠;運行在TLS之上時,wss 協議預設使用 443 連接埠。其實說白了,wss 就是 ws 基於 SSL 的安全傳輸,與 HTTPS 一樣樣的道理。

如果你的網站是 HTTPS 協議的,那你就不能使用 ws:// 了,瀏覽器會 block 掉串連,和 HTTPS 下不允許 HTTP 要求一樣,如:
650) this.width=650;" src="http://images2015.cnblogs.com/blog/539095/201706/539095-20170622132037304-957589823.png" alt="ws_https" style="border:0px;" />

Mixed Content: The page at ‘https://domain.com/‘ was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint ‘ws://x.x.x.x:xxxx/‘. This request has been blocked; this endpoint must be available over WSS.

這種情況,毫無疑問我們就需要使用 wss:\\ 安全性通訊協定了,我們是不是簡單的把 ws:\\ 改為 wss:\\ 就行了?那試試唄。

改好了,報錯啦!!!
650) this.width=650;" src="http://images2015.cnblogs.com/blog/539095/201706/539095-20170622132057038-755170502.png" alt="wss_ip" style="border:0px;" />

VM512:35 WebSocket connection to ‘wss://IP地址:連接埠號碼/websocket‘ failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR

很明顯 SSL 協議錯誤,說明就是認證問題了。記著,這時候我們一直拿的是 IP地址 + 連接埠號碼 這種方式串連 WebSocket 的,這根本就沒有認證存在好麼,況且產生環境你也要用 IP地址 + 連接埠號碼 這種方式串連 WebSocket 嗎?肯定不行阿,要用網域名稱方式串連 WebSocket 阿。

Nginx 佈建網域名支援 WSS

不用廢話,直接在配置 HTTPS 網域名稱位置加入如下配置:

location /websocket {    proxy_pass http://backend;    proxy_http_version 1.1;    proxy_set_header Upgrade $http_upgrade;    proxy_set_header Connection "upgrade";}

接著拿網域名稱再次串連試一下,不出意外會看 101 狀態代碼:
650) this.width=650;" src="http://images2015.cnblogs.com/blog/539095/201706/539095-20170622132017570-2009453161.png" alt="upgrade_101" style="border:0px;" />

這樣就完成了,在 HTTPPS 下以網域名稱方式串連 WebSocket ,可以開心的玩耍了。

稍微解釋一下 Nginx 配置
Nginx 自從 1.3 版本就開始支援 WebSocket 了,並且可以為 WebSocket 應用程式做反向 Proxy和負載平衡。
WebSocket 和 HTTP 協議不同,但是 WebSocket 中的握手和 HTTP 中的握手相容,它使用 HTTP 中的 Upgrade 協議頭將串連從 HTTP 升級到 WebSocket,當用戶端發過來一個 Connection: Upgrade要求標頭時,Nginx 是不知道的,所以,當 Nginx Proxy 伺服器攔截到一個用戶端發來的 Upgrade 請求時,需要顯式來設定Connection 、Upgrade 頭資訊,並使用 101(交換協議)返迴響應,在用戶端和Proxy 伺服器、後端伺服器之間建立隧道來支援 WebSocket。

當然,還需要注意一下,WebSockets 仍然受到 Nginx 預設為60秒的 proxy_read_timeout 的影響。這意味著,如果你有一個程式使用了 WebSockets,但又可能超過60秒不發送任何資料的話,那你要麼需要增加逾時時間,要麼實現一個 ping 的訊息以保持聯絡。使用 ping 的解決方案有額外的好處,可以發現串連是否被意外關閉。

更具體文檔詳見 Nginx 官方文檔:ht t p :/ / n g i n x. o r g /e n / d o cs / h t t p/ w e bs o c k et . html

總結一下

這一篇文章主要瞭解一下 WebSocket 基本原理和一些使用用途,並解決在實際開發使用過程中遇到的坑,HTTPS 下使用 wss 協議的問題,以及配合 Nginx 使用網域名稱方式建立串連,不使用 IP地址 + 連接埠號碼 串連 WebSocket,因為這種方式不夠優雅。


WebSocket 結合 Nginx 實現網域名稱及 WSS 協議訪問

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.