使用Azure SignalR Service实现控制台应用日志传输失败排查
问题描述
开发一个通过Azure SignalR Service在控制台应用间传递日志的项目,包含发送端控制台应用、接收端控制台应用和连接SignalR的Azure Function。发送端已成功连接SignalR,但接收端无法接收日志,Azure SignalR门户显示消息数和出站流量均为0,调试时连接状态显示“已连接”。
相关代码
发送端控制台应用
class Program { static async Task Main(string[] args) { var connection = new HubConnectionBuilder() .WithUrl("<Functionapp Url>") .Build(); await connection.StartAsync(); Log.Logger = new LoggerConfiguration() .WriteTo.Console() .CreateLogger(); var sender = new LogSender(connection); string logMessage = $"Log from Sender at {DateTime.Now}"; while (true) { sender.SendLog(logMessage); } } } class LogSender { private readonly HubConnection _connection; public LogSender(HubConnection connection) { _connection = connection; } public async void SendLog(string message) { Log.Information(message); await _connection.InvokeAsync("SendLog", message); } }
接收端控制台应用
class Program { static async Task Main(string[] args) { var connection = new HubConnectionBuilder() .WithUrl("<FunctionUrl>") .Build(); connection.On<string>("ReceiveLog", log => { Console.WriteLine($"Received log: {log}"); }); connection.Closed += async (exception) => { Console.WriteLine($"Connection closed: {exception?.Message}"); }; try { await connection.StartAsync(); Console.WriteLine("Connected to SignalR hub."); } catch (Exception ex) { Console.WriteLine($"Error connecting to SignalR hub: {ex.Message}"); } Console.WriteLine("Listening for logs. Press any key to exit."); Console.ReadKey(); } }
Azure Function
public static class Function1 { [FunctionName("negotiate")] public static SignalRConnectionInfo Negotiate( [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req, [SignalRConnectionInfo(HubName = "loghub")] SignalRConnectionInfo connectionInfo) { return connectionInfo; } } public class loghub : ServerlessHub { public async Task SendLog(string message) { await Clients.All.SendAsync("ReceiveLog", message); } }
发送端项目文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.10" /> <PackageReference Include="Microsoft.Azure.SignalR" Version="1.25.2" /> <PackageReference Include="Serilog" Version="3.1.1" /> <PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" /> </ItemGroup> </Project>
接收端项目文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.10" /> <PackageReference Include="Microsoft.Azure.SignalR" Version="1.25.2" /> </ItemGroup> </Project>
Azure Function项目文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <AzureFunctionsVersion>v4</AzureFunctionsVersion> <UserSecretsId>88e61c2f-e8c0-47d9-a0ce-c401e2e6296a</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.SignalRService" Version="1.10.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" /> <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.4.0" /> </ItemGroup> <ItemGroup> <None Update="host.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> <None Update="local.settings.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToPublishDirectory>Never</CopyToPublishDirectory> </None> </ItemGroup> </Project>
问题排查与解决方案
1. 修复异步方法调用问题
发送端SendLog方法使用async void,会导致异常无法捕获、异步操作无法等待,进而引发消息发送失败。修改为async Task并在调用时添加等待:
// LogSender类修改 public async Task SendLog(string message) { Log.Information(message); try { await _connection.InvokeAsync("SendLog", message); Log.Information("消息发送成功"); } catch (Exception ex) { Log.Error(ex, "发送日志消息失败"); } } // Main方法循环修改 while (true) { string logMessage = $"Log from Sender at {DateTime.Now}"; await sender.SendLog(logMessage); await Task.Delay(1000); // 添加延迟避免高频发送压垮连接 }
2. 修正客户端连接URL
SignalR客户端需要连接到Function的Hub端点,而非Function根URL。正确格式为"<FunctionUrl>/hubs/loghub",其中loghub是Function中定义的HubName。修改发送端和接收端的连接代码:
var connection = new HubConnectionBuilder() .WithUrl("<FunctionUrl>/hubs/loghub") .Build();
3. 检查Azure Function配置
- 确保
local.settings.json(本地运行)或Azure应用配置中,已添加AzureSignalRConnectionString,值为Azure SignalR Service的连接字符串。 - 可在
host.json中添加SignalR路由配置(默认配置通常足够,可选):
{ "version": "2.0", "extensions": { "signalR": { "hubRoute": "/hubs/{hubName}" } } }
4. 确保ServerlessHub被正确识别
确认Azure Function项目引用的Microsoft.Azure.WebJobs.Extensions.SignalRService版本与v4 Function兼容,运行时会自动扫描继承ServerlessHub的类,无需额外配置。
5. 优化日志消息内容
原代码中日志消息在循环外定义,时间不会更新,修改为循环内生成,确保每条日志的时间都是最新的。
内容的提问来源于stack exchange,提问作者ish1104
相关产品推荐
相关产品推荐

