我目前正在使用WebAPI和SignalR进行通信的Windows Azure应用程序。两个服务都通过OWIN托管在具有多个实例的Worker角色上。
当前解决方案
目前,我们在每台计算机上的端口443上使用WebAPI启动一个Owin主机,并在每台计算机上的instance input endpoint端口上启动一个SignalR Owin主机(例如10106-1010x)。
一切正常,但我们的一些客户坐在防火墙后面,除80/443外的所有端口都被阻止 - >所以没有websocket通信(WebAPI工作正常)。
新解决方案
我们正在每个实例上启动一个带有WebAPI和SignalR的Owin主机。因此HTTP和WebSocket流量都将通过端口443上的负载均衡器路由 - >没有更多的实例输入端点(并且没有更多的防火墙问题)。
问题
现在的问题是,有时可以建立WebSocket连接,有时不建立(浏览器独立)。如果无法建立连接,则控制台中将显示以下错误:
Error during WebSocket handshake: Unexpected response code: 400
No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.
我已经将角色实例ID添加到来自服务器的websocket响应消息,但无法找到任何(ir)规则(例如,单个实例不响应,... )。所有SignalR服务器似乎都已启动并运行,但有时无法建立连接。
您可以转到以下 link 来自行测试。如果您没有收到错误对话框(“连接到服务器丢失”)它正在运行,否则尝试多次刷新页面。
-
我不正在寻找SignalR的横向扩展功能(如here或here所述)。客户端只连接到一个(随机)服务器(工作者角色实例)并与服务器通信,直到发送关闭消息。如果他再次连接,他可以被路由到任何其他服务器。此外,服务器之间也没有通信。
更新/溶液
halter73是对的,每个实例都会生成自己的反CSRF令牌。为了避免这种情况,我实现了自己的IDataProtector / IDataProtectionProvider,类似于SO问题(参见here和here)。
答案 0 :(得分:2)
如果您可以查看400响应的内容(这可能很难,因为它是对WebSocket请求的SSL加密响应),您可能会看到类似于“ConnectionId格式不正确”的消息。 / p>
SignalR使用服务器的计算机密钥创建反CSRF令牌,但这要求服务器场中的所有服务器共享计算机密钥,以便在SignalR请求跳转服务器时正确解密令牌。 / negotiate是检索反CSRF令牌的请求。然后,当SignalR客户端使用反CSRF令牌发出/ connect请求时,如果/ connect请求由不创建令牌的其他服务器处理,则有时会失败,因此无法对其进行解密。
以下是遇到类似问题的人在GitHub上提出的问题:https://github.com/SignalR/SignalR/issues/2292。