【问题标题】:Supporting multiple virtual chatrooms (e.g. with NServiceBus)支持多个虚拟聊天室(例如使用 NServiceBus)
【发布时间】:2016-10-28 04:51:10
【问题描述】:

我刚开始阅读大量有关服务总线架构的内容,并更仔细地研究了 NServiceBus 框架。我真的不知道如何设计多个私人上下文,其中一组客户对同一消息的副本感兴趣(例如聊天室应用程序)。

服务总线应该只存在一次,还是我会创建多个服务总线实例,每个虚拟聊天室一个,并为每个感兴趣的客户订阅一个消息处理程序实例?

它是否与我在 Azure 上下文中已经阅读过的主题和订阅的概念有关?

【问题讨论】:

    标签: azure nservicebus esb servicebus


    【解决方案1】:

    服务总线应该只存在一次,还是我会创建多个服务总线实例,每个虚拟聊天室一个,并为每个感兴趣的客户订阅一个消息处理程序实例?

    使用 NServiceBus 时,您将为您创建的每个 endpoint 配置一个总线。您可以将端点视为处理某些消息的服务。端点不是动态的,它们需要指定一个名称,以便其他端点可以配置为向它们发送消息或从它们接收消息。

    这取决于您的系统的要求,但我假设 虚拟聊天室 是您可以动态生成和/或在不再使用时删除的东西。 p>

    它是否与我在 Azure 上下文中已经阅读过的主题和订阅的概念有关?

    NServiceBus 和 Azure 服务总线都提供了进行发布/订阅的基础结构。

    我真的不知道如何设计多个私人上下文,其中一组客户对同一消息的副本感兴趣

    多个私有上下文到底是什么意思?我将您的问题理解为如何在客户和聊天室之间建立关系。您的描述中缺少的部分是持久性,即存储客户端和聊天室之间的关系。

    以 NServiceBus 为例,您可以有一个 ClientService 来处理有关客户端采取的任何操作的消息,以及一个 ChatroomService 来处理有关聊天室中发生的操作的消息。然后工作流程可以去:

    1. 客户端进入聊天室(客户端向客户端发送命令)
    2. ClientService 将信息添加到 Client 对象并对其进行更新(持久性)
    3. ClientService 向 ChatroomService 发送命令以更新与相应聊天室关联的客户端列表。 (命令)
    4. 聊天室服务更新订阅客户端列表(持久性)
    5. 另一个客户端在聊天室中创建了一个Post。 (客户端向 ClientService 发送命令)
    6. ClientService 使用新的Post 和创建它的客户 ID 以及发送到的聊天室 ID(命令)向 ChatroomService 发送命令
    7. ChatroomService 将Post 添加到相应聊天室中的Posts 列表中(持久性)
    8. ChatroomService 为列表中订阅相应聊天室(发布)的所有其他客户端生成事件
    9. ClientService 处理 ChatroomService 引发的事件并将Post 分发给其他订阅的客户端。 (订阅)

    我实际上并没有创建一个聊天室应用程序,所以这可能不是你的想法的最佳设计,但它提供了一种描述如何使用 NServiceBus 来创建应用程序的方法。您可以使用端点来设置服务,这些端点处理与系统中的对象相对应的消息。通过这种或类似的设计,您可以实现关注点分离,并且可以根据每种对象类型必须处理的流量按需扩展您的服务。

    编辑以根据 cmets 中的问题添加更具体的示例

    注意:将text message 的所有引用更改为Post,以便在NServiceBus 中chat messageIMessage 之间没有歧义。我一直在故意使用术语commandevent。在 NServiceBus 中,ICommand 是一种只能发送到一个端点的消息,而IEvent 是一种可以被多个端点发布和订阅的消息。

    如果示例不清楚,请致歉。我试图传达的是,您可以存储Clients 和Chatrooms 之间的关系,这样当Chatroom 获得新的Post 时,它可以仅分发给Clients与它有关。假设您有一个聊天室 CR 和 3 个客户 ABC,它们都在 CR 中。另外,假设我们有以下类:

    class Chatroom
    {
        Guid Id { get; set; }
        List<Client> Subscribers { get; set; }
        List<Posts> Posts { get; set; }
    }
    
    
    class Client
    {
        Guid Id { get; set; }
        List<Chatroom> Chatrooms { get; set; }
        ConnectionInfo Info { get; set; }
    }
    
    class Post
    {
        Guid Id { get; set; }
        Guid ClientId { get; set; }
        Guid ChatroomId { get; set; }
        string Text { get; set; } 
    }
    
    class NewPostCommand : ICommand
    {
        Post NewPost { get; set; }
    }
    
    class NewChatroomPostEvent : IEvent
    {
        Post NewPost { get; set; }
        Chatroom Chatroom { get; set; }
        List<Client> Subscribers { get; set; }
    }
    
    1. A 创建一个 PostCR,这是使用从客户端到 API 的 HTTP 调用来实现的。 API 是用作 ClientService 的 NServiceBus 服务的一部分。 API 调用会创建一个 Post,其中包含文本 A.IdCR.Id
    2. ClientService 使用刚刚创建的PostChatroomService 发送NewPostCommand
    3. ChatroomService 接收NewPostCommand 并将其传递给相应的处理程序。
    4. 处理程序使用Post 上的ChatroomId 在您的数据库中搜索相应的Chatroom (CR)。新的Post 被添加到CR.Posts 并更新数据库。
    5. Handler 从CR 中获取CR.Clients 减去Post.ClientId 的列表(导致BC)。
    6. 处理程序发布一个新的NewChatroomPostEvent,其中包含PostChatroomSubscribers
    7. ClientService 订阅NewChatroomPostEvent,接收消息并将其传递给相应的处理程序。
    8. ClientService 具有与客户端通信的所有功能(使用Client.Info)并将新的Post 发送到NewChatroomPostEvent.Subscribers 列表中的每个客户端(BC)。

    现在我们已经了解了新帖子的消息流,您可以想象如何处理在每个聊天室中添加和删除订阅者。客户端在进入或离开聊天室时会向 HTTP API 发送消息,ClientService 会向 ChatroomService 发送消息,后者将更新相应的Chatroom.Subscribers 列表。希望这能阐明您如何控制在新帖子到达时向哪些客户端发送更新。

    【讨论】:

    • 这个例子提供了非常好的洞察力。我认为我的困惑与我非常喜欢分层 OOP 结构这一事实有关,而常见的企业服务设计似乎更多地遵循过程编程风格,因此正如您提到的静态配置的端点。我只是认为可以创建一个动态端点之类的东西,只有对特定聊天室感兴趣的客户才会订阅。在您的示例中,我必须编写逻辑以仅向 ChatroomService 中的相关客户端发布?我可以向特定客户发布吗?
    • 添加了一个更具体的示例,其中包含类和示例消息用法。再一次,我有点想用这个例子来展示它,并且更多地试图提供一个示例 NServiceBus 用法来展示它如何用于您的应用程序。聊天室可能有更好的设计模式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多