【发布时间】:2022-01-21 02:32:59
【问题描述】:
我在 docker 环境中使用 .net core 3.1,指向安装了 ARR 的 IIS 反向代理。
更新
我设法让重写运行。 BNut,因为我不知道它为什么会这样工作,所以我无法回答这个问题。 我将重写规则从 localhost: 更改为 127.0.0.1: 现在握手有效。但它似乎仅适用于 ServerSentEvents 的 websocket 协议。
Error: Failed to start the transport 'WebSockets': Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.
但是已经安装了 Websockets。我正在使用 ARR3。 所以对我来说最后两个问题是: 为什么它与 IP 而不是 localhost 一起工作? (下面的完整配置) 为什么安装了WS还是报这个错误?
完全重写配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<urlCompression doStaticCompression="false" doDynamicCompression="false" />
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="wss://(.*)" />
<action type="Rewrite" url="wss://127.0.0.1:3101/{R:1}" />
</rule>
<rule name="ReverseProxyInboundRule2" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="https://127.0.0.1:3101/{R:1}" />
</rule>
</rules>
<outboundRules>
<rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
<match filterByTags="A, Form, Img" pattern="^http(s)?://127.0.0.1:3101/(.*)" />
<action type="Rewrite" value="http{R:1}://sub.example.com/{R:2}" />
</rule>
<preConditions>
<preCondition name="ResponseIsHtml1">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
编辑
感谢张小龙,我找到了问题的根源,但仍然不知道如何解决它。
我有一个通过 docker compose 在 Windows 服务器上运行的 docker 环境。 在那里,我将 IIS10 与 UrlRewrite 和 ARR3 以及 .net core 3.1 应用程序和 signalR 核心一起使用。 作为客户,我使用@microsoft/signalr 的打字稿版本(最新) 由于某些原因,我不知道连接是否正常,但握手呼叫以超时结束。 我在网上查看了一些解决方案并应用了这个:
- 为 wss:// 和 ws:// 添加了 URL 重写入站规则
- 增加了 signalR 的超时时间
- 在 ARR 中配置响应缓冲区(见下图)
- 启用失败的请求跟踪
docker env 与启用了 ARR 和 Websockets 功能的 IIS 在同一台服务器上运行。
Web-App 容器公开端口 6652,将其映射到 docker 容器中的端口 443。
我的重写规则定义如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<urlCompression doStaticCompression="false" doDynamicCompression="false" />
<rewrite>
<rules>
<rule name="WS reverse proxy" stopProcessing="true">
<match url="ws://devlocal.example.com" />
<conditions>
<add input="{CACHE_URL}" pattern="^(.+)://" />
</conditions>
<action type="Rewrite" url="{C:1}://127.0.0.1:6652" />
</rule>
<rule name="WSS reverse proxy" stopProcessing="true">
<match url="wss://devlocal.example.com" />
<conditions>
<add input="{CACHE_URL}" pattern="^(.+)://" />
</conditions>
<action type="Rewrite" url="{C:1}://127.0.0.1:6652" />
</rule>
<rule name="_Inbound_devlocal.example.com.com" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="{C:1}://localhost:6652/{R:1}" logRewrittenUrl="true" />
<conditions logicalGrouping="MatchAny">
<add input="{CACHE_URL}" pattern="^(.+)://" />
<add input="{HTTP_HOST}" pattern="^devlocal\.example.com\.com$" />
</conditions>
</rule>
</rules>
<outboundRules>
<rule name="_Outboundund_devlocal.example.com.com" stopProcessing="true">
<match filterByTags="A, Form, Img, Link, Script" pattern="^http(s)?://localhost:6652/(.*)" />
<action type="Rewrite" value="http{R:1}://devlocal.example.com.com/{R:2}" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
SignalR 配置为:
services.AddSignalR(hubOptions =>
{
hubOptions.ClientTimeoutInterval = TimeSpan.FromSeconds(240);
hubOptions.HandshakeTimeout = TimeSpan.FromSeconds(120);
hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(60);
hubOptions.EnableDetailedErrors = true;
hubOptions.MaximumReceiveMessageSize = 200;
hubOptions.StreamBufferCapacity = 300;
});
// Mappig hub like:
app.UseEndpoints(api =>
{
api.MapControllers();
api.MapHub<CommentsHub>("/sockR/hub");
}
);
signalR 客户端的跟踪日志显示它的握手调用以超时结束:
[2022-01-13T18:29:07.232Z] Information: Normalizing '/sockR/hub' to 'https://devlocal.example.com/sockR/hub'.
Utils.js:151 [2022-01-13T18:29:07.233Z] Debug: Starting HubConnection.
Utils.js:151 [2022-01-13T18:29:07.233Z] Debug: Starting connection with transfer format 'Text'.
Utils.js:147 [2022-01-13T18:29:07.342Z] Information: WebSocket connected to wss://devlocal.example.com/sockR/hub.
Utils.js:151 [2022-01-13T18:29:07.342Z] Debug: The HttpConnection connected successfully.
Utils.js:151 [2022-01-13T18:29:07.342Z] Debug: Sending handshake request.
Utils.js:147 [2022-01-13T18:29:07.342Z] Information: Using HubProtocol 'json'.
... After 3 minutes:
ERROR Error: Uncaught (in promise): Error: Server timeout elapsed without receiving a message from the server. Error: Server timeout elapsed without receiving a message from the server.
有什么方法可以调试为什么请求以超时结束?奇怪的是,我在服务器上也有一个 jira 实例。也通过具有相同设置的反向代理绑定,并且那里的 WSS/WS 调用不会失败。
【问题讨论】:
-
我认为你可以使用失败的请求跟踪来跟踪请求。检查 ARR 是否将请求正确转发到后端服务器。然后你可以知道超时发生在哪里,ARR 或后端服务器。
-
启用失败请求跟踪,但日志文件夹为空。应用程序可以写入我的机器上的文件夹
-
我的意思是你可以在 ARR 服务器上启用它,这样它就会显示它是否成功转发请求。如果文件夹为空,则表示它没有收到请求。
-
我的 docker env 与 iis 在同一台服务器上运行。计划是从 iis 站点(例如 sub.mydomain.com)反向代理到我在同一机器上的 docker 容器中运行的站点,因为计划是将来切换到 azure 或 aws。通过 http/https 的所有请求都可以正常工作,并且请求主机也被正确重写。我在控制台中看到的是握手似乎在集线器连接中起作用......只有在集线器上下文发送新消息时才会引发此错误。
-
更新似乎超时也发生在连接后。所以请求没有通过的理论是正确的。来自 signalR 的调试日志只是错误地说“已连接”。但是通过我上面的配置,wss 调用也应该通过。还是我的配置中遗漏了什么?
标签: asp.net-core iis signalr asp.net-core-signalr arr-3.0