Nginx 伺服器配置支援SignalR (WebSocket)

Cfan1236發表於2020-07-22

今天SignalR部署在測試環境伺服器前端出現無法連線,前端報錯如下:

failed: Error during WebSocket handshake: Unexpected response code: 200

Failed to start the transport 'WebSockets': null

SignalR地址直接報錯404

然後檢視伺服器端是否有什麼問題,伺服器端也有報錯如下

Microsoft.AspNetCore.SignalR.HubConnectionContext - Failed connection handshake.

看前端報錯看像是WebSocket問題,因為SignalR本質還是通過WebSocket來實現通訊的,根據錯誤像是伺服器不支援WebSocket,我們是使用的Nginx做代理的時候預設配置不支援WebSocket。需要修改代理設定,需要改代理請求頭的設定。

主要修改如下,在location節點下面新增。

文末有完整的nginx配置例項可複製。

proxy_http_version 1.1   

指定使用http版本,因為只有http1.1才支援長連線。

proxy_set_header Upgrade $http_upgrade

將客戶端http請求頭Upgrade 透傳過來

roxy_set_header Connection  “upgrade” 

upgrade意思是告訴伺服器使用最高版本協議進行通訊。

預設roxy_set_header Connection這裡如果不寫的話,在htt1.0中Connection  預設是close的,即連線請求完畢後就關閉。

以上歸根到底都是基於http頭進行設定修改,如果我們自己本身對http頭有更多瞭解,還是有很大幫助的。

按照這個修改,然後重啟Nginx。nginx –s reload。

再看前端signal發現連線成功

 

但是這個時候其他webapi介面無法請求了,swagger可以開啟但是介面無法請求了報400

這個時候也想到了應該是Nginx問題,畢竟再沒有修改Nginx的時候其他介面是可以使用的。當然如果SignalR和api業務伺服器本來就是相互獨立那麼就不會存在這個情況,我的SignalR和業務服務介面都是在一起的。

原因就在於我們剛剛配置了Nginx代理時使用長連線,但是我們webapi其他介面都是短連線的。所以我們要將signal的連線代理和webapi其他介面的代理分開。

最後的設定如下

location 就是Nginx的路由匹配,這樣新增後當我們請求url域名後面是SignalR則使用長連線進行代理轉發了。location通常我們還回用於靜態檔案的代理,這樣靜態檔案直接通過nginx就能返回到前端了。不需要請求到後端伺服器。

本次完整的nginx配置如下

server{
     listen 80;
     listen 443 ssl;
     #域名
     server_name t-aabb.com;
     #https配置證書和ssl
     ssl_certificate   cert/_.aabb.com.crt;
     ssl_certificate_key  cert/_.aabb.com.key;
     ssl_session_timeout 5m;
     ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_prefer_server_ciphers on;
     client_max_body_size 100m;
     
     #後端服務代理
     location / {
                proxy_pass http://192.168.0.28:8080;
                proxy_set_header Host $http_host;
               }
              
     #Signal代理
     location /SignalR { 
                       proxy_pass http://192.168.0.28:8080;
                       #啟用http長連線支援websocket
                       proxy_http_version 1.1;
                       proxy_set_header Upgrade $http_upgrade;
                       proxy_set_header Connection "upgrade";

      }

   }

 

相關文章