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

发布时间:2019-03-22   来源:未知

  大部分时候,微服务 都是建立在一种基于请求和响应的协议之上。比如,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,也就是关注隔离。

  现在如 果我们使用事件驱动,而不是 请求驱动的方式的话,那么事 情就会变得好一些。

  在返回给用户之前,UI service 发布一个OrderRequested事件,然后等待OrderConfirmed(或者Rejected)。

  订单服务(Orders Service)和库存服务(Stock Service) react这个事件。

  仔细看这里,UI service和Orders Service并没有改变很多,而是通过事件来通信,而不是 直接调用另一个。

  这个Stock service(库存服务)很有趣。Order Service告诉他要做什么。然后StockService自己决 定是否参与本次交互,这是事 件驱动架构非常重要的属性,也就是:Reciver Driven Flow Control,接收者驱动流程控制。一下子控制反转了。

  这种控 制反转给接收者,很好的 解耦了服务之间的交互,这就为 架构提供了可插拔性。组件们 可以轻松的被插入和替换掉,优雅!

  随着架 构变得越来越复杂,这种可 插拔性的因素变得更加重要。举个例子,我们要 添加一个实时管理定价的service,根据供 需调整产品的价格。在一个 命令驱动的世界里,我们就 需要引入一个可以由库存服务(Stock Service)和订单服务(Orders Service)调用的类似updatePrice()这样的方法。

  但是在事件驱动(event-driven)世界更新价格的话,service只需要订阅共享的stream就是了,当相应的条件符合时,就去执 行更新价格的操作。

  事件(Events)和查询(Queries)的混合

  上面的 例子只是命令和事件。并没有说到查询。别忘了,我们之 前可是说到了三个概念。现在我们开始说查询。我们扩展上面的例子,让订单服务(Orders Service)在支付 之前检查是否有足够的库存。

  在请求驱动(request-driven)的架构中,我们可 能会向库存服务(Stock Service)发送一 个查询请求然后获取到当前的库存数量。这就导致了模型混合,事件流 纯粹被用作通知,允许任何的service加入flow,但查询 却是通过请求驱动的方式直接访问源。

  对于服务(service)需要独 立发展的较大的生态系统,远程查 询要涉及到很多关联,耦合很严重,要把很 多服务捆绑在一起。我们可以通过“内部化”来避免 这种涉及多个上下文交叉的查询。而事件 流可以被用于在每个service中缓存数据集,这样我 们就可以在本地来完成查询。

  所以,增加这个库存检查,订单服务(Order Service)可以订阅库存服务(Stock Service)的事件流,库存一有更新,订单服 务就会收到通知,然后把 更新存储到本地的数据库。这样接 下来就可以查询本地这个“视图(view)”来检查 是否有足够的库存。

友情链接:    500vip彩票ios   福建省体彩22选5开奖查询   567彩票分分快三   360彩票   主流彩票