是时候改变你对微服务的认知了!

2019-04-27 09:37 admin

大部分时候,微服务都是建立在一种基于请求和响应的协议之上。比如,REST等。这种方式是自然的。我们只需要调用另外一个模块就是了,然后等待响应返回,然后继续。这样的方式确实也满足了我们的很多的场景:用户通过点击页面的一个按钮然后希望发生一些事情。

 

但是,当我们开始接触许多独立的service的时候,事情就发生改变了。随着service数量急速的增长,同步交互比例也随着service在急速增长。这时候,我们的service就会遇到很多的瓶颈。

于是,不幸的ops工程师们就被我们坑了,他们疲惫的奔波于一个又一个的service,拼凑在一起的二手信息片段,谁说了什么,去往哪里,什么时候发生?等等。。。

这是一个非常典型的问题。市面上也有一些解决方案。一种方案就是确保您的个人服务具有比您的系统更高的SLA。 Google提供了这样做的协议。另一种方法是简单地分解将服务绑定在一起的同步关系。

 

上面的做法都没有从模式上根本解决问题。我们可以使用异步机制来解决这个问题。比如,电商网站中你会发现这样的同步接口,比如getImage()或者processOrder(),也许你感觉蛮正常。调用了然后希望马上有一个响应。但当用户点击了“购买”后,触发了一个复杂且异步的处理过程。这个过程涉及到购买、送货上门给用户,这一切都是发生在当初的那一次的按钮点击。所以把一个程序处理逻辑切分成多个异步的处理,是我们需要解决的问题。这也正符合我们的真实的世界,真实世界本来就是异步的,拥抱异步吧。

 

在实际情况下,我们其实已经自动拥抱了异步了。我们发现自己会定时轮询数据库表来更改又或者通过cron定时job来实现一些更新。这些方法都是一些打破同步的方式,但是这种做法总让人感觉有种黑客范儿,感觉像是黑客行为,怪怪的。

 

在本文中,我们将会讨论一种完全不同的架构:不是把service们通过命令链揉到一块,而是通过事件流(stream of events)来做。这是一个不错的方式。这种方式也是我们之后要讨论的一系列的一个基础。

 

当我们进入正式的例子之前,我们需要先普及三个简单的概念。一个service与另外一个service有三种交互方式:命令(Commands)、事件(Events)以及查询(Queries)。

 

事件的美妙之处在于“外部数据”可以被系统中的任何service所重用。

 

而且从service的角度来说,事件要比命令和查询都要解耦。这个很重要。

 

服务之间的交互有三种机制:

 

Commands 。命令是一个操作。希望在另一个服务中执行某些操作的一个请求。 会改变系统状态的东西。 命令期待有响应。

Events 。事件既是一个事实也是一个触发器。 发生了一些事情,表示为通知。

Queries 。查询是一个请求,是一个查找一些东西的请求(request)。重要的是,查询不会使得系统状态发生改变。

 

一个简单事件驱动流程

 

让我们开始一个简单的例子:用户购买一个小东西。那么接下来要发生两件事情:

 

支付。

系统检查是否还有更多的商品需要被订购。

在请求驱动(request-approach)的架构中,这两个行为被表现为一个命令链条。交互就像下面这样:

 

首先要注意的问题是“购买更多”的这个业务流程是随着订单服务(Order Service)一块被初始化的。这就使得责任不独立,责任跨了两个service。理想情况下,我们希望separation of concerns,也就是关注隔离