Nginx 服務器配置支持SignalR (WebSocket)
今天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"; } }