
Read Time:1 Minute, 50 Second
微服务分布式的架构具备可扩展、可持续交付的特性 。
然而, 在这分布式的架构下, 我们将更需关注 :
如何避免当某个微服务执行性能变差时, 造成整体的微服务发生骨牌式的全面崩溃 ?!
Client Resilience
如图一所示 :
当微服务 Z 因某个不明的原因而突然发生执行性能下降时 :
- 微服务 Y 与应用系统 C 将因调用微服务 Z 而耗用更长的等待时间与更多的资源, 而使得微服务 Y 与应用系统 C 本身的执行性能也跟著下降。
- 当微服务 Y 执行性能下降时, 微服务 X、应用系统 A、应用系统 B 的性能也都将跟著下降。
假如, 微服务 Z 的执行性能下降的问题, 没有办法即时的获得有效的疏解, 而仍旧持续的恶化, 毫无疑问的, 应用系统 A、应用系统 B、应用系统 C、微服务 X、微服务 Y 都将会接著发生所谓的骨牌式的全面崩溃。

为防止微服务分布式的架构发生骨牌式的全面崩溃, 我们所建立的保护措施; Client Resiliency Patterns; 需具备以下的特点:
- 当发现被调用的微服务性能下降时, 能立即的切断微服务与被调用微服务间的连接。
- 能统计在某个时间段内, 被调用的微服务未在所设定的时间内正常响应的总数, 并且能在失败的总数超过预期时, 能自动的将微服务与被调用的微服务隔离。
- 当微服务与被调用的微服务被切断或被隔离(断开) 时, 有必要时, 需能引导调用的微服务去调用备选的微服务或数据源, 以获得较佳的使用者体验。
- 当微服务与被调用的微服务被隔离 (断开) 时, 能自动的侦知被调用的微服务的性能已恢复正常。
- 被调用的微服务中的每个服务调用, 都有自身的线程池 (thread pool)。每个服务调用都会由自身的线程池中获得线程, 而使得每个服务调用都能获得较佳的隔离。
Client Resiliency Patterns 主要是由下列三个元素所构成:
- Circuit Breaker
- Fallback
- Bulkhead
如图二所示:
- 微服务 A 内的 Circuit Breaker, 将会引导微服务 A 的服务调用 X, 至线程池 X1 获取可使用的线程; 引导服务调用 Y, 至线程池 Y1 获取可使用的线程。
- 微服务 A 的各个服务调用都有各自的线程池, 使得各个的服务调用都有专属的 Bulkhead (舱壁); 有效的隔离了某个异常的服务调用, 会对其他的服务调用所产生的影响。

如图三所示:
- 当微服务 B 超过在 Circuit Breaker 所设定的 Time Out 时间内, 还未响应微服务 A 的服务调用 X 时, Circuit Breaker 便会自动切断微服务 A 的服务调用 X 与微服务 B 之间的连接。
- 为获得更佳的使用者体验, 当 Circuit Breaker 自动切断微服务 A 的服务调用 X 与微服务 B 之间的连接后, Circuit Breaker 便会引导微服务 A 的服务调用 X, 到服务调用 X 的 Fallback; 服务调用 X 改调微服务 C 或数据源 Z。

如图四所示:
- 当微服务 B 超过在 Circuit Breaker 所设定的 Time Out 时间内, 还未响应微服务 A 的服务调用时, Circuit Breaker 便会自动切断微服务 A 的服务调用 X 与微服务 B 之间的连接, 同时 Circuit Breaker 便会开始统计在某个区段时间内, 微服务 B 有多少次的逾时失败的响应; 当微服务 B 逾时失败响应的总数超过 Circuit Breaker 所设定的数目时, Circuit Breaker 便会立即切断微服务 A 与微服务 B 间的所有的服务调用。
- 当 Circuit Breaker 切断微服务 A 与微服务 B 间的所有的服务调用时, 为获得更佳的使用者体验, Circuit Breaker 便会引导微服务 A 所有的服务调用到 Fallback; 微服务 A 所有的服务调用将改调用其它的微服务或数据源。

如图五所示:
- 当 Circuit Breaker 切断微服务 A 与微服务 B 间的所有的服务调用后的某个时间段, Circuit Breaker 便会引导微服务 A 的某个服务调用去调用微服务 B:
- 假如, 微服务 B 可正常的响应此服务调用, 就表示微服务 B 已恢复了正常的运作, Circuit Breaker 便会引导微服务 A 所有的服务调用去调用微服务 B。
- 假如, 微服务 B 还是没法在 Circuit Breaker 所设定的 Time Out 间内响应此服务调用, Circuit Break 便会持续的切断微服务 A 与微服务 B间的所有的服务调用, 直到下个的时间段, Circuit Break 会再让微服务A 的某个服务调用去调用微服务 B; 看看微服务 B 是否恢复了正常的运作?

当微服务分布式的架构中, 拥有数百甚至是上千个微服务时, Client Resiliency Patterns 的设计就显得相当、相当的重要了, 因为:
- Client Resiliency Patterns 可使得每个微服务都能免于执行效能会持续恶化的恶运。
- Client Resiliency Patterns 可使得每个微服务在其执行效能恶化的初期, 就能获得一喘息的机会; 而不至于恶化到某个微服务的崩溃。
- Client Resiliency Patterns 避免了数百甚至是上千个微服务的集体崩溃。更在某个微服务发生执行效能恶化时, 便可提供另一个微服务执行的方案, 而降低了用户因某个微服务执行效能的恶化, 所会产生的愤怒、不满与失望。
期望这篇文章能对微服务的架构师, 有所启发, 有所帮助。