SignalR服务器端消息推送 — 在外部向集线器推送消息

我们除了可以在集线器中向客户端推送消息,也可以在MVC控制器、托管服务等外部向客户端推送消息,这在一些场景中非常有用。

比如,在Web聊天室中,管理员通过控制器的操作方法把某一个群成员设置为群管理员了,我们就需要在操作方法中向所有客户推送这个消息;

再如,在后台的托管服务中,我们检测到数据发生变化了,就在托管服务中向客户端推送数据变化的通知。

下面来实现在后台中新增一个用户的时候,通知聊天室所有的客户端”欢迎新人XX加入”。

Hub类中可以从依赖注入容器中注入上下文服务,因此我们可以在ChatRoomHub中编写用户新增用户的AddUser方法,在AddUser中执行数据库插入新用户的操作,然后把消息推送给客户端。

这样在前端中新增用户的时候,我们直接通过SignalR调用ChatRoomHub中的AddUser方法来完成用户的新增。

不过,在使用SignalR的时候,Hub类中的方法不应该有数据库操作等比较耗时的操作,因为这会影响SignalR的性能,Hub类中的方法只应该用于消息的发布,而不应该用来写业务逻辑。

SignalR中客户端给服务器端传递消息的超时时间为30s,如果对Hub类中的方法的调用执行时间超过30s,程序就会报错。

虽然我们可以调整默认的超时时间,但是本书的作者强烈不建议这样做,因为如果出现Hub类中的方法执行时间很长,那么一定是在方法中编写了除了消息发布之外的代码。

因此,我们一般仍然在控制器中编写业务逻辑代码,只是通过集线器向客户端推送消息。

在Hub类之外,我们可以通过注入IHubContext<THub>来获取对集线器进行操作的服务,其中泛型THub为要操作的Hub类。

IHubContext中定义了可以进行客户端筛选的IHubClients类的Clients属性,以及进行分组操作的IGroupManager类的Groups属性,它们的用法和Hub类非常类似,这里不进行过多解释。

下面我们来实现WebAPI中完成新增用户操作后,向客户端推送消息的功能。

第1步

在ASP.NET Core Web API的控制器类中通过构造方法注入一个IHubContext服务,如以下代码所示:

C#
 //使用主构造函数注入IHubContext服务
 public class ChatRoomHub(IHubContext _hubContext):Hub

第2步

为控制器类增加一个用于新增用户的操作方法,如以下代码所示:

C#
   public async Task AddUser(User user)
   {
       //这里省略执行用户注册的代码
       //用SendAsync推送
       await _hubContext.Clients.All.SendAsync("UserAdded", user.Name);

   }

第3步

在前端中增加监听”UserAdded”消息的代码,并且把消息添加到聊天记录中,如以下代码所示:

C#
connection.on{'UserAdded',userName=>{
     
     state.message.push("系统消息:欢迎"+userName+"加入我们!");
});  

完成上面的代码后,运行项目,然后在WebAPI页面中调用AddUser方法新增用户,就可以在聊天室页面中看到在控制器中向客户端推送的消息了。

IHubContext接口和Hub类有如下的区别:

IHubContext接口中没有Hub类中的上下文属性Context;

IHubContext接口的Clients属性是IHubClients类型的,而Hub类中的Client属性IHubCallerClients类型的。

SIgnalR注意事项:
  • Hub类的生命周期是瞬态的
  • 建议把ASP.NET Core程序和SignalR服务器端部署到不同的服务器上,以免它们互相干扰。

订阅评论
提醒
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
滚动至顶部