【问题标题】:Share SignalR Service with Blazor Server and Azure Function与 Blazor 服务器和 Azure 函数共享 SignalR 服务
【发布时间】:2021-05-27 12:44:32
【问题描述】:

我有一个在 Azure 应用服务上运行的 Web 应用。它是由 SignalR 服务支持的 Blazor 服务器。我还有一些由 Azure Function 执行的后台处理。功能完成后,我想通过 SignalR 向网络应用发送通知。

我通过在 Azure 函数上启用 SignalR 输出绑定来实现这一点。只要我将 Function App 视为 SignalR 集线器(即 Blazor 服务器为 Function App 创建一个HubConnection),我就能够接收从 Azure Function 发送的消息。

但是,在上述场景中,我必须配置在“无服务器”模式下运行的第二个 SignalR 实例。所以我想知道,有没有一种替代方法可以用来绕过无服务器设计?我可以只在 Azure Function 中使用 SignalR 客户端(并手动为第一个 SignalR 服务创建 HubConnection)吗?

或者对于 Azure 函数来说这有点太重了?以另一种方式创建推送通知会更好吗(例如,Blazor 服务器对服务总线队列做出反应并然后通过 SignalR 发送消息)?

【问题讨论】:

标签: azure-functions blazor-server-side azure-signalr


【解决方案1】:

所以我想出了两个可能的答案。在第一个版本中,我将 SignalR 客户端添加到 Azure Function:

[Function("SignalRFunction")]
public static async Task RunAsync([ServiceBusTrigger("import-request")] string json, FunctionContext context)
{
    var conn = new HubConnectionBuilder()
        .WithUrl( "https://localhost:5001" )
        .Build();

    await conn.StartAsync();
    await conn.InvokeAsync( "Broadcast", "me", "some message" );
}

这会连接到我的 Blazor 服务器上的集线器,并在我的 ImportHub 上调用广播消息:

public class ImportHub : Hub
{
    public const string HubUrl = "/import";

    public async Task Broadcast(string username, string message)
    {
        await Clients.All.SendAsync("Broadcast", username, message);
    }
}

但是使用这种方法,我会为每个函数调用创建一个 SignalR 连接。可能不是最好的计划。我可以将conn 变成static 对象(就像您可能对HttpClient 所做的那样),但我仍然需要调用StartAsync()。我不确定HubConnection 的最佳做法是什么。

相反,我选择了答案 2 - Azure 函数对 Blazor 服务器进行 api 调用。这是我现在的功能:

[Function("SignalRFunction")]
public static async Task RunAsync([ServiceBusTrigger("import-request")] string json, FunctionContext context)
{
    var client = RestService.For<IImportHubApi>( "https://localhost:5001" );

    await client.Broadcast("me", json);
}

对于客户,我正在使用 Refit:

public interface IImportHubApi
{
    [Get("/api/broadcast")]
    Task Broadcast( string user, string message );
}

在我的 Blazor 服务器上,我有以下 API 控制器:

[Route("api/broadcast")]
[ApiController]
public class BroadcastController : ControllerBase
{
    private readonly IHubContext<ImportHub> _hub;

    public BroadcastController(IHubContext<ImportHub> hub)
    {
        _hub = hub;
    }

    [HttpGet]
    public async Task Get(string user, string message)
    {
        await _hub.Clients.All.SendAsync("Broadcast", user, message);
    }
}

因此,我认为这允许我的 Azure 函数进行扩展(如果相关),而无需担心在使用一个 SignalR 服务(默认模式下)时管理连接。

但是,这是否是一个好主意(从安全的角度来看)是另一个问题。我认为只要推送通知不用于邪恶(即用于刷新显示,而不是启动某些进程),那么确保我的服务器代码仅使用通知来提示 UI 刷新是一个问题。

我们确实有一个在应用服务上运行的 API 服务器。所以我可以将这个 API 调用移到那里并将它放在防火墙后面(API 管理)。这样,广播只能在 VPC 内进行。我假设我可以锁定ImportHub,所以你必须先通过身份验证。

但我对其他人可能要说的话很感兴趣。欢迎任何建议!

【讨论】:

    猜你喜欢
    • 2022-07-01
    • 2020-01-21
    • 2022-06-30
    • 2017-01-13
    • 2019-11-21
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多