nginx: [emerg] unknown "connection_upgrade" variable

問題

clipboard.png
一天更新完主分支後啓動nginx,結果報錯:nginx: [emerg] unknown "connection_upgrade" variable

解決方法

網上查,發現是nginx配置文件出了問題,將下面map代碼塊補上即可。

   http {
    map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
   }

    server {
        location / {
                    #…
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
            }
        }
}

思考

雖然問題解決了,但後來我想知道爲什麼會出現這種情況,以及解決方法的真正原理。
這篇博客可以知道問題出在了nginx代理websocket上。

什麼是websocket

傳統的http通訊模式是:客戶端發起請求,服務端接收請求並作出響應。
clipboard.png

而websocket協議複用了http的握手通道,具體指的是,客戶端通過HTTP請求與WebSocket服務端協商升級協議。

第一步,建立連接,客戶端使用http報文的格式發起協議升級的請求,服務端響應協議升級。
clipboard.png

第二步,交換數據,客戶端與服務端可以使用websocket協議進行雙向通訊。
clipboard.png

nginx反向代理websocket

clipboard.png
首先,客戶端發起協議升級的請求,而nginx在攔截時需要識別出這是一個協議升級(upgrade)的請求,所以必須顯式設置升級(Upgrade head)和連接頭(Connection head),如下:

    location /sockjs-node/ {
    proxy_pass http://127.0.0.1:4200/sockjs-node/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

完成後,nginx將其作爲WebSocket連接處理。

clipboard.png

接着,服務器響應升級請求,由nginx做代理進行處理,這時,需要進行如下配置:

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
    
    server {
        ...
    }
}

這時就出現了一開始我所修改的地方,結合上面那段的內容,我大概可以猜出來map 代碼段該作用主要是根據客戶端請求中 $http_upgrade 的值,來構造改變 $connection_upgrade 的值,即根據變量 $http_upgrade 的值創建新的變量 $connection_upgrade。
由於我沒有進行map映射,它不知道connection_upgrade是什麼,所以就會出現unknown "connection_upgrade" variable錯誤。

總結

即使是小小的一點改動,背後也會隱藏龐大的信息。如果止步於解決問題,而不是探索問題,就永遠不會有進步。
參考文檔:
https://www.nginx.com/blog/we...
https://www.cnblogs.com/chyin...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章