【问题标题】:Messages not coming thru to Azure SignalR Service消息未通过 Azure SignalR 服务
【发布时间】:2018-12-05 04:21:30
【问题描述】:

我正在使用 React 前端的 ASP.NET Core 2.2 应用程序中实现 Azure SignalR 服务。当我发送消息时,我没有收到任何错误,但我的消息没有到达 Azure SignalR 服务。

具体来说,这是一个私人聊天应用程序,因此当消息到达中心时,我只需将其发送给特定聊天的参与者,而不是发送给所有连接。

当我发送消息时,它会到达我的集线器,但我看不到消息正在发送到 Azure 服务的迹象。

为了安全,我使用 Auth0 JWT Token 认证。在我的中心,我正确地看到了授权用户的声明,所以我认为安全性没有任何问题。正如我所提到的,我能够访问集线器这一事实告诉我,前端和安全性工作正常。

然而,在 Azure 门户中,我看不到任何消息的指示,但如果我正确读取数据,我确实看到 2 个客户端连接在我的测试中是正确的,即我用于测试的两个打开的浏览器。这是屏幕截图:

这是我的Startup.cs 代码:

public void ConfigureServices(IServiceCollection services)
{
   // Omitted for brevity
   services.AddAuthentication(options => {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
   })
   .AddJwtBearer(jwtOptions => {
       jwtOptions.Authority = authority;
       jwtOptions.Audience = audience;

       jwtOptions.Events = new JwtBearerEvents
       {
            OnMessageReceived = context =>
            {
                var accessToken = context.Request.Query["access_token"];

                // Check to see if the message is coming into chat
                var path = context.HttpContext.Request.Path;
                if (!string.IsNullOrEmpty(accessToken) &&
                    (path.StartsWithSegments("/im")))
                {
                   context.Token = accessToken;
                }
                return System.Threading.Tasks.Task.CompletedTask;
             }
        };
    });


    // Add SignalR
    services.AddSignalR(hubOptions => {
       hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(10);
    }).AddAzureSignalR(Configuration["AzureSignalR:ConnectionString"]);
}

这是Configure() 方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
   // Omitted for brevity
   app.UseSignalRQueryStringAuth();

   app.UseAzureSignalR(routes =>
   {
      routes.MapHub<Hubs.IngridMessaging>("/im");
   });
}

这是我用来将用户的connectionId 映射到userName 的方法:

public override async Task OnConnectedAsync()
{
    // Get connectionId
    var connectionId = Context.ConnectionId;

    // Get current userId
    var userId = Utils.GetUserId(Context.User);

    // Add connection
    var connections = await _myServices.AddHubConnection(userId, connectionId);

    await Groups.AddToGroupAsync(connectionId, "Online Users");
    await base.OnConnectedAsync();
}

这是我的中心方法之一。请注意,我知道一个用户可能同时有多个连接。我只是简化了这里的代码以使其更易于消化。我的实际代码考虑了具有多个连接的用户:

[Authorize]
public async Task CreateConversation(Conversation conversation)
{
   // Get sender
   var user = Context.User;
   var connectionId = Context.ConnectionId;

   // Send message to all participants of this chat
   foreach(var person in conversation.Participants)
   {
       var userConnectionId = Utils.GetUserConnectionId(user.Id);
       await Clients.User(userConnectionId.ToString()).SendAsync("new_conversation", conversation.Message);
   }
}

知道我做错了什么导致消息无法到达 Azure SignalR 服务吗?

【问题讨论】:

  • 要进行故障排除,请尝试直接向已知连接发送消息,以查看消息是否可以通过。如果确实如此,那么您可以缩小聊天逻辑范围以找出可能的问题。
  • 我确保消息到达集线器,调用正确的方法并将消息发送到正确的 ConnectionId。我仍然在门户网站上看到 0 条消息,并且在“活动日志”下什么也没有。除了 Azure 门户上的“概述”选项卡和“活动日志”下的消息指示器之外,还有其他方法可以查看消息是否到达 Azure SignalR 服务?
  • 该问题是由 SignalR 的旧版本客户端脚本引起的。当我将它们升级到最新版本时,一切都开始正常了。
  • 这部分在我看来是错误的。但可能不会导致您的问题。看起来它正在发送给请求呼叫的用户,而不是所有参与者 // 向此聊天的所有参与者发送消息 foreach(var person in conversation.Participants) { var userConnectionId = Utils.GetUserConnectionId(user.Id) ;等待 Clients.User(userConnectionId.ToString()).SendAsync("new_conversation", conversation.Message); }
  • 在我使用 Azure 的 SignalR 的 3 个月中两次,该服务刚刚完全停止接收消息(尽管它仍在“运行”)。调用 SignalR 服务,发送消息,这是肯定的。但就接收而言,signalR 服务上没有任何记录。我的解决方案是发布一个新的 SignalR 服务并换掉连接细节。不是一个可行的长期解决方案。

标签: azure asp.net-core signalr asp.net-core-signalr azure-signalr


【解决方案1】:

这可能是由拼写错误的方法、错误的方法签名、错误的集线器名称、客户端上的重复方法名称或客户端上缺少 JSON 解析器造成的,因为它可能会在服务器上静默失败。

取自Calling methods between the client and server silently fails :

方法拼写错误、方法签名不正确或中心名称不正确

如果被调用方法的名称或签名与客户端上的适当方法不完全匹配,则调用将失败。验证服务器调用的方法名称是否与客户端上的方法名称匹配。此外,SignalR 使用驼峰式方法创建集线器代理,这在 JavaScript 中是合适的,因此在服务器上名为 SendMessage 的方法将在客户端代理中调用 sendMessage。如果您在服务器端代码中使用HubName 属性,请验证使用的名称是否与用于在客户端上创建集线器的名称相匹配。如果您不使用 HubName 属性,请验证 JavaScript 客户端中的中心名称是否为驼峰式,例如 chatHub 而不是 ChatHub。

客户端方法名重复

确认您在客户端上没有重复的方法,仅因大小写不同而不同。如果您的客户端应用程序有一个名为 sendMessage 的方法,请验证是否也有一个名为 SendMessage 的方法。

客户端缺少 JSON 解析器

SignalR 需要一个 JSON 解析器来序列化服务器和客户端之间的调用。如果您的客户端没有内置 JSON 解析器(例如 Internet Explorer 7),您需要在应用程序中包含一个。

更新

针对您的 cmets,我建议您尝试其中一个 Azure SignalR 示例,例如 Get Started with SignalR: a Chat Room Example,看看您是否得到相同的行为。

希望对你有帮助!

【讨论】:

  • 感谢您的回复,但这些建议均未应用于我的代码。一切似乎都是正确的。您是否知道一种方法来验证消息是否正在发送到 Azure SignalR 服务?我知道消息正在到达集线器并被发送到活动的 connectionId。换句话说,我验证了“发送”部分,但不确定如何验证 Azure SignalR 服务中的消息是“已接收”还是“未接收”。
  • 如果一个客户端收到来自第二个客户端的消息,或者客户端收到来自集线器的消息(例如当您的CreateConversation 被调用时),则表示通信正常。但是为什么您在 Message Count (max) 计数器中看不到任何值确实很奇怪。
猜你喜欢
  • 2022-09-23
  • 2017-10-07
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-13
相关资源
最近更新 更多