本文为个人翻译,原文链接
上一篇文章讲了一个特殊的服务总线,即命令总线。现在我们回过头来看看其他服务总线,他们有什么相似或是不同之处。
什么是服务总线?
好像很难用简单的话来解释什么是服务总线。如果你在维基百科上查询服务总线,会看到一些关于企业级软件开发的术语定义,还列举了一些微软、IBM和Oracle的例子。这和我平时接触的PHP驱动的网络开发相比,完全是另一个世界。
我先用自己的话来总结一下什么是服务总线吧:
- 服务总线是组件之间传递信息的方式
- 消息是以DTO的形式,包含了需要执行的信息
- “消息发送组件”会创建消息并传递给总线
- “消息接收组件”会告知总线它想要消费的消息类型
- 当总线接收到消息时,会分发消息给接收者
- 总线是能够解耦组件的边界,发送者和接收者都不会感知到其他组件
- 由于解耦,总线能够让组件很高效地合作
- 而且因为总线是所有消息的“中间商”,可以给所有的消息增加功能,而不需要改动消息、发送者或接收者。例如给所有的消息加上日志打印或者给消息排序
希望这些描述能让你更清楚什么是服务总线。如果还不明白的话,可以看看我之前的文章,解释了什么是命令总线。那篇文章不会很抽象,而且有一些代码样例。
不同的总线
到目前为止,我们讨论了“通用的”服务总线。这个总线只会分发信息,无论如何也不会限定消息,或者是做一些处理。
你可以想象一下,不同类型的消息应该用不同的方式处理,这也是为什么我们有各种各样的服务总线,接下来我会讨论3种:
- 命令总线
- 查询总线
- 事件总线
我们来看一下它们的关键点
命令总线
- 消息(命令)标识了用户的意图。比如说“创建文章”或者“注册帐号”。
- 一个命令只能有一个确定的处理者
- 命令不会返回任何值
查询总线
- 消息(查询)标识了一次查询操作,注意不是数据库查询。比如“最新的文章”或者“文章的所有评论”
- 一个查询只能有一个确定的矗立着
- 查询会返回数据
- 查询不会改变应用的状态
事件总线
- 消息(事件)标识了一个已经发生的事件。比如“文章已创建”或者“用户已注册”。
- 一个事件可以有任意数量的处理者([0, inf])。
- 只会持有基础变量(字符串,整数值,布尔值),而不是整个类。
- 事件不会返回值
可以看到这些总线很相似,在我看来这也是他们很有用的原因。总线的概念很容易理解,使用也简单,可以给你的应用增强结构性和可预测性。
最后一点
验证
消息都应该被验证,这就意味着消息对象应该验证自己的入参,这样一来,只有有效的消息会被分发,也会带来一点限制。
“注册用户”命令应该需要(不考虑其他情况)一个用户名。这个命令应该要验证一下用户名是个字符串,并且字符的长度在6和100之间。而用户名是否唯一,这个需要由处理者来验证,而不是通过命令本身。
更大的模式
实现命令和查询是命令查询职责分离(CQRS)的一部分,当然你也可以不应用CQRS,直接使用服务总线。
命令和事件经常一起使用,比如“注册用户”命令完成后,会发送事件“用户已注册”。可以阅读 Matthias Noback 写的 From Commands To Events 。
拓展阅读
如果想更深入了解服务总线和消息:
- Mathias Verraes 写的 Messaging Flavours
- Robert Basic 写的 All Aboard The Service Bus
- Matthias Noback 写的 Some questions about the command bus
或者阅读我的其他文章: