【问题标题】:Serverless Azure SignalR + sending message via. HubConnection无服务器 Azure SignalR + 通过发送消息。集线器连接
【发布时间】:2022-09-23 09:24:49
【问题描述】:

我有一个 Azure SignalR 无服务器实例;我创建了一个按预期工作的 Azure 函数协商终结点。我按照此处提供的“协商服务器”指南使用隔离的 Azure 函数进行了设置。

https://github.com/aspnet/AzureSignalR-samples/tree/main/samples/Management

然后,我使用来自同一链接的“SignalR 客户端”下的指导来创建客户端应用程序 - 主要是对事件的订阅,即 hubConnection.On(\“HubMethodName\”, action => { ... })。在这里使用 HubConnection 对象是理想的,因为 HubConnectionBuilder 是针对代理 URI 执行的 - 即 https://myfunctionapp.com/hubName,这会触发协商功能并返回 HubConnection 实际使用的连接详细信息。在这一点上,我还将指出 HubConnection 有一些与发送消息相关的方法 - 即 SendAsync(...) 和 InvokeAsync(...)。

在消息发布方面,文档似乎忽略了上述这些方法,而是指初始化一个ServiceManager创建一个HubContext,然后利用中心上下文提供的代理方法进行消息发送(即hubContext.Clients.All.发送异步(...))。我的问题是这个 ServiceManager / HubContext 感觉非常服务器端 - 它们是我在我的 Azure Function 上用来实现协商的对象,提供比发送/订阅更多的管理功能,并且不适合我的协商终结点的概念(ServiceBuilder 接受 Azure SignalR 连接字符串并且不利用协商终结点)。

话虽如此,我非常倾向于从我的客户端代码中排除 ServiceManager / HubContext 并且非常渴望弄清楚如何使用严格的 HubConnection 实例来使其工作。但是,使用 SendAsync / InvokeAsync 方法不会成功。首先,我通过创建一个发送消息的附加 Azure Function 端点来确认我的订阅工作成功。 _context.Clients.All.SendAsync(\"method\", \"some text\") 成功触发我的客户端订阅。但是,当我从客户端使用 hubConnection.SendAsync(\"method\", \"some text\") 方法时,不会触发我的订阅。

调查后,我发现实际上没有发送任何“消息”。在 Azure SignalR 日志中,我可以看到正在初始化的连接并且连接数在增加;但是,当我在 HubConnection 上调用 SendAsync(...) 时,消息计数统计信息不会改变。通过将传输模式更改为长轮询并使用 Fiddler,我确认在调用 hubConnection.SendAsync(...) 方法时正在发生 HTTP 发布 - 它确实对我的 Azure SignalR 服务执行 POST。

POST https://xxx.signalr.net/client/?hub=testhub&id=xxx HTTP/1.1
Host: xxx.service.signalr.net
User-Agent: Microsoft SignalR/6.0 (6.0.9+3fe12b935c03138f76364dc877a7e069e254b5b2; Windows NT; .NET; .NET 6.0.9)
X-Requested-With: XMLHttpRequest
Authorization: Bearer xxx
Content-Length: 88

{\"type\":1,\"target\":\"method\",\"arguments\":[\"test message\"]}

长话短说,这个 POST 不是在广播消息时应该发生的——至少不是我的意图。切入正题,看看我的“成功的测试用例”会发生什么——当服务器调用 hubContext.Clients.All.SendAsync(...) 时,它使用的逻辑与 HubConnection 的 SendAsync(... ) 方法。在这种情况下,我们看到 RestApiProvider 影响被调用的端点 (https://github.com/Azure/azure-signalr/blob/180cf1923e828c19967e2ad44bd5e3693bff4218/src/Microsoft.Azure.SignalR.Management/RestApiProvider.cs#L45)。

public Task<RestApiEndpoint> GetBroadcastEndpointAsync(string appName, string hubName, TimeSpan? lifetime = null, IReadOnlyList<string> excluded = null)
{
    var queries = excluded == null ? null : new Dictionary<string, StringValues>() { { \"excluded\", excluded.ToArray() } };
    return GenerateRestApiEndpointAsync(appName, hubName, \"/:send\", lifetime, queries);
}

在工作案例中(使用 HubContext.Clients.All.SendAsync),我们最终使用路径 \"api/testhub/:send?api-version=2022-06-01\" 对 Azure SignalR 服务执行 POST 和在非工作情况下(使用 HubConnetion.SendAsync),我们最终使用路径 \"client/?hub=testhub&id=xxx\" 对 Azure SignalR 服务执行 POST - 最显着的区别是 /api/ 与。 /client/ 端点路径。

这通过使用 Azure SignalR 的实时跟踪日志捕获一些实时日志得到进一步证实。

两者之间的区别似乎很根本,因为 HubConnection.SendAsync(...) 方法似乎放弃了 RestApiProvider 中包含的所有逻辑,并且无服务器 SignalR 实现没有默认 SignalR 服务模式的“具体”集线器方法做。

有没有人能够使用 HubConnection.SendAsync(...) 从无服务器 Azure SignalR 环境中的客户端成功发送消息?

标签: c# azure .net-core azure-functions azure-signalr


【解决方案1】:

以下三个链接为我提供了使用 Azure Functions 和无服务器 Azure SignalR 实现所需的知识。

https://github.com/aspnet/AzureSignalR-samples/tree/main/samples/BidirectionChat https://github.com/aspnet/AzureSignalR-samples/tree/main/samples/DotnetIsolated-BidirectionChat https://github.com/Azure/azure-signalr/issues/969

基本上,您确实需要在无服务器实现中定义该“集线器方法”。使用孤立的功能,它看起来像这样。

    [Function("Broadcast")]
    [SignalROutput(HubName = "TestHub")]
    public SignalRMessageAction Broadcast(
        [SignalREndpointsInput("TestHub")] SignalREndpoint[] endpoints,
        [SignalRTrigger("TestHub", "messages", "Broadcast", "message")] SignalRInvocationContext invocationContext, 
        string message)
    {
        return new SignalRMessageAction("Broadcast")
        {
            Arguments = new object[] { message },
            Endpoints = endpoints
        };
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 2017-02-10
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多