示例:
http {
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;
}
}
也許你也曾遇到為什么配置ws/wss協議相關的代理時總是不順利?最后一番搜索發現需要加上面三行,于是二話不講,ctrl+c/ctrl+v 一套帶走,reload一下, 完成了。
那么這三行到底有什么特殊本領呢?簡單看看:
proxy_http_version 1.1;
這一行沒啥說的,設置http協議版本1.1, 這個主要是為了下面的兩行做準備。
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade;
這兩行就是設置兩個請求頭 Upgrade、Connection,這兩個請求頭都是逐跳標頭(只能傳輸一次,不能透傳), 后端ws程序根據這兩個頭攜帶的信息來判斷是否使用ws協議來通信。
Upgrade
能且只能在http1.1版本中使用, 用來標識協議升級/轉換, 在我們這篇文章的背景下,這個頭信息一般是: Upgrade: websocket; 表示客戶端希望使用websocket協議通信, 那么后端的ws程序取到頭信息后會返回101狀態碼(協議轉換),此時瀏覽器就會使用當前的TCP連接建立websocket通道。
Connection
在本篇文章的背景下, Connection頭信息取值upgrade, 表示本次請求是一次協議升級(協議轉換)請求, 配合 Upgrade: websocket信息, 完整表達了這個請求要升級到websocket協議。
上面提到了反向代理和逐跳標頭,客戶端發起請求時是和反響代理服務器建立請求, 此時客戶端攜帶的 Upgrade、Connection頭是不會被反向代理服務器直接轉發到后端服務的(這就是逐跳標頭), 后端服務獲取不到這兩個頭信息自然也不會主動去切換協議。
因此,需要在反向代理服務器轉發上游時帶上客戶端原來的請求頭,才可以完成協議的升級或切換。
需要注意多層反向代理的場景,都要顯示指定頭信息才行,否則不得行。
wss只要在最外層的代理服務器上配置即可, 內層的代理服務器使用ws協議交互。