场景;
我们目前有一个 Web 应用程序充当 Angular 客户端应用程序的 API,并且我们有一个单独的 azure 函数项目,我们在其中处理服务总线上排队的消息。我们有很多异步功能,用户在客户端上触发一个操作,由 api 处理,然后将一些消息排队到消息总线上。然后这些由功能项目处理。
现在我们正在尝试在客户端应用程序中添加“实时更新”。
这些实时更新的触发器可能都来自正在处理的消息,或正在调用的 api 上的其他端点。但我很挣扎。
使用 Microsoft 的代码示例,我成功地在 api 内设置了“聊天应用程序”,并使用集线器接收消息并将消息广播到聊天客户端应用程序。但我正在努力将我的 Azure Functions 连接到同一个信号服务,以便它也可以向聊天广播消息。
Web 应用程序设置:
在 Startup.cs 中的正确位置添加了以下代码行
services
.AddSignalR()
.AddAzureSignalR(configuration.GetConnectionString("SignalR"));
app.MapEndpoints(endpoints => {
endpoints.MapHub<ChatHub>("/chat");
});
创建了一个中心:ChatHub.cs
public class ChatHub : Hub
{
public async Task BroadcastMessage(string name, string message)
{
await Clients.All.SendAsync("broadcastMessage", name, message);
}
public async Task Echo(string name, string message)
{
await Clients.Client(Context.ConnectionId)
.SendAsync("echo", name, $"{message} (echo from server)");
}
}
到目前为止,客户端应用程序可以连接,并且作为用户,我既可以广播消息,也可以将消息回显给自己。
我在其中一个控制器上创建了一个端点,以便能够测试是否可以从控制器内向聊天发送消息:
[HttpPost("chat/message")]
public async Task<ActionResult> HandlePostChatMessage(string message)
{
await _chatUtil.SendChatMessage("ApiTrigger", message);
return NoContent();
}
现在我在函数项目中创建了一个计时器触发器,它还应该每 30 秒发送一次消息(作为测试以查看是否一切正常)
SendChatMessageTimerTrigger.cs
public class SendChatMessageTimerTrigger
{
[FunctionName(nameof(SendChatMessageTimerTrigger))]
public async Task Run(
[TimerTrigger("%Functions:" + nameof(SendChatMessageTimerTrigger) + ":TriggerSchedule%")] TimerInfo timerInfo,
[SignalR(ConnectionStringSetting = "ConnectionStrings:SignalR", HubName = "chat")] IAsyncCollector<SignalRMessage> signalRMessages)
{
await signalRMessages.AddAsync(
new SignalRMessage
{
Target = "broadcastMessage",
Arguments = new[] { "FunctionTrigger", $"Current time: {DateTimeOffset.UtcNow}" }
});
}
}
从我调试该函数可以看到,SignalR 已连接(因此找到了连接字符串)。方法执行时不会引发异常。但是,这些消息不会显示在客户端应用程序中。
有人知道为什么功能应用程序无法成功发送聊天消息吗?还是我还漏掉了其他东西?
是的,我们应该在 azure 门户中添加上游 url。
在开发中,您可以使用ngrok来公开Function_App_URL。而key我们可以留空。但如果要在生产环境中使用,则需要使用
API_KEY
。
所有详细步骤,您可以在这里找到。