nginx-8 WebSocket代理

使用HTTP/1.1協(xié)議中的protocol_switch機(jī)制,可以將客戶端與服務(wù)器的連接協(xié)議由HTTP/1.1升級為WebSocket。

HTTP協(xié)議中的 hop-by-hop 頭部

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • TE
  • Trailers
  • Transfer-Encoding
  • Upgrade

只對單個傳輸級連接有效,不存儲于緩存,可以由代理服務(wù)器轉(zhuǎn)發(fā)。

HTTP method 之 CONNECT

CONNECT https://www.baidu.com HTTP/1.1
客戶端告訴代理服務(wù)器,替我訪問https://www.baidu.com,并將結(jié)果返回給我。


因為Upgrade是一個hop-by-hop頭部,所以不能直接從客戶端傳遞給被代理的服務(wù)器。使用正向代理時,客戶端可以CONNECT方法回避這個問題。對于反向代理卻回避不了,因為客戶端并不知道代理服務(wù)器的存在,更不知道請求需要在代理服務(wù)器上特殊處理。

版本1.3.13之后,nginx實現(xiàn)了一種特殊操作模式:如果被代理的服務(wù)器返回帶有101狀態(tài)碼的響應(yīng),并且客戶端通過請求中的Upgrade請求protocol_switch,則允許在客戶機(jī)和被代理的服務(wù)器之間設(shè)置隧道。

正如上面所說,作為hop-by-hop頭部,UpgradeConnection不能從客戶端直接傳遞給被代理的服務(wù)器。為了讓被代理的服務(wù)器可以接收到這兩個頭部,知道客戶端想要切換到WebSocket協(xié)議,必須由代理服務(wù)器顯示地轉(zhuǎn)發(fā)。

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

在一個更復(fù)雜的例子中,向代理服務(wù)器發(fā)出的請求中Connection頭字段的值取決于客戶端請求報頭中是否存在Upgrade字段:

http {
    # 若http_upgrade存在,Connection值為upgrade,升級協(xié)議
    # 若http_upgrade不存在,Connection值為close,關(guān)閉連接
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        ...

        location /chat/ {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }

默認(rèn)情況下,如果被代理的服務(wù)器在60s內(nèi)未傳輸任何數(shù)據(jù),連接就會被關(guān)閉。這個時間可由proxy_read_timeout指令修改?;蛘?,可以配置被代理的服務(wù)器定期發(fā)送 WebSocket ping幀 來重置超時并檢查連接是否仍然有效。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容