本文介绍了是否可以将REST和消息传递结合用于微服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们拥有基于微服务架构的应用程序的第一个版本.我们使用REST进行内部和外部通信.

We have the first version of an application based on a microservice architecture. We used REST for external and internal communication.

现在,我们想从CP(CAP定理)*切换到AP,并使用消息总线在微服务之间进行通信.关于如何基于Kafka,RabbitMQ等创建事件总线的信息很多.但是我找不到结合REST和消息传递的最佳实践.例如,您创建了汽车服务,并且需要添加不同的汽车组件.为此,将REST与POST请求一起使用会更有意义.另一方面,对于基于事件的方法,预订汽车的服务将是一项不错的任务.

Now we want to switch to AP from CP (CAP theorem)* and use a message bus for communication between microservices.There is a lot of information about how to create an event bus based on Kafka, RabbitMQ, etc.But I can't find any best practices for a combination of REST and messaging.For example, you create a car service and you need to add different car components. It would make more sense, for this purpose, to use REST with POST requests. On the other hand, a service for booking a car would be a good task for an event-based approach.

当您具有不同的字典和业务逻辑功能时,您是否也使用类似的方法?您如何将它们结合在一起?只是分别支持两种方法?还是用一种方法统一它们?

Do you have a similar approach when you have a different dictionary and business logic capabilities? How do you combine them? Just support both approaches separately? Or unify them in one approach?

*对于第一个版本,我们同意选择一致性和分区容限.但是现在可用性对我们来说变得越来越重要.

* for the first version, we agreed to choose consistency and partition tolerance. But now availability becomes more important for us.

推荐答案

最下面的底线:您正在寻找命令查询职责隔离;它定义了一种架构模式,用于分解从查询数据到请求运行流程的职责.简短的答案是,您不想以阻塞的方式在查询或流程中将两者混为一谈.该答案的其余部分将详细说明原因以及您可以按照自己的意愿去做的三种不同方式.

Bottom line up front: You're looking for Command Query Responsibility Segregation; which defines an architectural pattern for breaking up responsibilities from querying for data to asking for a process to be run. The short answer is you do not want to mix the two in either a query or a process in a blocking fashion. The rest of this answer will go into detail as to why, and the three different ways you can do what you're trying to do.

这个答案是我对微服务的经验的简短形式.我的真心实意:我从零开始创建了微服务拓扑(几乎是零知识),并且正如他们所说的那样,一直沿用到每个分支.

This answer is a short form of the experience I have with Microservices. My bona fides: I've created Microservices topologies from scratch (and nearly zero knowledge) and as they say hit every branch on the way down.

从零知识开始的好处之一是,我创建的第一个拓扑混合使用了服务内同步和阻塞(HTTP)通信(从保存它的服务中检索操作所需的数据),和消息队列+异步事件以运行操作(用于Commands).

One of the benefits of starting from zero-knowledge is that the first topology I created used a mixture of intra-service synchronous and blocking (HTTP) communication (to retrieve data needed for an operation from the service that held it), and message queues + asynchronous events to run operations (for Commands).

我将定义两个术语:

命令:告诉服务执行某项操作.例如,运行ETL批处理作业".您期望从中得到一个输出.但这肯定是一个过程,您将无法可靠地等待.命令有副作用.由于此操作,某些事情会发生变化(如果什么也没有发生并且什么都没有变化,那么您就什么也没做).

Commands: Telling a service to do something. For instance, "Run ETL Batch job". You expect there to be an output from this; but it is necessarily a process that you're not going to be able to reliably wait on. A command has side-effects. Something will change because of this action (If nothing happens and nothing changes, then you haven't done anything).

查询:向服务询问其保存的数据.此数据可能是由于发出命令而存在的,但要求数据不应有副作用.由于收到查询,因此无需 即可运行任何Command操作.

Query: Asking a service for data that it holds. This data may have been there because of a Command given, but asking for data should not have side effects. No Command operations should need to be run because of a Query received.

无论如何,回到拓扑.

对于第一个拓扑,我们将同步查询与发出的异步事件混合在一起.这是有问题的.

For this first topology, we mixed Synchronous Queries with Asynchronous Events being emitted. This was... problematic.

消息总线本质上是可以观察到的. RabbitMQ中的一项设置或事件源,您可以观察系统中的所有事件.这具有一些良好的副作用,即在过程中发生某些事情时,您通常可以找出导致该状态的事件(如果遵循事件驱动的范例+状态机).

Message Buses are by their nature observable. One setting in RabbitMQ, or an Event Source, and you can observe all events in the system. This has some good side-effects, in that when something happens in the process you can typically figure out what events led to that state (if you follow an event-driven paradigm + state machines).

如果不检查网络流量或记录这些请求,就无法观察到HTTP调用(这本身就有问题,因此在正常操作中,我们将从不可行"开始).因此,如果您将基于消息的流程和HTTP调用混合在一起,那么您将遇到无法分辨正在发生什么的漏洞.您将发现一些地方,由于网络错误,您的HTTP调用未返回数据,因此您的服务没有继续执行该过程.您还需要为HTTP调用挂接Retry/Circuit Breaker模式,以确保它们至少尝试几次,但是然后您必须区分由于关闭而没有启动"和因为暂时很忙而没有启动"之间的区别. .

HTTP Calls are not observable without inspecting network traffic or logging those requests (which itself has problems, so we're going to start with "not feasible" in normal operations). Therefore if you mix a message based process and HTTP calls, you're going to have holes where you can't tell what's going on. You'll have spots where due to a network error your HTTP call didn't return data, and your services didn't continue the process because of that. You'll also need to hook up Retry/Circuit Breaker patterns for your HTTP calls to ensure they at least try a few times, but then you have to differentiate between "Not up because it's down", and "Not up because it's momentarily busy".

简而言之,将两种方法混合用于命令驱动程序并不是很灵活.

In short, mixing the two methods for a Command Driven process is not very resilient.

在此成熟度模型的第二步中,将命令和查询分开.命令应使用事件驱动的系统,查询应通过HTTP进行.如果您需要查询命令的结果,则发出一条消息,并在消息总线上使用请求/响应模式.

In step two of this maturity model, you separate out Commands and Queries. Commands should use an event driven system, and queries should happen through HTTP. If you need the results of a query for a Command, then you issue a message and use a Request/Response pattern over your message bus.

这也有好处和问题.

从收益的角度来看,即使它跳过了多个服务,您的整个命令现在还是可以观察到的.您还可以通过重新运行事件来重播系统中的进程,这对于跟踪问题很有用.

Benefits-wise your entire Command is now observable, even as it hops through multiple services. You can also replay processes in the system by rerunning events, which can be useful in tracking down problems.

在问题方面,现在您的某些事件看起来很像查询;现在,您正在重新创建HTTP中可用于消息的漂亮的HTTP和REST语义;这并不是十分有趣或有用的.例如,一个404告诉您REST中没有数据.对于基于消息的事件,您必须重新创建这些语义(关于我找不到的关于主题很好的Youtube会议演讲,但是一个团队却竭尽全力做到这一点).

Problems-wise now some of your events look a lot like queries; and you're now recreating the beautiful HTTP and REST semantics available in HTTP for messages; and that's not terribly fun or useful. As an example, a 404 tells you there's no data in REST. For a message based event, you have to recreate those semantics (There's a good Youtube conference talk on the subject I can't find but a team tried to do just that with great pain).

但是,您的事件现在是异步的并且是非阻塞的,并且每个服务都可以重构为将响应给定事件的状态机.需要注意的是,这些事件应包含操作所需的所有数据(导致消息在整个过程中不断增长).

However, your events are now asynchronous and non-blocking, and every service can be refactored to a state-machine that will respond to a given event. Some caveats are those events should contain all the data needed for the operation (which leads to messages growing over the course of a process).

您的查询仍然可以使用HTTP进行外部通信;但是对于内部命令/过程,您将使用消息总线.

Your queries can still use HTTP for external communication; but for internal command/processes, you'd use the message bus.

我也不推荐这种方法(尽管这是第一种方法的进步).我不建议您这样做,因为您的事件开始会发生混乱,在微服务系统中,整个系统中的合同都是相同的.

I don't recommend this approach either (though it's a step up from the first approach). I don't recommend it because of the impurity your events start to take on, and in a microservices system having contracts be the same throughout the system is important.

成熟度模型中的第三步(当我离开项目时,我们就进入了这种范式)是用于生成数据的服务,以便在生成数据时发出事件.然后,这些数据将由侦听这些事件的服务记录下来,这些服务将使用(可能是)陈旧的数据来执行其操作.外部客户仍然使用HTTP.但是在内部,您会在产生新数据时发出事件,并且每个关心该数据的服务都会存储该数据以在需要时使用.这就是Michael Bryzek的演讲的症结所在以正确的方式设计微服务架构. Michael Bryzek是白标电子商务公司 Flow.io 的CTO.

The third step in the maturity model (and we were on our way to that paradigm when I departed from the project) is for services that produce data to issue events when that data is produced. That data is then jotted down by services listening for those events, and those services will use that (could be?) stale data to conduct their operations. External customers still use HTTP; but internally you emit events when new data is produced, and each service that cares about that data will store it to use when it needs to. This is the crux of Michael Bryzek's talk Designing Microservices Architecture the Right way. Michael Bryzek is the CTO of Flow.io, a white-label e-commerce company.

如果您想获得更深层次的答案以及其他问题,我将向您指出我关于该主题的博客帖子.

If you want a deeper answer along with other issues at play, I'll point you to my blog post on the subject.

这篇关于是否可以将REST和消息传递结合用于微服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 09:55