所以我想出了两个可能的答案。在第一个版本中,我将 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,所以你必须先通过身份验证。
但我对其他人可能要说的话很感兴趣。欢迎任何建议!