将 REST Web API 应用程序与 SignalR 集成?

Posted

技术标签:

【中文标题】将 REST Web API 应用程序与 SignalR 集成?【英文标题】:Integrating REST Web API App with SignalR? 【发布时间】:2015-08-11 20:42:17 【问题描述】:

目标:通过在数据库中存储新消息(发布到 Web API)并将其推送到单个侦听客户端 (SignalR) 来促进 2 个用户之间的聊天。

这是我的担忧:

除了Command and Query Responsibility Segregation (CQRS) Pattern 和Event Sourcing Pattern 之外,我找不到任何解决此问题的设计模式。这两者似乎都专注于复杂的实时应用程序。我的应用程序有很多传统的 REST 功能,但目前唯一的实时组件是聊天,因此似乎没有必要使用其中一种模式。 是否有更简单的方法将基于 REST 的网站 (Web API) 与实时组件 (SignalR) 集成? 我现在所做的感觉就像是在混合两种完全不同的东西。

我想试试:

使用 events 将我的 POST 处理程序耦合到我的推送处理程序 - 虽然我不确定这对我有帮助,因为我不希望我的应用程序的“发送消息”部分从“接收”部分演变成一部分. 将我所有的推送逻辑转移到由消息代理处理的作业中 - 这似乎也没有必要,但会产生更好的分离。根据answer,我的理解是 SignalR 使用内存中的消息代理,因此广播不会等待接收消息,因此除非我真的需要扩展,否则不需要外部消息代理。李>

也许我的应用程序太简单了,需要更好的设计?

这是我目前所拥有的:

public class chatPush

    public chatPush()

    public push(string msg)
    
        try
            string jsonMsg = JsonConvert.SerializeObject(msg);
            await Clients.User(userId).send(jsonMsg);
        
        catch
        
            string errorMsg = //error with msg
            await Clients.User(userId).send(errorMsg);
        
    


async Task<IHttpActionResult> PostMessage(Message msg)

    db.Messages.Add(msg);

    try
    
        await db.SaveChangesAsync();
    
    catch
    
        //return error in JSON
    

    //if update succeeded push it out
    _chatPush.push(jsonMsg);

    return //Success or Error code

【问题讨论】:

【参考方案1】:

我认为您不需要使用任何复杂的设计模式,而您的需求就是这么简单。 SignalR 仅在 POST/etc 中运行良好。 API 和 MVC 的处理程序。

如果您需要扩展到多台前端服务器,更复杂的设计会为您提供帮助,因为每个用户只会连接到您的一个 SignalR 主机,因此您需要担心持久的用户连接映射通过背板或数据库。但是,一旦您需要,SignalR 就有很好的文档。

在基本设计方面我有几点建议:

1) 如果您在服务器端有 MessageHub,请创建 MessageHubHelper 以轻松将数据推送给正确的用户。

[Authorize]
public class MessageHub : Hub



public static class MessageHubHelper

    private static readonly IHubContext _hubContext =
        GlobalHost.ConnectionManager.GetHubContext<MessageHub>();

    public static IHubContext Context
    
        get  return _hubContext; 
    

    public static void Send(User user, Message message)
    
        _hubContext.Clients.User(GetUserId(user)).Send(message);
    

    public static void DoSomethingElse(User user, Message message)
    
        _hubContext.Clients.User(GetUserId(user)).DoSomethingElse(message);
    

    private static string GetUserId(User user)
    
        return user.IdentityUser.UserName;
    

2) 确保仅在数据库提交成功时才推送数据(例如,在 try 中的 SaveChangesAsync 之后,除非 catch 会提前抛出/返回)。

3) 您不需要手动处理 JSON。只需按下对象,C# SignalR 库就会为您处理编码和解码。

4) 根据我的经验,SignalR 的重新连接可能有点不稳定,尤其是使用 IUserIdProvider 时(我见过客户端和服务器都认为它们已重新连接但实际上没有推送通过的情况)。所以,我推荐https://github.com/DamianEdwards/NDCLondon2013/tree/master/UserPresence 之类的东西,以便为您提供更可靠(或至少更易于调试)的用户状态管理。

【讨论】:

以上是关于将 REST Web API 应用程序与 SignalR 集成?的主要内容,如果未能解决你的问题,请参考以下文章

RESTful API 与 Web 服务 API

c#,鉴于具有REST API的Web应用,并想添加每个REST API可以与之交互的Web套接字,在哪里定义ClientManager进行全局访问?

如何将我的 Rest Api 服务器与我的 Web Socket 服务器通信

如何将 Twitter API 用于超过 REST 速率限制的大型 Web 应用程序

使用 rest api 从 Web 应用程序将文件上传到 Azure 文件存储

基于Vue.js 与 WordPress Rest API 构建单页应用