在 MassTransit 中发送、发布和 Request/Response
Send, Publish and Request/Response in MasstTransit
最近我正在尝试在我们的微服务生态系统中使用MassTransit。
根据 MassTransit 词汇和文档,我的理解是:
- 发布:向 1 个或多个订阅者发送消息(Pub/Sub 模式)以传播消息。
- Send: 用于像publish 一样以fire and forget 的方式发送消息,而是只用于一个接收者。与 Publish 的主要区别在于,在 Send 中,如果您的目的地没有收到消息,它将 return 异常。
- Requests:使用 request/reply 模式发送消息并在不同的通道中获得响应,以便能够从接收方获得响应值。
现在,我的问题是根据微服务的概念,遵循事件驱动的设计,我们使用Publish将消息(事件)传播到整个生态系统。但是这里 Send 的用法(用例)到底是什么?只是为了在接收者不存在时得到一个异常?
我的下一个问题是,使用 Publish、Send 和 Requests[=35 是个好方法吗? =] 同时在微服务生态系统中?例如传播事件的发布、命令的发送(即发即弃)以及从目的地获取响应的请求。
-----更新
我还发现 Chris Patterson 清除了很多东西。对我也有很大帮助。
Send
和 Publish
之间的区别与意图有关。
如您所述,Send
用于命令,Publish
用于事件。我曾在一个大型企业系统上工作过一次 运行 在 webMethods 上作为集成 engine/service 总线并且只使用了事件。我可以告诉你,这不太理想。如果命令和事件之间存在区别,那么对更多人来说会更有意义。无论如何,从技术上讲,一个消息需要排队,在那个级别上它并不重要,这就是为什么排队机制通常不会关心这种语义的原因。
用一个愚蠢的例子来说明这一点:Facebook 在我的时间轴上放置了 Event,我的一个朋友在特定的一天过生日。我可以直接回复(发送消息),也可以在我的时间线上发布消息并希望我的朋友看到。另一个愚蠢的例子:你发送一封电子邮件给 PersonA 和 CC 其他 4 个人,询问“请出示报告 ABC”。预计 PersonA 会生成报告或安排完成报告。如果同一封电子邮件作为收件人发送给了所有五个人(没有抄送),那么谁来做呢?我知道,即使 Publish
也可能有 1-1 recipient/topic 但如果另一个端点订阅了呢?那是什么意思?
所以发件人有责任(仍然像订阅一样可配置)确定Send
消息发往何处。对于我自己的服务总线,我使用 IMessageRouteProvider 接口的实现。我曾经开发的系统中的一个实际示例是收到的电子邮件必须将其正文转换为内容存储的图像(如果没记错的话,IBM FileNet P8)。由于我不会深入的原因,系统每晚 20 点停止并在早上 6 点重新启动。这导致通常需要转换大约 8000 封电子邮件的积压。转换端点将在大约 2 秒内处理一次转换,但这仍然需要一段时间才能完成。与此同时,Web 前端人员可以请求将 PDF 文件转换为分页的 TIFF 文件。现在,这些最终排在队列的末尾,他们将不得不等待数小时才能返回。解决方案是实现另一个转换端点,它有自己的队列,并将 Web 前端配置为发送相同的消息类型,例如ConvertDocumentCommand
到该“优先”队列进行处理。很容易做到。现在,如果那是一个发布,我将如何进行拆分?同一事件在不同情况下会转到 2 个不同的端点?好吧,您的系统可以有另一个订阅商店,但现在您需要同时维护两者。可能还有另一个答案,例如将此逻辑编码到发送位中,但这是一种设计选择,需要更改编码。
在我自己的 Shuttle.Esb 服务总线中,我只有 Send
和 Publish
。对于 request/response,发件人和收件人都有一个收件箱,一个请求将被发送 (Send
) 给收件人,然后它可以回复(也是一个 Send
但使用发件人的 URI) .
您的问题与地铁无关。 MassTransit 实现了在 Enterprise Integration Patterns
等流行资源上精心描述的众所周知的消息传递模式
正如 Eben 在他的回答中所写,使用何种模式的决定是由意图驱动的。每种模式的消息传递机制也存在技术差异。
Send 用于 commands,您告诉其他服务做某事。您无需等待回复(即发即忘),尽管您可能会通过其他方式(例如事件)确认操作成功或失败。
它是 point-to-point channel 的一个实现,您也可以在其中实现竞争消费者以扩展处理,但这些将是同一服务的实例。
对于使用 RabbitMQ 的 MassTransit,它是通过将消息发布到端点交换而不是消息类型交换来完成的,因此即使其他端点可以使用消息,也不会收到消息。
发布 用于 events。这是一种广播类型的传送或扇出。您可能正在发布没有人收听的事件,因此您真的不知道谁会使用它们。你也不期待任何回应。
它是 publish-subscribe channel 的实现。
带有 RabbitMQ 的 MassTransit 为发布的每种消息类型创建交换,并将消息发布到这些交换。消费者在他们的端点交换和消息交换之间创建绑定,因此每个消费者服务(不同的应用程序)将在他们独立的队列中获得这些。
请求-响应既可以用于需要确认的命令,也可以用于查询。
它是 request-reply 消息模式的实现。
MassTransit nice diagrams in the docs 解释了 RabbitMQ 的机制。
这些消息传递模式经常以不同的组合和变体用于复杂的分布式系统。
最近我正在尝试在我们的微服务生态系统中使用MassTransit。
根据 MassTransit 词汇和文档,我的理解是:
- 发布:向 1 个或多个订阅者发送消息(Pub/Sub 模式)以传播消息。
- Send: 用于像publish 一样以fire and forget 的方式发送消息,而是只用于一个接收者。与 Publish 的主要区别在于,在 Send 中,如果您的目的地没有收到消息,它将 return 异常。
- Requests:使用 request/reply 模式发送消息并在不同的通道中获得响应,以便能够从接收方获得响应值。
现在,我的问题是根据微服务的概念,遵循事件驱动的设计,我们使用Publish将消息(事件)传播到整个生态系统。但是这里 Send 的用法(用例)到底是什么?只是为了在接收者不存在时得到一个异常?
我的下一个问题是,使用 Publish、Send 和 Requests[=35 是个好方法吗? =] 同时在微服务生态系统中?例如传播事件的发布、命令的发送(即发即弃)以及从目的地获取响应的请求。
-----更新
我还发现
Send
和 Publish
之间的区别与意图有关。
如您所述,Send
用于命令,Publish
用于事件。我曾在一个大型企业系统上工作过一次 运行 在 webMethods 上作为集成 engine/service 总线并且只使用了事件。我可以告诉你,这不太理想。如果命令和事件之间存在区别,那么对更多人来说会更有意义。无论如何,从技术上讲,一个消息需要排队,在那个级别上它并不重要,这就是为什么排队机制通常不会关心这种语义的原因。
用一个愚蠢的例子来说明这一点:Facebook 在我的时间轴上放置了 Event,我的一个朋友在特定的一天过生日。我可以直接回复(发送消息),也可以在我的时间线上发布消息并希望我的朋友看到。另一个愚蠢的例子:你发送一封电子邮件给 PersonA 和 CC 其他 4 个人,询问“请出示报告 ABC”。预计 PersonA 会生成报告或安排完成报告。如果同一封电子邮件作为收件人发送给了所有五个人(没有抄送),那么谁来做呢?我知道,即使 Publish
也可能有 1-1 recipient/topic 但如果另一个端点订阅了呢?那是什么意思?
所以发件人有责任(仍然像订阅一样可配置)确定Send
消息发往何处。对于我自己的服务总线,我使用 IMessageRouteProvider 接口的实现。我曾经开发的系统中的一个实际示例是收到的电子邮件必须将其正文转换为内容存储的图像(如果没记错的话,IBM FileNet P8)。由于我不会深入的原因,系统每晚 20 点停止并在早上 6 点重新启动。这导致通常需要转换大约 8000 封电子邮件的积压。转换端点将在大约 2 秒内处理一次转换,但这仍然需要一段时间才能完成。与此同时,Web 前端人员可以请求将 PDF 文件转换为分页的 TIFF 文件。现在,这些最终排在队列的末尾,他们将不得不等待数小时才能返回。解决方案是实现另一个转换端点,它有自己的队列,并将 Web 前端配置为发送相同的消息类型,例如ConvertDocumentCommand
到该“优先”队列进行处理。很容易做到。现在,如果那是一个发布,我将如何进行拆分?同一事件在不同情况下会转到 2 个不同的端点?好吧,您的系统可以有另一个订阅商店,但现在您需要同时维护两者。可能还有另一个答案,例如将此逻辑编码到发送位中,但这是一种设计选择,需要更改编码。
在我自己的 Shuttle.Esb 服务总线中,我只有 Send
和 Publish
。对于 request/response,发件人和收件人都有一个收件箱,一个请求将被发送 (Send
) 给收件人,然后它可以回复(也是一个 Send
但使用发件人的 URI) .
您的问题与地铁无关。 MassTransit 实现了在 Enterprise Integration Patterns
等流行资源上精心描述的众所周知的消息传递模式正如 Eben 在他的回答中所写,使用何种模式的决定是由意图驱动的。每种模式的消息传递机制也存在技术差异。
Send 用于 commands,您告诉其他服务做某事。您无需等待回复(即发即忘),尽管您可能会通过其他方式(例如事件)确认操作成功或失败。
它是 point-to-point channel 的一个实现,您也可以在其中实现竞争消费者以扩展处理,但这些将是同一服务的实例。
对于使用 RabbitMQ 的 MassTransit,它是通过将消息发布到端点交换而不是消息类型交换来完成的,因此即使其他端点可以使用消息,也不会收到消息。
发布 用于 events。这是一种广播类型的传送或扇出。您可能正在发布没有人收听的事件,因此您真的不知道谁会使用它们。你也不期待任何回应。
它是 publish-subscribe channel 的实现。
带有 RabbitMQ 的 MassTransit 为发布的每种消息类型创建交换,并将消息发布到这些交换。消费者在他们的端点交换和消息交换之间创建绑定,因此每个消费者服务(不同的应用程序)将在他们独立的队列中获得这些。
请求-响应既可以用于需要确认的命令,也可以用于查询。
它是 request-reply 消息模式的实现。
MassTransit nice diagrams in the docs 解释了 RabbitMQ 的机制。
这些消息传递模式经常以不同的组合和变体用于复杂的分布式系统。