分布式系统架构设计 – 第1式 - 隔板模式

导读

日拱一卒,功不唐捐,分享是最好的学习,一个知识领域里的 “道 法 术 器” 这四个境界需要从 微观、中观以及宏观 三个角度来把握。微观是实践,中观讲套路,宏观靠领悟。本系列文章我把它命名为《分布式系统架构设计三十六式》,讲诉分布式系统里最重要的三十六个虚数的中观套路,而微服务的本质也是分布式,因此搞明白这三十六个最重要的知识点也就同时能搞明白微服务。

实现一个分布式系统通常会面临三大难题: 故障传播性、业务拆分与聚合以及分布式事务 。本系列中的服务治理章节主要是为了解决故障传播性的难题,它包括: 隔离、熔断、降级、限流、容错以及资源管控 ,本文将讲诉服务治理里的 “隔板” 模式。

动机

在分布式系统里通常将进程容器化以进行资源隔离,然后在同一个进程里的各种业务都共享线程池对外提供服务,这就经常会遇到这样的问题:

  1. 业务A负载较高,抢占了线程池里的大部分线程资源,从而造成其他业务的服务质量下降;
  2. 同一个进程内新加入一个业务,这个业务会抢占其他业务的资源,从而造成系统的不稳定,比如业务性能抖动;
  3. 难以调试,比如同一个进程里的10个业务共享同一个线程池,当出现故障时难以通过简单的日志判断是哪个业务出了问题。

因此,我们希望找出一个机制解决这样的问题。

隔板模式

首先我来看一个英文单词“Bulkhead”,翻译成中文就是“舱壁”‘或“隔板”,在分布式系统里有个资源隔离的设计模式叫做”舱壁模式”或者“隔板模式”。

模式来源: 通过万能的Wiki百科我们可以了解到轮船里的两个舱位之间的挡板就是隔板/舱壁(Bulkhead),如下图:


bulkhead

图片来源于引文[1],版权归原作者所有




在造船的时候,”船农们“(对应码农)通常会把一个大的船舱用隔板分成N个小的空间,以便万一船体破裂或着火的时候,只有这个被分割开的小船舱受到影响,而其他的船舱是被隔离而不受影响的,从而提高整个船只的安全度。

同样这种隔板模式可以应用在分布式系统的资源隔离设计里,在分布式系统里,资源隔离通常按业务分为进程级别的隔离和线程级别的隔离,某些简单的服务质量要求不高的业务场景下实现进程级别的隔离就够了,但是在某些对服务质量要求较高的分布式场景下需要线程级别的细粒度隔离。


进程隔离

进程级别隔离通常指的是容器化隔离,比如通过使用docker实现业务进程之间的资源隔离。

线程隔离

线程级别隔离是指给每个跑在进程里的业务都按业务类型创建一个线程池,从而实现线程级别细粒度的资源隔离,线程隔离具有以下优势:

  1. 提高业务可靠性,减少业务受其他业务影响的程度,当一个业务耗尽自身的线程资源后也不会影响另外一个业务的服务质量;
  2. 降低新加入的业务的给系统带来的风险,比如当前系统的一个进程用例中有10个业务。当新加入一个业务时,必然会抢占此前10个业务的线程资源,从而给系统带来不稳定,比如性能抖动;
  3. 利于调试,给每一个业务都分配一个线程池名称,当业务出故障时,通过线程池名称可以很方便地定位是哪个业务出了故障,并且通过监控线程池的请求失败次数、超时次数、拒绝请求次数等可以实时的反应当前业务服务质量。

事物都有二元性,线程池隔离,有利自然也有弊,线程池隔离也会引入额外的一些开销,开销类型有:

  1. 对象分配,每个调用都会实例化一个新的线程对象及其中的关联对象,占用系统资源;
  2. 并发,共享数据结构,计数器等,也占用系统资源;
  3. 线程的执行开销:切换,调度,执行,同样也占用资源。

因此,线程池的隔离带来了好处但是也会引起一些顾虑,比如给每个业务都创建一个线程池是否会给系统带来太大的开销。通过Hystrix的数据分析可以得出结论是: “开销是有的,但是对比好处,通过权衡,其开销在一些要求不苛刻的场景可以忽略。”

线程池的开销分析

Hystrix官网[3],统计了线程池带来的开销成本,如下图表示在单个API实例上以60个请求/秒执行一个HystrixCommand:

Hystrix

图片来源于引文[3],版权归原作者所有

通过分析这个统计图(注意不同的颜色),我们可以看到:

  1. 中位数(P50)和更低的场景下,对比不使用线程池隔离模式,隔离线程池基本没有成本开销。
  2. 在P90的场景下,对比不使用线程池隔离模式,隔离线程池的耗时差距为3毫秒。
  3. 在P99的场景下,对比不使用线程池隔离模式,隔离线程池的耗时差距为9毫秒。

但是从上图可以看出,成本增加的幅度远小于单独一个线程的执行时间增加的幅度,当未使用线程池隔离的线程执行时间从2ms跳到28ms时,线程池隔离的耗时成本从0ms跳到9ms。

因此,对于大多数的使用场景而言,在P90及以上的线程池隔离带来的开销被认为是可接受的,从而获得资源隔离带来的好处。

但是在某些场景这样的开销可能过高,比如缓存场景,在这种情况下,可以选用信号量来进行隔离,缺点是信号量不允许设置超时,难以实现熔断、降级之类的服务治理行为。

小结

本文讲诉了服务治理里的 “隔板”模式,在下一篇将讲诉分布式系统服务治理的熔断模式。另作者能力与认知都有限,欢迎大家拍砖留念。

作者简介

常平,中科大硕,10年+数据相关经验,主要工作背景为分布式系统、存储、缓存、微服务、云计算以及大数据,现就职于DELL EMC。

版权申明

本文的版权协议为 CC-BY-NC-ND license:https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh

在遵循署名、非商业使用(以获利为准)以及禁止演绎的前提下可以自由阅读、分享、转发、复制、分发等。

参考资料

[1] https://en.wikipedia.org/wiki/Bulkhead_(partition)

[2] http://writing.engr.psu.edu/uer/bassett.html

[3] https://github.com/Netflix/Hystrix/wiki/FAQ%20:%20General