使用 REST & PUB/SUB 的微服务间通信
Posted
技术标签:
【中文标题】使用 REST & PUB/SUB 的微服务间通信【英文标题】:Inter-microservices Communication using REST & PUB/SUB 【发布时间】:2016-03-13 13:08:48 【问题描述】:这仍然是我心中的一个理论。
我正在通过将事物拆分为微服务来重建我的后端。我想开始的微服务是: - 订单(存储订单详情和每个订单的状态) - 客户(存储客户详细信息、地址、预订的订单) - 服务提供商(存储服务提供商的详细信息、每个服务提供商的状态和位置、服务提供商当前正在处理的订单等) - 付款(存储每个订单的付款信息) - 渠道(通过电子邮件/短信/手机推送与客户沟通)
我希望能够使用 PUB/SUB 来创建带有相应数据的消息,该消息可供任何其他订阅该消息的微服务使用。
首先,我理解每个微服务都应该具有完整的代码和数据隔离的概念(因此,在不同的实例/虚拟机上);并且所有微服务都应严格使用 HTTP REST API 合约进行通信。
我的疑惑如下:
为了显示订单列表,我将使用订单数据库来获取所有订单。在每个订单文档(我将使用 MongoDB 进行存储)中,我将拥有一个 customer_id 外键。现在是使用customer_id解析customer_name的问题。 如果我需要在页面上显示 100 个订单并假设每个订单都有一个与之关联的唯一 customer_id,那么我是否需要执行 100 次 REST API 调用才能获取所有 100 个 customer_id 的名称? 或者,数据复制是解决这个问题的好方法吗?
我正在设想这样的事情。 PUB/SUB:商务中心人员将订单标记为已分配并选择服务提供商分配给该订单。这会在跨服务器 PUB/SUB 频道上创建一条消息。 然后,Channel 微服务(位于完全不同的实例/VM 上)捕获此消息并使用消息内容中的数据向服务提供商的设备发送推送消息和 SMS。 这可能吗?对问题 2 的更新:我希望 Order 微服务完全独立于将构建在它之上/并排构建的任何其他微服务。 Channel 微服务是一个微服务示例,它依赖于 Order 微服务中发生的事件。
另外,请指导我使用哪些技术/库。
我将开发的内容: 爪哇 MongoDB 每个微服务的 Amazon AWS 实例。
感谢任何人对此的帮助。 谢谢!
【问题讨论】:
【参考方案1】:#1
如果我需要显示 100 个订单并且每个订单都有一个唯一的 customer_id,我需要进行 100 次 REST API 调用吗?
不,只需使用 100 个 order_id 发出 1 个请求并返回 order_id customer_id 的字典
#2 这是一个请求
POST
/orders/new
"selected_service_provider_id" : "123"
...
哪个可以回复您order_id
,您可以在本地为客户打印或跟踪进度或您有什么。
在服务器端,您收到订单并进行处理。处理可以包括在某个阶段发送 SMS。此功能可以在收到此请求的原始服务内部实现,也可以作为对另一个专用服务的单独调用来实现。
【讨论】:
至 #2,我希望 Order 微服务完全独立于 Channel 微服务。另外,我希望 Channel 插入 Order,以便开发 Channel 微服务的人需要注意发送 SMS 的适当位置。不仅是 SMS/push,还有任何其他意想不到的微服务本身 你的服务是相互独立的——代码方面。它们通过 REST 集成。您将拥有通用的数据结构和 API。您创建一个数据传输对象并将其发送出去。您可以拥有一个处理管道树,最初将订单发送到根摄取 API,该 API 决定将您的消息路由到哪里。为此,服务必须知道其他服务的位置和接口。你不能让微服务完全独立。这样的系统将无法在内部交换消息,因为它不知道任何子组件。有意义吗? 那么,我不是想在跨服务器共享的 Pub/Sub 通道中生成消息,而是只能从 API 网关调用 API?另一个疑问,我的 API 网关能否将我的 API 请求转发到多个微服务的 API,而不仅仅是一个? (有点明显,但我很想知道它是怎么做的)。另外,请告诉我根据您的知识是否存在跨服务器发布订阅系统? 你一直问的很好,但问题太多了 :) 如果你想使用 REST,那么你的服务需要相互了解。您可以向多个服务发送一个请求。有点像这样:client => gateway => service1, service2, ..., serviceN, database(s)
。如果您想使用 pubsub - 那是另一回事。查看消息队列,例如 nservicebus 或 kafka(以及许多其他)
我确实想象过 API 网关不只是充当一对一的转发器,而是可以通过编程将请求转发给多个接收者。由于我从未构建过 API 网关,因此是这个问题。至于问题的质量/数量,哈哈,是的,仍在学习所有这些,所以问题可能会不断出现:-P。感谢你的帮助! :-D【参考方案2】:
对于您的第一个问题,您不需要执行 100 次查询,只需查询 100 个文档的数组,如下所示:
db.collection.find( _id : $in : [1,2,3,4] );
https://***.com/a/7713461/1384539
【讨论】:
那么,我会按顺序获得 100 个查询 ID 的 100 个响应对象吗(“按顺序”是关键)?【参考方案3】:我知道这个问题已有 1 年的历史,但我想将我的答案添加到第一点。
一种选择是使用某种形式的 CQRS 并在 OrderDB 上存储一些创建订单时的用户详细信息。这样,当您必须显示订单列表时,您已经拥有所需的所有详细信息。此外,订单文档将代表创建订单时用户状态的照片。
当然,如果您在存储订单时没有用户详细信息,您只需要对用户服务进行 GET 调用,但这将是 1 次调用,而不是 100 次。
【讨论】:
以上是关于使用 REST & PUB/SUB 的微服务间通信的主要内容,如果未能解决你的问题,请参考以下文章
Pub/Sub:似乎无法让本地模拟器与 Node.js 一起使用
Google Cloud Pub/Sub - Cloud Function & Bigquery - 数据插入未发生
socket.io 广播功能 & Redis pub/sub 架构