今天SignalR部署在测试环境服务器前端出现无法连接,前端报错如下:

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

Failed to start the transport 'WebSockets': null

Nginx 服务器配置支持SignalR (WebSocket)-LMLPHP

SignalR地址直接报错404

然后查看服务器端是否有什么问题,服务器端也有报错如下

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

Nginx 服务器配置支持SignalR (WebSocket)-LMLPHP

看前端报错看像是WebSocket问题,因为SignalR本质还是通过WebSocket来实现通信的,根据错误像是服务器不支持WebSocket,我们是使用的Nginx做代理的时候默认配置不支持WebSocket。需要修改代理设置,需要改代理请求头的设置。

主要修改如下,在location节点下面新增。

Nginx 服务器配置支持SignalR (WebSocket)-LMLPHP

文末有完整的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发现连接成功

Nginx 服务器配置支持SignalR (WebSocket)-LMLPHP

但是这个时候其他webapi接口无法请求了,swagger可以打开但是接口无法请求了报400

这个时候也想到了应该是Nginx问题,毕竟再没有修改Nginx的时候其他接口是可以使用的。当然如果SignalR和api业务服务器本来就是相互独立那么就不会存在这个情况,我的SignalR和业务服务接口都是在一起的。

原因就在于我们刚刚配置了Nginx代理时使用长连接,但是我们webapi其他接口都是短连接的。所以我们要将signal的连接代理和webapi其他接口的代理分开。

最后的设置如下

Nginx 服务器配置支持SignalR (WebSocket)-LMLPHP

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";

      }

   }
07-23 03:06