支持多个虚拟聊天室(例如使用 NServiceBus)
Supporting multiple virtual chatrooms (e.g. with NServiceBus)
我刚刚开始大量阅读有关服务总线架构的文章,并更仔细地研究了 NServiceBus 框架。我真的不知道如何设计多个私人上下文,其中一组客户对同一消息的副本感兴趣(例如聊天室应用程序)。
服务总线应该只存在一次,还是我会创建多个服务总线实例,每个虚拟聊天室一个,并为每个感兴趣的客户端订阅一个消息处理程序实例?
这是否与我已经在 Azure 上下文中阅读过的主题和订阅的概念有关?
Is the service bus supposed to exist only once or would I create multiple service bus instances, one for each virtual chatroom, and subscribe a message handler instance for each interested client?
使用 NServiceBus 时,您将为创建的每个 endpoint 配置一个总线。您可以将端点视为处理某些消息的服务。端点不是动态的,它们需要指定一个名称,以便其他端点可以配置为向它们发送消息或从它们接收消息。
这取决于您的系统要求,但我假设 虚拟聊天室 是您可以动态生成的东西 and/or不再使用。
Does it have something to do with the concept of topics and subscribes which I already read about in the context of Azure?
NServiceBus 和 Azure 服务总线都提供基础结构来完成 pub/sub。
I am not really getting an idea on how to design multiple private contexts where a set of clients are interested in the copies of the same message
多个私有上下文到底是什么意思?我理解你的问题是如何在客户和聊天室之间建立关系。您的描述中缺少的部分是持久性,即存储客户端和聊天室之间的关系。
以 NServiceBus 为例,您可以有一个 ClientService 来处理有关客户端采取的任何操作的消息,以及一个 ChatroomService 来处理有关聊天室内发生的操作的消息。然后工作流程可以去:
- 客户端进入聊天室(客户端向客户端发送命令)
- ClientService向Client对象添加信息并更新(持久化)
- ClientService 向 ChatroomService 发送命令以更新与相应聊天室关联的客户端列表。 (命令)
- 聊天室服务更新订阅客户列表(持久性)
- 另一个客户端在聊天室中创建了一个
Post
。 (客户端向 ClientService 发送命令)
- ClientService 使用新的
Post
和创建它的客户端的 ID 以及它被发送到的聊天室的 ID 向 ChatroomService 发送命令(命令)
- ChatroomService 将
Post
添加到相应聊天室的 Posts
列表中(持久性)
- ChatroomService 为订阅相应聊天室(发布)的列表中的所有其他客户端生成事件
- ClientService 处理 ChatroomService 引发的事件并将
Post
分发给其他订阅的客户端。 (订阅)
我还没有真正创建过聊天室应用程序,因此这可能不是最适合您的想法的设计,但它提供了一种描述如何使用 NServiceBus 来创建应用程序的方法。您可以使用处理与系统中对象对应的消息的端点来设置服务。使用这种或类似的设计,您可以分离关注点,并可以根据每个对象类型必须处理的流量按需扩展您的服务。
编辑以根据评论中的问题添加更具体的示例
注意:将 text message
的所有引用更改为 Post
以便 NServiceBus 中 chat message
和 IMessage
之间没有歧义。我一直在故意使用术语 command
和 event
。在NServiceBus中,ICommand
是一种只能发送给1个端点的消息,而IEvent
是一种可以被多个端点发布和订阅的消息。
如果示例不清楚,我们深表歉意。我想表达的是,你可以存储 Client
s 和 Chatroom
s 之间的关系,这样当 Chatroom
得到一个新的 Post
时,它可以分发给只有与它相关的 Client
s。假设您有一个聊天室 CR
和 3 个客户端 A
、B
和 C
,它们都在 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; }
}
A
创建一个 Post
到 CR
,这是使用从客户端到 API 的 HTTP 调用实现的。 API 是充当 ClientService 的 NServiceBus 服务的一部分。 API 调用创建了一个包含文本 A.Id
和 CR.Id
. 的 Post
- ClientService 使用刚刚创建的
Post
将 NewPostCommand
发送到 ChatroomService
。
- ChatroomService 接收
NewPostCommand
并将其传递给适当的处理程序。
- 处理程序在
Post
上使用 ChatroomId
在您的数据库中搜索相应的 Chatroom
(CR)。新 Post
添加到 CR.Posts
并更新数据库。
- 处理程序从
CR
中获取 CR.Clients
减去 Post.ClientId
的列表(导致 B
和 C
)。
- Handler 发布了一个新的
NewChatroomPostEvent
,其中包含 Post
、Chatroom
和 Subscribers
。
- ClientService 订阅
NewChatroomPostEvent
,接收消息并将其传递给适当的处理程序。
- ClientService 具有与客户端通信的所有功能(使用
Client.Info
)并将新的 Post
发送到 NewChatroomPostEvent.Subscribers
列表中的每个客户端(B
和 C
).
现在我们已经了解了新 post 的消息流,您可以想象如何在每个聊天室中添加和删除订阅者。客户端在进入或离开聊天室时会向 HTTP API 发送消息,ClientService 会向 ChatroomService 发送消息,后者会更新相应的 Chatroom.Subscribers
列表。希望这能阐明您如何控制在新 post 到达时向哪些客户端发送更新。
我刚刚开始大量阅读有关服务总线架构的文章,并更仔细地研究了 NServiceBus 框架。我真的不知道如何设计多个私人上下文,其中一组客户对同一消息的副本感兴趣(例如聊天室应用程序)。
服务总线应该只存在一次,还是我会创建多个服务总线实例,每个虚拟聊天室一个,并为每个感兴趣的客户端订阅一个消息处理程序实例?
这是否与我已经在 Azure 上下文中阅读过的主题和订阅的概念有关?
Is the service bus supposed to exist only once or would I create multiple service bus instances, one for each virtual chatroom, and subscribe a message handler instance for each interested client?
使用 NServiceBus 时,您将为创建的每个 endpoint 配置一个总线。您可以将端点视为处理某些消息的服务。端点不是动态的,它们需要指定一个名称,以便其他端点可以配置为向它们发送消息或从它们接收消息。
这取决于您的系统要求,但我假设 虚拟聊天室 是您可以动态生成的东西 and/or不再使用。
Does it have something to do with the concept of topics and subscribes which I already read about in the context of Azure?
NServiceBus 和 Azure 服务总线都提供基础结构来完成 pub/sub。
I am not really getting an idea on how to design multiple private contexts where a set of clients are interested in the copies of the same message
多个私有上下文到底是什么意思?我理解你的问题是如何在客户和聊天室之间建立关系。您的描述中缺少的部分是持久性,即存储客户端和聊天室之间的关系。
以 NServiceBus 为例,您可以有一个 ClientService 来处理有关客户端采取的任何操作的消息,以及一个 ChatroomService 来处理有关聊天室内发生的操作的消息。然后工作流程可以去:
- 客户端进入聊天室(客户端向客户端发送命令)
- ClientService向Client对象添加信息并更新(持久化)
- ClientService 向 ChatroomService 发送命令以更新与相应聊天室关联的客户端列表。 (命令)
- 聊天室服务更新订阅客户列表(持久性)
- 另一个客户端在聊天室中创建了一个
Post
。 (客户端向 ClientService 发送命令) - ClientService 使用新的
Post
和创建它的客户端的 ID 以及它被发送到的聊天室的 ID 向 ChatroomService 发送命令(命令) - ChatroomService 将
Post
添加到相应聊天室的Posts
列表中(持久性) - ChatroomService 为订阅相应聊天室(发布)的列表中的所有其他客户端生成事件
- ClientService 处理 ChatroomService 引发的事件并将
Post
分发给其他订阅的客户端。 (订阅)
我还没有真正创建过聊天室应用程序,因此这可能不是最适合您的想法的设计,但它提供了一种描述如何使用 NServiceBus 来创建应用程序的方法。您可以使用处理与系统中对象对应的消息的端点来设置服务。使用这种或类似的设计,您可以分离关注点,并可以根据每个对象类型必须处理的流量按需扩展您的服务。
编辑以根据评论中的问题添加更具体的示例
注意:将 text message
的所有引用更改为 Post
以便 NServiceBus 中 chat message
和 IMessage
之间没有歧义。我一直在故意使用术语 command
和 event
。在NServiceBus中,ICommand
是一种只能发送给1个端点的消息,而IEvent
是一种可以被多个端点发布和订阅的消息。
如果示例不清楚,我们深表歉意。我想表达的是,你可以存储 Client
s 和 Chatroom
s 之间的关系,这样当 Chatroom
得到一个新的 Post
时,它可以分发给只有与它相关的 Client
s。假设您有一个聊天室 CR
和 3 个客户端 A
、B
和 C
,它们都在 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; }
}
A
创建一个Post
到CR
,这是使用从客户端到 API 的 HTTP 调用实现的。 API 是充当 ClientService 的 NServiceBus 服务的一部分。 API 调用创建了一个包含文本A.Id
和CR.Id
. 的 - ClientService 使用刚刚创建的
Post
将NewPostCommand
发送到ChatroomService
。 - ChatroomService 接收
NewPostCommand
并将其传递给适当的处理程序。 - 处理程序在
Post
上使用ChatroomId
在您的数据库中搜索相应的Chatroom
(CR)。新Post
添加到CR.Posts
并更新数据库。 - 处理程序从
CR
中获取CR.Clients
减去Post.ClientId
的列表(导致B
和C
)。 - Handler 发布了一个新的
NewChatroomPostEvent
,其中包含Post
、Chatroom
和Subscribers
。 - ClientService 订阅
NewChatroomPostEvent
,接收消息并将其传递给适当的处理程序。 - ClientService 具有与客户端通信的所有功能(使用
Client.Info
)并将新的Post
发送到NewChatroomPostEvent.Subscribers
列表中的每个客户端(B
和C
).
Post
现在我们已经了解了新 post 的消息流,您可以想象如何在每个聊天室中添加和删除订阅者。客户端在进入或离开聊天室时会向 HTTP API 发送消息,ClientService 会向 ChatroomService 发送消息,后者会更新相应的 Chatroom.Subscribers
列表。希望这能阐明您如何控制在新 post 到达时向哪些客户端发送更新。