如何通过Azure Function的TimerTrigger定时向Azure SignalR Service广播消息
解决方案
问题根因
你原来的实现是将Azure Function作为普通SignalR客户端连接Hub,而SendMessageToGroup属于服务端操作,普通客户端没有直接调用该方法推送消息的权限,所以会触发connectionId相关的权限校验报错。
方案1:使用Azure SignalR服务 + Azure Function SignalR输出绑定(推荐)
这是最简便的实现方式,不需要手动维护SignalR连接:
步骤1:安装依赖NuGet包
Install-Package Microsoft.Azure.WebJobs.Extensions.SignalRService
步骤2:配置连接字符串
在项目配置文件(本地调试用local.settings.json,云端用Function应用配置)中添加Azure SignalR服务的连接字符串,Key为AzureSignalRConnectionString。
步骤3:修改Function代码
[FunctionName("SendMessage")] public static async Task RunAsync( [TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, [SignalR(HubName = "MessageHub")] IAsyncCollector<SignalRMessage> signalRMessages, ILogger log) { // 向指定组发送消息 await signalRMessages.AddAsync( new SignalRMessage { GroupName = "Group2", Target = "ReceiveMessage", // 需和客户端监听的方法名保持一致 Arguments = new[] { "This is a test" } }); // 如果需要全局广播给所有客户端,去掉GroupName属性即可 // await signalRMessages.AddAsync( // new SignalRMessage // { // Target = "ReceiveMessage", // Arguments = new[] { "This is a global broadcast" } // }); }
方案2:自托管SignalR服务的实现方式
如果你用的是自托管的ASP.NET Core SignalR,没有使用Azure SignalR服务,按以下步骤实现:
步骤1:在SignalR服务端暴露管理接口
在自托管的ASP.NET Core项目中新增API控制器,注入IHubContext实现消息推送,建议加API密钥做权限校验避免恶意调用:
[ApiController] [Route("api/[controller]")] public class SignalRAdminController : ControllerBase { private readonly IHubContext<MessageHub> _hubContext; private const string ValidApiKey = "你自定义的接口调用密钥"; public SignalRAdminController(IHubContext<MessageHub> hubContext) { _hubContext = hubContext; } [HttpPost("send-to-group")] public async Task<IActionResult> SendToGroup([FromQuery] string apiKey, [FromQuery] string groupName, [FromQuery] string message) { if (apiKey != ValidApiKey) return Unauthorized(); await _hubContext.Clients.Group(groupName).SendAsync("ReceiveMessage", message); return Ok(); } }
步骤2:修改Azure Function代码,调用上述API接口
[FunctionName("SendMessage")] public static async Task RunAsync([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, ILogger log) { using var httpClient = new HttpClient(); // 替换为你自托管服务的实际地址 var requestUrl = "http://localhost:5003/api/SignalRAdmin/send-to-group?apiKey=你自定义的接口调用密钥&groupName=Group2&message=This is a test"; await httpClient.PostAsync(requestUrl, null); }
内容的提问来源于stack exchange,提问作者Tim Cadieux
相关产品推荐
相关产品推荐

