带有 IIS 10 和 ARR 3.0 的 SignalR
SignalR with IIS 10 and ARR 3.0
在 Visual Studio 开发机器前使用 ARR 3.0 作为反向代理时,我们无法让 SignalR 工作。连接已成功建立,但连接建立后应从 SignalR 服务器发送的初始帧从未发送,事实上,无法发送任何帧,这会导致客户端断开 WebSocket 连接。综上所述,"the websocket connection can establish, but can't transfer frames."
MVC 应用程序在没有反向代理的情况下工作。
我们已经尝试了以下线程中所有建议的解决方案:
- Websockets reverse proxy in IIS 8
- http://matthewmanela.com/blog/using-signalr-in-an-arr-cluster/
"negotiate"-请求的屏幕截图。
"connect"-请求的屏幕截图。
编辑 1
似乎正在发送连接帧,但在途中失败了。它在环回时通过 Wireshark 可见。
编辑 2
当我没有向 url 附加后缀时,SignalR 似乎可以与 ARR 一起使用。换句话说:
因此,我们设法解决了有问题的问题,并深入挖掘了根本原因,以便能够清楚地重现问题。它与完成重写的顺序有关,我们所做的是在我们的 ASP.NET MVC 应用程序中创建了一个辅助方法,如果来自发起的请求包含我们的重写路径后缀。
public static class RouteHelper
{
public static string Url(string url)
{
string orginalUrl = HttpContext.Current?.Request.Headers["X-Original-URL"];
if (!string.IsNullOrEmpty(orginalUrl))
{
if (orginalUrl.StartsWith("/" + "portal", true, CultureInfo.InvariantCulture)
|| orginalUrl.StartsWith("portal", true, CultureInfo.InvariantCulture))
{
url = "/" + "portal" + url;
}
}
return url;
}
}
我们将此方法用于 SignalR hub/connection 的集合 URL,如下所示:
$.connection.hub.url = '@RouteHelper.Url("/signalr")'
结果将是 $.connection.hub.url = '@RouteHelper.Url("/portal/signalr")'
很容易认为这会产生与创建执行此更改的出站重写规则相同的结果,但这是不正确的。
returns 从代理到客户端的响应将是相同的,但代理与后端网络服务器之间的通信将出现故障。
相反,我们为此创建了一个出站规则,如下所示:
<rule name="SignalRReverseProxySignalRHubsUrl">
<match filterByTags="None" pattern="connection.hub.url.*=.*['\"](.*)['\"]" />
<action type="Rewrite" value="connection.hub.url = "/portal{R:1}"" />
</rule>
我无法解释导致 SignalR 帧未到达的反向代理和后端 Web 服务器之间的内部情况,但我可以确认所有 URL 重写都需要在代理和逻辑上完成在模拟相同重写的应用程序中将无法正常工作,至少不会以上述方式工作。
在 Visual Studio 开发机器前使用 ARR 3.0 作为反向代理时,我们无法让 SignalR 工作。连接已成功建立,但连接建立后应从 SignalR 服务器发送的初始帧从未发送,事实上,无法发送任何帧,这会导致客户端断开 WebSocket 连接。综上所述,"the websocket connection can establish, but can't transfer frames."
MVC 应用程序在没有反向代理的情况下工作。
我们已经尝试了以下线程中所有建议的解决方案:
- Websockets reverse proxy in IIS 8
- http://matthewmanela.com/blog/using-signalr-in-an-arr-cluster/
"negotiate"-请求的屏幕截图。
"connect"-请求的屏幕截图。
编辑 1
似乎正在发送连接帧,但在途中失败了。它在环回时通过 Wireshark 可见。
编辑 2
当我没有向 url 附加后缀时,SignalR 似乎可以与 ARR 一起使用。换句话说:
因此,我们设法解决了有问题的问题,并深入挖掘了根本原因,以便能够清楚地重现问题。它与完成重写的顺序有关,我们所做的是在我们的 ASP.NET MVC 应用程序中创建了一个辅助方法,如果来自发起的请求包含我们的重写路径后缀。
public static class RouteHelper
{
public static string Url(string url)
{
string orginalUrl = HttpContext.Current?.Request.Headers["X-Original-URL"];
if (!string.IsNullOrEmpty(orginalUrl))
{
if (orginalUrl.StartsWith("/" + "portal", true, CultureInfo.InvariantCulture)
|| orginalUrl.StartsWith("portal", true, CultureInfo.InvariantCulture))
{
url = "/" + "portal" + url;
}
}
return url;
}
}
我们将此方法用于 SignalR hub/connection 的集合 URL,如下所示:
$.connection.hub.url = '@RouteHelper.Url("/signalr")'
结果将是 $.connection.hub.url = '@RouteHelper.Url("/portal/signalr")'
很容易认为这会产生与创建执行此更改的出站重写规则相同的结果,但这是不正确的。
returns 从代理到客户端的响应将是相同的,但代理与后端网络服务器之间的通信将出现故障。
相反,我们为此创建了一个出站规则,如下所示:
<rule name="SignalRReverseProxySignalRHubsUrl">
<match filterByTags="None" pattern="connection.hub.url.*=.*['\"](.*)['\"]" />
<action type="Rewrite" value="connection.hub.url = "/portal{R:1}"" />
</rule>
我无法解释导致 SignalR 帧未到达的反向代理和后端 Web 服务器之间的内部情况,但我可以确认所有 URL 重写都需要在代理和逻辑上完成在模拟相同重写的应用程序中将无法正常工作,至少不会以上述方式工作。