在AWS ECS容器中运行时SignalR返回“需要连接ID”

问题描述

我正在尝试使用具有Angular前端的.Net Core 3.1 SignalR Web API来与websocket一起使用。

从IDE内部或通过docker run在本地运行时,代码可以正常运行。但是,一旦将代码部署到API网关后面的AWS中的ECS实例中,Web套接字就会拒绝连接。

我这样设置映射:

app.UsePathBase("/ui");
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
               "default","{controller}/{action=Index}/{id?}")
             .RequireCors(PolicyName);
    endpoints.MapHub<SessionHub>("/ws/session");
    endpoints.MapHub<SessionsHub>("/ws/sessions");
});

在客户端上,我像这样连接到集线器:

this.sessionsHubConnection = new HubConnectionBuilder()
  .withUrl(`${window.origin}/ws/sessions`,{
    skipNegotiation: true,transport: HttpTransportType.WebSockets,accesstokenFactory: () => this.getAccesstoken()
  })
  .withAutomaticReconnect()
  .build();

以下fiddler跟踪显示了初始化Websocket连接的初始HTTP请求以及kestrel返回的错误

enter image description here

我对Web套接字中间件进行了调整,以处理访问令牌,还Console.Write附加了一些我认为可能很有见地的调试语句:

public async Task Invoke(HttpContext httpContext)
{
    var request = httpContext.Request;
    Console.WriteLine($"Starting connection id: {httpContext.Connection.Id}");

    // web sockets cannot pass headers so we must take the access token from query param and
    // add it to the header before authentication middleware runs
    if (request.Path.StartsWithSegments("/ws",StringComparison.OrdinalIgnoreCase)
        &&
        request.Query.TryGetValue("access_token",out var accesstoken))
    {
        request.Headers.Add("Authorization",$"Bearer {accesstoken}");
    }

    try
    {
        var sb = new StringBuilder();
        sb.AppendLine($"Connection Id: {httpContext.Connection.Id}");
        Console.WriteLine(sb.ToString());

        await _next(httpContext);

        sb = new StringBuilder();
        sb.AppendLine($"Status code {httpContext.Response.StatusCode}"); <-- this line
        sb.AppendLine($"Connection Id: {httpContext.Connection.Id}");    <-- and this line
        Console.WriteLine(sb.ToString());
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
        Console.WriteLine(e.StackTrace);
        throw;
    }
}

在AWS日志中,您可以看到存在连接ID,但是由于某种原因,该连接ID被EndpointMiddleware(?)忽略了。

enter image description here

有什么想法会导致这种情况吗?我还不能排除的两个想法是:

  1. 我们的API网关处的HTTP / S终止使Kestrel感到困惑,因为浏览器客户端正在HTTPS下构建套接字请求,但就Kestrel而言,一切都通过HTTP进行通信?
  2. app.UsePathBase("/ui");使Kestrel感到困惑,并且所有Web套接字路径实际上应该是/ ui / ws / session吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)