《构建微服务》一书详细描述了@RogerAlsing在他的回答中提到的风格。
在43页的编配vs编舞中,这本书说:
As we start to model more and more complex logic, we have to deal with
the problem of managing business processes that stretch across the
boundary of individual services. And with microservices, we’ll hit
this limit sooner than usual. [...] When it comes to actually
implementing this flow, there are two styles of architecture we could
follow. With orchestration, we rely on a central brain to guide and
drive the process, much like the conductor in an orchestra. With
choreography, we inform each part of the system of its job and let it
work out the details, like dancers all find‐ ing their way and
reacting to others around them in a ballet.
这本书接着解释了这两种风格。编排风格更多地对应于编排/任务服务的SOA思想,而编排风格对应于Martin Fowler的文章中提到的哑管道和智能端点。
编排风格
在这种风格下,上面的书提到:
Let’s think about what an orchestration solution would look like for
this flow. Here, probably the simplest thing to do would be to have
our customer service act as the central brain. On creation, it talks
to the loyalty points bank, email service, and postal service [...],
through a series of request/response calls. The
customer service itself can then track where a customer is in this
process. It can check to see if the customer’s account has been set
up, or the email sent, or the post delivered. We get to take the
flowchart [...] and model it directly into code. We could even use
tooling that implements this for us, perhaps using an appropriate
rules engine. Commercial tools exist for this very purpose in the form
of business process modeling software. Assuming we use synchronous
request/response, we could even know if each stage has worked [...]
The downside to this orchestration approach is that the customer
service can become too much of a central governing authority. It can
become the hub in the middle of a web and a central point where logic
starts to live. I have seen this approach result in a small number of
smart “god” services telling anemic CRUD-based services what to do.
Note: I suppose that when the author mentions tooling he's referring to something like BPM (e.g. Activity, Apache ODE, Camunda). As a matter of fact, the Workflow Patterns Website has an awesome set of patterns to do this kind of orchestration and it also offers evaluation details of different vendor tools that help to implement it this way. I don't think the author implies one is required to use one of these tools to implement this style of integration though, other lightweight orchestration frameworks could be used e.g. Spring Integration, Apache Camel or Mule ESB
然而,我读过的其他关于微服务主题的书籍以及我在网上找到的大多数文章似乎都不赞成这种编排方法,而是建议使用下一种方法。
编排风格
编舞风格下,作者说:
With a choreographed approach, we could instead just have the customer
service emit an event in an asynchronous manner, saying Customer
created. The email service, postal service, and loyalty points bank
then just subscribe to these events and react accordingly [...]
This approach is significantly more decoupled. If some
other service needed to reach to the creation of a customer, it just
needs to subscribe to the events and do its job when needed. The
downside is that the explicit view of the business process we see in
[the workflow] is now only implicitly reflected in our system [...]
This means additional work is needed to ensure that you can monitor
and track that the right things have happened. For example, would you
know if the loyalty points bank had a bug and for some reason didn’t
set up the correct account? One approach I like for dealing with this
is to build a monitoring system that explicitly matches the view of
the business process in [the workflow], but then tracks what each of
the services do as independent entities, letting you see odd
exceptions mapped onto the more explicit process flow. The [flowchart]
[...] isn’t the driving force, but just one lens through
which we can see how the system is behaving. In general, I have found
that systems that tend more toward the choreographed approach are more
loosely coupled, and are more flexible and amenable to change. You do
need to do extra work to monitor and track the processes across system
boundaries, however. I have found most heavily orchestrated
implementations to be extremely brittle, with a higher cost of change.
With that in mind, I strongly prefer aiming for a choreographed
system, where each service is smart enough to understand its role in
the whole dance.
注意:到目前为止,我仍然不确定编排是否只是事件驱动架构(EDA)的另一种名称,但是如果EDA只是实现它的一种方式,那么其他方式是什么?(另见“事件驱动”是什么意思?以及事件驱动架构的意义)。而且,CQRS和EventSourcing之类的东西似乎与这种架构风格有很多共鸣,对吧?
现在,在这之后是乐趣。微服务这本书并没有假设微服务将使用REST实现。事实上,在本书的下一节中,他们将继续考虑RPC和基于soa的解决方案,最后是REST。这里很重要的一点是,微服务并不意味着REST。
那么,HATEOAS怎么样?(超媒体作为应用状态的引擎)
现在,如果我们想要遵循RESTful方法,就不能忽视HATEOAS,否则Roy Fielding会很高兴地在他的博客中说,我们的解决方案不是真正的REST。参见他的博客文章《REST API必须是超文本驱动的》:
我对调用任何基于http的人的数量感到沮丧
接口一个REST API。需要做什么来制作REST
架构风格明确,超文本是一种概念
约束?换句话说,如果应用程序的引擎状态(和
因此API)不是由超文本驱动的,那么它就不可能是
RESTful的,不能是REST API。时期。有什么坏了的手册吗
某个需要修理的地方?
因此,如您所见,Fielding认为如果没有HATEOAS,就不能真正构建RESTful应用程序。对于Fielding来说,HATEOAS是编排服务的最佳方式。我只是在学习这一切,但对我来说,HATEOAS并没有清楚地定义谁或什么是真正遵循链接背后的驱动力。在UI中可能是用户,但在计算机对计算机交互中,我认为这需要由更高级别的服务来完成。
根据HATEOAS, API使用者真正需要知道的唯一链接是发起与服务器通信的链接(例如POST /order)。从这一点开始,REST将执行流,因为在此端点的响应中,返回的资源将包含到下一个可能状态的链接。然后API使用者决定遵循哪个链接并将应用程序移动到下一个状态。
尽管这听起来很酷,客户端仍然需要知道链接是否必须post、PUTed、GETed、PATCHed等等。客户端仍然需要决定传递什么有效负载。客户端仍然需要知道如果失败了该做什么(重试、补偿、取消等等)。
I am fairly new to all this, but for me, from HATEOAs perspective, this client, or API consumer is a high order service. If we think it from the perspective of a human, you can imagine an end-user on a web page, deciding what links to follow, but still, the programmer of the web page had to decide what method to use to invoke the links, and what payload to pass. So, to my point, in a computer-to-computer interaction, the computer takes the role of the end-user. Once more this is what we call an orchestrations service.
我认为我们可以将HATEOAS用于编配或编排。
API网关模式
Chris Richardson提出了另一个有趣的模式,他也提出了他所谓的API网关模式。
In a monolithic architecture, clients of the application, such as web
browsers and native applications, make HTTP requests via a load
balancer to one of N identical instances of the application. But in a
microservice architecture, the monolith has been replaced by a
collection of services. Consequently, a key question we need to answer
is what do the clients interact with?
An application client, such as a native mobile application, could make
RESTful HTTP requests to the individual services [...] On the surface
this might seem attractive. However, there is likely to be a
significant mismatch in granularity between the APIs of the individual
services and data required by the clients. For example, displaying one
web page could potentially require calls to large numbers of services.
Amazon.com, for example,
describes how some
pages require calls to 100+ services. Making that many requests, even
over a high-speed internet connection, let alone a lower-bandwidth,
higher-latency mobile network, would be very inefficient and result in
a poor user experience.
A much better approach is for clients to make a small number of
requests per-page, perhaps as few as one, over the Internet to a
front-end server known as an API gateway.
The API gateway sits between the application’s clients and the
microservices. It provides APIs that are tailored to the client. The
API gateway provides a coarse-grained API to mobile clients and a
finer-grained API to desktop clients that use a high-performance
network. In this example, the desktop clients make multiple requests
to retrieve information about a product, whereas a mobile client
makes a single request.
The API gateway handles incoming requests by making requests to some
number of microservices over the high-performance LAN. Netflix, for
example,
describes
how each request fans out to on average six backend services. In this
example, fine-grained requests from a desktop client are simply
proxied to the corresponding service, whereas each coarse-grained
request from a mobile client is handled by aggregating the results of
calling multiple services.
Not only does the API gateway optimize communication between clients
and the application, but it also encapsulates the details of the
microservices. This enables the microservices to evolve without
impacting the clients. For example, two microservices might be
merged. Another microservice might be partitioned into two or more
services. Only the API gateway needs to be updated to reflect these
changes. The clients are unaffected.
Now that we have looked at how the API gateway mediates between the
application and its clients, let’s now look at how to implement
communication between microservices.
这听起来与上面提到的编曲风格非常相似,只是意图略有不同,在这种情况下,它似乎都是关于性能和简化交互。