分布式系统设计模式

概述

这篇文章是对于【分布式系统设计模式】的我的理解和部分翻译。node

文章探讨了关于《基于容器化软件组件的微服务架构》。算法

其实容器化编程的发展路径和面向对象编程有殊途同归之妙--
都是将复杂的系统进行抽象、解耦,而后经过必定的方式组合起来。编程

既然咱们要组合,确定会有面对不一样状况的不一样组合方式。因此,这些不一样的组合方式也会有几个经常使用的固定模式。
而这个正式咱们要探讨的--分布式系统设计模式。segmentfault

说到分布式,第一个联想到的应该就的容器化。
为何?其实容器化和分布式本没有交集,只是由于咱们发现容器化是一个实现分布式的高效的方法。设计模式

容器化设置了一个自然的边界,边界以外用接口进行通讯。
有了这个边界的好处就是,任何意料以外的状况均可以被限制在最小的影响范围,毕竟咱们构建的是一个大型的复杂系统。安全

我认为,用FMEA模型能很好的描述为何会采用容器化去解构分布式系统。(FMEA,能够理解为:失控的状态必定会发生,咱们要作的是控制失控的范围)架构

因此,咱们接下来要说的设计模式基本上都是和容器相关,咱们须要把容器做为一等公民去看。
毕竟这是写 Kubernetes 的哥们写的。app

单容器管理者模式 (Single-container management patterns)

咱们为容器增长一些可控接口,好比 run(), stop(), pause(),使得容器对外来讲是可控的。负载均衡

也正是由于普遍的 http 协议支持,你彻底能够经过 http 和 JSON这样的序列化方式去构造你应用的对外的 API。框架

通常来讲咱们的设计方针都是一个容器提供一种服务。同时容器会为其上下游提供接口。

什么接口?

向上,提供容器自己丰富的信息接口。可以为特定的监控容器运行状态的应用提供信息。

向下,提供了控制容器自己的接口。使得分布式系统可以更有效的管理整个应用的生命周期,以及应用的优先级。

好比,一个集群的管理系统,可以设置集群处理任务的优先级。(好比 K8s 中的抢占式调度)

因此一旦采用这种模式的话,你会须要一个统一的管理平台,经过接口去管理(组管理)单个容器。

单节点-多容器应用模式 (Single-node, multi-container application patterns)

这种模式比较好理解,有些容器应用是须要“共生”的,因此咱们会将其放在同一个节点上。
一旦这样,分布式系统会对容器组作联合调度。
好比 K8s 里将调度单位描述成了 Pods(一个 Pod 可能包含多个容器),Nomad 则称其为 task groups。
下面几个就是经常使用的单节点多容器的设计模式:

副载模式(Sidecar pattern)

多容器部署最通用的一种模式,就是 sidecar 模式。
其实你们都直接称呼 Sidecar 模式,不会翻译成副载。

那 Sidecar 是个啥样子呢?

举个例子吧:咱们有一个主容器是 Web Server,咱们须要收集 Web Server 所产生的日志。
因此咱们会有一个专门的 sidecar 容器,负责收集日志并把日志存储到集群的存储系统。
图片描述

另一个例子,就是主容器的内容呈现,是由一个 sidecar 容器去实时同步的。

还有个例子是为一个 Http Web Server 提供 Https 功能。
图片描述

你会发现 Sidecar 是主容器的一种扩展和升级,这种模式的好处在于,由于是容器隔离,因此可以保证从属容器不会在主容器须要资源的时候占用过多的资源,由于分配资源的最小单位就是容器。同时,sidecar 通常在功能上比较专职,又是容器化的,因此能够很方便的进行单独的部署、升级。

大使模式(Ambassador pattern)

图片描述

大使模式实现方式是在节点中增长一个通信代理。他解决的问题是:
为某些年久失修的外部服务,增长一个调用代理,调用者是咱们节点上的应用。

大使模式给开发者的好处是:

  1. 他们只要考虑应用与本地服务的链接
  2. 他们能够在本地进行测试
  3. 调用的外部服务语言无关

其实有个很典型可是非容器化的例子,就是 Ribbon 中的客户端负载。
和大使模式很像,全部的请求流量都先经由客户端的负载均衡器决定了流量流向--咱们在大使容器中现决定流量流向,而后直接调用真正的服务。

聪明的你会发现,咱们彷佛能够在大使容器中作不少手脚,好比熔断,路由,流量监控,安全控制等等(有点像服务端的 API 网关)。

没错,因此咱们得出了一些使用该模式的场景(来自docs.microsoft.com/en...):

  • 客户端链接语言无关,框架无关
  • 将客户端链接的问题与应用分离,解耦开发
  • 为年久失修的应用程序提供云或集群支持

适配器模式(Adapter pattern)

和 Ambassador 相比,Adapter 模式向外部呈现了一个统一的接口。(方向反了一下)

最典型的例子应该就是容器管理平台,全部系统中的容器都会有一套统一的监控接口。
图片描述

如今的容器多种多样,不过只要保证每一个容器都有统一的不变的对外监控接口,对于单独的监控工具来讲就不难实时收集各个容器的数据了。

单节点多容器的模式主要就是上面三种。

多节点应用模式 (Multi-node application patterns)

和单节点多应用模式同样,咱们一样要求实现这个模式的系统支持 K8s 中 Pod 这样的概念。

领导人选举 (Leader election pattern)

在分布式系统中,老生常谈的问题了,就是领导人选举。

通常领导人选择是怎样一种状态呢?就是在分布式系统中,存在一个或者多个领导人,还有剩下的做为工做节点。
一旦有领导人节点挂了,工做节点按照必定算法升级成为领导人节点。

领导人选举算法是十分复杂的算法(至少对我来讲),甚至有些算法库仍是语言限定的,因此,更好的方式就是经过容器去使用这个领导人选举功能。

那为何要分为领导节点和工做节点呢?

固然是为了更好分配任务,分配好了任务,就能保证系统处在一个高效的状态下运行。避免出现有些工做节点空闲,有些工做节点忙的现象。整个模式的思想仍是中心化治理最高效的方针。

工做队列模式 (Work queue pattern)

我以为,分布式系统中的工做队列模式,其实表达了一个具备拓扑关系的分布式系统。每一个步骤都是单独的,可是他们的输入可能须要依靠上一个输出,亦或者,他们的输出会成为下一个的输入。

这个模式好在他语言无关,我只要知道个人容器的输入输出,而后将它放在合适的位置就能够了。

同时还须要一个专门进行做业管理的容器进行任务的分发。
图片描述

我在网上并无找到过多的关于描述 Work queue pattern 的资料。
彷佛这种设计模式的叫法不太同样。

向量化模式 (Scatter/gather pattern)

这是一种有点广播竞争的模式。

一个外部请求会先被发送到一个“根”或“父”节点。
而后根节点扩散请求并让服务端同时进行竞争,而后每一个竞争者都会返回一部分请求的结果,根节点再把碎片结果揉成一个完整的返回。

这样的模式其实对于开发者的要求仍是比较高的,由于要对分布式任务处理中产生的异常有很好的把控,同时涉及到了分布式任务一致性。

通常实现这种模式须要至少 2 个容器,一个是用来进行任务分发的,还有一个是进行结果归总的。

总结

面向对象编程须要面向对象的设计模式做为支撑。
容器化的分布式系统也同样,须要容器的设计模式做为支撑。

上面咱们分析了三种容器架构下的设计模式,一共 7 种。
上面这 7 中模式会以组合的形式出如今分布式系统之中,毕竟分布式系统是一个复杂系统。

这篇文章所依据的论文,虽然说是分布式系统的设计模式,可是其实会涉及到不少经典的企业集成模式。因此我在这里向你们推荐一本书《企业集成模式》
可别觉得是讲企业管理的,这是给开发者看的。

好吧,暂时先这样吧。

参考