Amazon web services “信号器返回”;“需要连接ID”;在AWS ECS容器中运行时
我正试图获得一个带有角度前端的.NETCore3.1SignalerWebAPI来处理WebSocket 在本地运行时,无论是从IDE内部还是通过Amazon web services “信号器返回”;“需要连接ID”;在AWS ECS容器中运行时,amazon-web-services,asp.net-core,signalr,kestrel-http-server,Amazon Web Services,Asp.net Core,Signalr,Kestrel Http Server,我正试图获得一个带有角度前端的.NETCore3.1SignalerWebAPI来处理WebSocket 在本地运行时,无论是从IDE内部还是通过docker run运行,代码都可以正常运行。但是,一旦代码部署到API网关后面AWS中的ECS实例,web套接字将拒绝连接 我将映射设置为: app.UsePathBase("/ui"); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute(
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");
});
下面的Fiddler跟踪显示初始化websocket连接的初始HTTP请求以及kestrel返回的错误。
我调整了我的web套接字中间件,以处理访问令牌,并将其连接到控制台。编写一些我认为可能很有见地的额外调试语句:
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;
}
}
公共异步任务调用(HttpContext HttpContext)
{
var request=httpContext.request;
WriteLine($“启动连接id:{httpContext.connection.id}”);
//web套接字无法传递头,因此我们必须从查询参数和
//在运行身份验证中间件之前将其添加到标头
if(request.Path.StartsWithSegments(“/ws”,StringComparison.OrdinalIgnoreCase)
&&
request.Query.TryGetValue(“access_token”,out var accessToken))
{
Add(“Authorization”、$“Bearer{accessToken}”);
}
尝试
{
var sb=新的StringBuilder();
sb.AppendLine($“连接Id:{httpContext.Connection.Id}”);
Console.WriteLine(sb.ToString());
等待下一步(httpContext);
sb=新的StringBuilder();
sb.AppendLine($“状态代码{httpContext.Response.StatusCode}”);在Azure中,您必须启用AAR关联令牌,以确保客户端位于应用程序的同一实例上。因此,发生的情况是,第一个请求将发送到一个实例,然后第二个请求将发送到另一个实例。另一个实例与初始请求无关,因此它需要一个连接ID,因为它认为这是第一个请求。因此,请查找处理“会话状态”的设置并确保状态是持久的。我猜该请求没有作为websocket请求转发到服务器,Signal认为您正在尝试使用不支持跳过协商的LongPolling。@andy只有一个容器,因此没有其他实例可供使用。@Brennan我正按照您的思路思考,但我有long Pollinging已禁用。在执行套接字升级请求时,混合中会丢失一些内容。在这种情况下,长轮询是否被禁用并不重要。“正在执行的终结点”/ws/sessions”日志表示信号器终结点正在运行,并且是您唯一一次获得“需要的连接ID”如果您点击了LongPolling或SSE代码路径,则响应为(同样,在这里禁用LongPolling并不重要)。对于websocket请求,您应该点击这些按钮的唯一原因是网关/代理未正确转发升级请求的标头。您说您使用的是AWS API网关,可能需要对websocket进行一些配置。
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;
}
}