使用 Azure SignalR 管理 SDK
Azure SignalR 管理 SDK 可帮助你直接通过 Azure SignalR 服务管理 SignalR 客户端,例如广播消息。 因此,该 SDK 可以但不限于在无服务器环境中使用。 可以使用此 SDK 在任何环境(例如在控制台应用程序、Azure 函数或 Web 服务器)中管理连接到 Azure SignalR 服务的 SignalR 客户端。
注意
若要查看 SDK 版本 1.9.x 及更早版本的指南,请转到 Azure SignalR 服务管理 SDK(旧版)。 你可能还需要阅读迁移指南。
功能
功能 | 暂时 | 永久 |
---|---|---|
广播 | ✔ | ✔ |
广播(某些客户端除外) | ✔ | ✔ |
发送到客户端 | ✔ | ✔ |
发送到客户端 | ✔ | ✔ |
发送给用户 | ✔ | ✔ |
发送给用户 | ✔ | ✔ |
发送给组 | ✔ | ✔ |
发送到组 | ✔ | ✔ |
发送到组(某些客户端除外) | ✔ | ✔ |
将用户添加到组 | ✔ | ✔ |
从组中移除用户 | ✔ | ✔ |
检查某个用户是否在组中 | ✔ | ✔ |
支持多个 SignalR 服务实例 | ❌ | ✔ |
MessagePack 客户端支持 | 自 v1.21.0 起 | 自 v1.20.0 起 |
重试暂时性错误 | 自 v1.22.0 起 | ❌ |
功能仅随新的 API 提供
功能 | 暂时 | 永久 |
---|---|---|
检查连接是否存在 | ✔ | 自 v1.11 起 |
检查组是否存在 | ✔ | 自 v1.11 起 |
检查用户是否存在 | ✔ | 自 v1.11 起 |
关闭客户端连接 | ✔ | 自 v1.11 起 |
使用情况
本部分介绍如何使用管理 SDK。
创建 Service Manager
从 ServiceManagerBuilder
生成 ServiceManager
实例
var serviceManager = new ServiceManagerBuilder()
.WithOptions(option =>
{
option.ConnectionString = "<Your Azure SignalR Service Connection String>";
})
.WithLoggerFactory(loggerFactory)
.BuildServiceManager();
可以使用 ServiceManager
来检查 Azure SignalR 终结点运行状况并创建服务中心上下文。 以下部分提供了有关创建服务中心上下文的详细信息。
若要检查 Azure SignalR 终结点运行状况,可以使用 ServiceManager.IsServiceHealthy
方法。 如果有多个 Azure SignalR 终结点,则只会检查第一个终结点。
var health = await serviceManager.IsServiceHealthy(cancellationToken);
创建服务中心上下文
从 ServiceManager
创建 ServiceHubContext
实例:
var serviceHubContext = await serviceManager.CreateHubContextAsync("<Your Hub Name>",cancellationToken);
协商
在默认模式下,Azure SignalR 服务 SDK 会公开终结点 /<Your Hub Name>/negotiate
以进行协商。 SignalR 客户端会访问此终结点,然后重定向到 Azure SignalR 服务。
在无服务器模式下,我们建议托管协商终结点来为 SignalR 客户端的协商请求提供服务,并将客户端重定向到 Azure SignalR 服务。
提示
阅读有关 SignalR 协商协议重定向的更多详细信息。
若要将 SignalR 客户端重定向到 Azure SignalR 服务,端点和访问令牌都很有用。
可以使用 ServiceHubContext
实例为 SignalR 客户端生成终结点 URL 和相应的访问令牌,从而连接到 Azure SignalR 服务。
var negotiationResponse = await serviceHubContext.NegotiateAsync(new (){UserId = "<Your User Id>"});
假设中心终结点为 http://<Your Host Name>/<Your Hub Name>
,那么协商终结点为 http://<Your Host Name>/<Your Hub Name>/negotiate
。 托管协商终结点后,可以使用 SignalR 客户端连接到中心,如下所示:
var connection = new HubConnectionBuilder().WithUrl("http://<Your Host Name>/<Your Hub Name>").Build();
await connection.StartAsync();
有关如何使用管理 SDK 将 SignalR 客户端重定向到 Azure SignalR 服务的示例,请参阅此处。
发送消息和管理组
我们从 ServiceHubContextBuilder
生成的 ServiceHubContext
是实施和扩展 IServiceHubContext
的类。 可以使用它将消息发送到客户端和管理组。
try
{
// Broadcast
await hubContext.Clients.All.SendAsync(callbackName, obj1, obj2, ...);
// Send to user
await hubContext.Clients.User(userId).SendAsync(callbackName, obj1, obj2, ...);
// Send to group
await hubContext.Clients.Group(groupId).SendAsync(callbackName, obj1, obj2, ...);
// add user to group
await hubContext.UserGroups.AddToGroupAsync(userId, groupName);
// remove user from group
await hubContext.UserGroups.RemoveFromGroupAsync(userId, groupName);
}
finally
{
await hubContext.DisposeAsync();
}
强类型中心
强类型中心是一种编程模型,可以将客户端方法提取到接口中,从而避免拼写错误的方法名称或传递错误的参数类型等错误。
假设我们有一个名为 ReceivedMessage
的客户端方法,其中包含两个字符串参数。 如果没有强类型中心,可以通过 hubContext.Clients.All.SendAsync("ReceivedMessage", user, message)
广播到客户端。 使用强类型中心,首先定义如下所示的接口:
public interface IChatClient
{
Task ReceiveMessage(string user, string message);
}
然后,创建一个实施 IHubContext<Hub<T>, T>
的强类型中心上下文,其中,T
是客户端方法接口:
ServiceHubContext<IChatClient> serviceHubContext = await serviceManager.CreateHubContextAsync<IChatClient>(hubName, cancellationToken);
最后,可以直接调用该方法:
await Clients.All.ReceiveMessage(user, message);
除了在发送消息方面存在差异,你可以像使用 ServiceHubContext
一样与 ServiceHubContext<T>
协商或管理组。
在此处的 ASP.NET Core 文档中了解有关强类型中心的更多信息。
传输类型
此 SDK 可以使用两种传输类型与 Azure SignalR 服务通信:
- 暂时:为发送的每条消息创建 Http 请求 Azure SignalR 服务。 SDK 只需在暂时模式下封装 Azure SignalR 服务 REST API。 此类型在无法建立 WebSocket 连接时非常有用。
- 永久:首先创建 WebSocket 连接,然后发送此连接中的所有消息。 此类型在发送大量消息时非常有用。
消息中自变量的序列化行为摘要
序列化 | 暂时 | 永久 |
---|---|---|
默认 JSON 库 | Newtonsoft.Json |
与 ASP.NET Core SignalR 相同:Newtonsoft.Json 适用于 .NET Standard 2.0;System.Text.Json 适用于 .NET Core App 3.1 及更高版本 |
MessagePack 客户端支持 | 自 v1.21.0 起 | 自 v1.20.0 起 |
JSON 序列化
在管理 SDK 中,发送到客户端的方法参数被序列化为 JSON。 可以通过多种方式自定义 JSON 序列化。 我们按照从最推荐到最不推荐的顺序显示所有方法。
ServiceManagerOptions.UseJsonObjectSerializer(ObjectSerializer objectSerializer)
最推荐的方法是使用通用抽象类 ObjectSerializer
,因为它支持不同的 JSON 序列化库,例如 System.Text.Json
和 Newtonsoft.Json
,并且适用于所有传输类型。 通常,你不需要自己实施 ObjectSerializer
,因为已经提供了 System.Text.Json
和 Newtonsoft.Json
的便捷 JSON 实施。
使用
System.Text.Json
作为 JSON 处理库时,内置JsonObjectSerializer
将使用System.Text.Json.JsonSerializer
进行序列化/反序列化。 以下是使用驼峰式大小写命名法进行 JSON 序列化的示例:var serviceManager = new ServiceManagerBuilder() .WithOptions(o => { o.ConnectionString = "***"; o.UseJsonObjectSerializer(new JsonObjectSerializer(new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); }) .BuildServiceManager();
使用
Newtonsoft.Json
作为 JSON 处理库时,首先使用 .NET CLI 从 NuGet 安装软件包Microsoft.Azure.Core.NewtonsoftJson
:dotnet add package Microsoft.Azure.Core.NewtonsoftJson
以下是对
NewtonsoftJsonObjectSerializer
使用驼峰式大小写命名的示例:var serviceManager = new ServiceManagerBuilder() .WithOptions(o => { o.ConnectionString = "***"; o.UseJsonObjectSerializer(new NewtonsoftJsonObjectSerializer(new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() })); }) .BuildServiceManager();
使用其他 JSON 处理库时
你也可以自行实施
ObjectSerializer
。 以下链接可能有所帮助:
ServiceManagerBuilder.WithNewtonsoftJson(Action<NewtonsoftServiceHubProtocolOptions> configure)
此方法仅适用于 Newtonsoft.Json
用户。 以下是使用驼峰式大小写命名的示例:
var serviceManager = new ServiceManagerBuilder()
.WithNewtonsoftJson(o =>
{
o.PayloadSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
})
.BuildServiceManager();
ServiceManagerOptions.JsonSerializerSettings
(已弃用)
ServiceManagerOptions.JsonSerializerSettings
此方法仅适用于暂时性传输类型。 不使用此选项。
var serviceManager = new ServiceManagerBuilder()
.WithOptions(o =>
{
o.JsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
})
.BuildServiceManager();
消息包序列化
需要安装
Microsoft.AspNetCore.SignalR.Protocols.MessagePack
包。若要使用默认 JSON 协议并行添加 MessagePack 协议,请执行以下操作:
var serviceManagerBuilder = new ServiceManagerBuilder() .AddHubProtocol(new MessagePackHubProtocol());
若要完全控制中心协议,可以使用
var serviceManagerBuilder = new ServiceManagerBuilder() .WithHubProtocols(new MessagePackHubProtocol(), new JsonHubProtocol());
WithHubProtocols
首先清除现有协议,然后添加新协议。 还可以使用此方法移除 JSON 协议,并仅使用 MessagePack。
对于暂时模式,默认情况下,服务端会将 JSON 负载转换为 MessagePack 负载,这是支持 MessagePack 的传统方式。 但是,建议显式添加 MessagePack 中心协议,因为传统方式可能无法按预期工作。
HTTP 请求重试
对于暂时模式,此 SDK 提供在发生暂时性错误时自动重新发送请求的功能,前提是请求是幂等的。 若要启用此功能,可以使用 ServiceManagerOptions.RetryOptions
属性。
具体而言,将重试以下类型的请求:
对于向 SignalR 客户端发送消息的消息请求,如果 HTTP 响应状态代码大于 500,则 SDK 会重试该请求。 当 HTTP 响应代码等于 500 时,可能表示服务端超时,重试请求可能会导致重复消息。
对于其他类型的请求(例如向组添加连接),SDK 会在以下条件下重试请求:
- HTTP 响应状态代码在 5xx 范围内,或者请求超时,状态代码为 408(请求超时)。
- 请求超时,持续时间长于在
ServiceManagerOptions.HttpClientTimeout
中配置的超时长度。
SDK 只能重试幂等请求,即重复请求不会产生任何其他影响的请求。 如果请求不是幂等的,则可能需要手动处理重试。
后续步骤
本文介绍如何在应用程序中使用 SignalR 服务。 查看以下文章以了解有关 SignalR 服务的更多信息。