【问题标题】:Microservices Create Entity Implementation微服务创建实体实现
【发布时间】:2019-11-01 09:22:35
【问题描述】:

这是我在here 概述的问题的后续问题。

网关充当应用程序的入口点,客户端的每个请求都向该应用程序发出。然后网关将请求分配给负责的微服务并处理身份验证。

在这种情况下,网关监听HTTP POST /bok 并通知Microservice A 创建一本书。因此Microservice A ist 负责管理和存储有关图书实体的所有内容。


以下伪代码是该架构的简化实现:

队列通信

网关

router.post('/book', (req, res) => {
  queue.publish('CreateBook', req.body);
  queue.consume('BookCreated', (book) => {
    const user = getUserFromOtherMicroService(book.userId);
    res.json({ book, user });
  });
});

微服务A

queue.consume('CreateBook', (payload) => {
  const book = createBook(payload);
  eventStore.insert('BookCreated', book);
  const createdBook = updateProjectionDatabase(book);
  queue.publish('BookCreated', createdBook);
})

但我对此不太确定,原因如下:

  1. 每次用户请求创建新书时,都会重新创建在Gateway 中使用BookCreated 的侦听器
  2. 如果 2 个用户同时创建一本书,并且返回错误的书会怎样?
  3. 我不知道如何获取其他数据(例如getUserFromOtherMicroService

这就是我考虑实施这种架构的原因:

直接和队列通信

网关

router.post('/book', async (req, res) => {
  const book = await makeHttpRequest('microservice-a/create-book', req.body);
  const user = await makeHttpRequest('microservice-b/getUser', book.userId);
  res.json({ book, user });
});

微服务A

router.post('/create-book', (req, res) => {
  const book = createBook(req.body);
  eventStore.insert('BookCreated', book);
  const createdBook = updateProjectionDatabase(book);
  queue.publish('BookCreated', createdBook);
  res.json(createdBook);
})

但我也不太确定这个实现,因为:

  1. 创作后还书不违反CQRS吗? (因为我应该只返回OKERROR
  2. 在微服务系统中发出另一个 HTTP 请求是不是效率很低?

【问题讨论】:

  • 我有点搞不懂网关在这里是什么意思。通常网关是 api 网关或任何可以用作网关的应用程序。你能解释一下你到底想达到什么目的吗?实际上是您要解决的业务案例?你认为每个微服务会做什么?
  • 对不起,我在顶部添加了几行:)
  • 我认为这里的问题是网关的作用。在您的案例中,“网关”似乎是一个处理编排和通信逻辑的自定义应用程序(即发布和消费到/从适当的主题)。也许您应该尝试将图表中的“网关”替换为“微服务”,这可能有助于您确定哪种方法更好。
  • 如果我这样做,我会采用哪种方法(1 或 2)?
  • 我也忘了,网关应该处理身份验证

标签: node.js architecture microservices cqrs event-sourcing


【解决方案1】:

基于上面的 cmets 。

方法 1

在这种情况下,您的 api 网关将用于将消息放入队列中。如果您的流程需要很长时间并且您有一个队列工作人员坐在后面来接收消息和流程,那么这种方法更合适。但是您的客户端必须轮询才能获得结果。假设您正在寻找机票。你放下消息。你得到一个 ID 来投票。您的客户将继续轮询,直到结果可用。

但在这种情况下,您将面临挑战,当您删除消息时,您将如何生成客户端将轮询的 ID?您是否将 ID 分配给网关处的消息并放入队列并返回相同的 ID 供客户端轮询以获取结果?同样,这种方法适用于 web/worker 类型的场景。

方法 2

由于您的 API 网关是自定义应用程序,它将处理身份验证并将请求重定向到相应的服务。您的 Microsvc A 将创建书籍并发布事件,您的微服务 B 和 C 将使用它。您的网关将等待微服务 A 返回响应,其中包含已创建书籍的 ID(或新创建对象的事件元数据),因此您稍后无需轮询它,而客户端拥有它。如果您愿意,您可以从其他微服务获取其他信息,此时您可以获取并发送聚合响应。

对于微服务 A、B、C 中可用的任何数据,您都将通过网关获取。确保您的网关高度可用。

希望对您有所帮助。如果您有任何问题,请告诉我!

【讨论】:

  • 好吧,这完全有道理! CQRS呢……返回新创建的对象可以吗?
  • 你有什么理由使用 CQRS 吗?这是一个很棒的模式,但它有其自身的复杂性。是的,您可以使用已创建的 http 状态代码 201 返回对象
  • 你可能是对的......它只是增加了不必要的复杂性。我可能会再次向您寻求进一步的帮助,谢谢!
  • 不用担心。我正在使用 CQRS。除非您有非常具体的原因,否则请使用它。否则它可能会成为您系统的反模式
猜你喜欢
  • 2018-01-02
  • 2013-04-05
  • 2021-02-10
  • 2020-09-20
  • 2021-09-27
  • 2017-12-26
  • 2018-08-03
  • 2017-09-14
  • 1970-01-01
相关资源
最近更新 更多