减少或者避免被锁定,会消耗架构设计工作中的很大一部分成本。这是一个神圣的职责:架构就是提供选项,而锁定则刚好相反。然而锁定不是非白即黑的:摆脱某一方面的锁定,往往意味着在其它方面被锁定。同样地,开源软件之类的流行概念,据说天然的消除锁定,这并非事实。是时候详细考察一下锁定问题,防止我们被锁定在反锁定的路上。
架构师的主要职责之一就是提供选择。这些选项让系统能够容忍变化,有了选择的自由,我们可以耐心的等待信息完整之后才作出决定,以及应对一些预计外的事件。锁定的含义则刚好相反:锁定使得软件很难从一种方案切换到另一种方案。很多架构师可能会将锁定视为大敌,同时认为自己守护着 IT 世界中的自由,在这世界中,组件可以被随意替换和互联。
但是架构从来都不简单——这是个事关妥协的生意。经验丰富的架构师知道,锁定的重要性,可能会超过避免锁定的重要性。锁定有很多方面,有时候还可能是最佳方案。所以我们进入架构师电梯,仔细观察一下锁定这个事。
近年来,我们用来部署软件的平台越来越强——现代云平台不止告诉我,我们的照片是小狗还是饼干,它们还会编译代码,进行部署,配置必要的基础设施,并保存数据。
这种便利性和生产力的急剧提高,带来了全新的锁定方式。吸引了很多架构师注意的混合多云方案,就是一个用于审视锁定问题的好例子。假设你有一个要部署到云上的应用。这很简单,但是在架构师的视角来看,却会有很多选择、很多权衡,尤其是在锁定方面。
你可能想要把你的应用部署在容器里。这听起来很棒,但是你会使用 ECS 来运行它么?这是 AWS 的专属。考虑 Kubernetes ?它是开源的而且能够在绝大多数环境上运行——其中也包括自建设施。问题解决了么?还没有——你被锁定在 Kubernetes 上了——想想那些 YAML 吧。所以这是从锁定走向锁定。如果你使用的是托管 Kubernetes 例如 GKE 和 EKS,你还可能被锁定到 Kubernetes 的特定版本和特定扩展上。
如果想要让软件运行在私有设施中,也还有 AWS Outposts 的选项,所以你还是有得选。但这还是 AWS 的专有品种。你可能已经被锁定到 VMWare,它也能和 VMWare 集成,所以这有什么不同么?Google 的 Anthos 也是同样产品,它使用开源组件构建而成,但还是专属品:你可以把应用迁移到不同的云上——前提是你继续使用 ANthos。所以这就是锁定的意思,对吧?
另外如果你把你的部署自动化和你的应用运行时漂亮的分割开来,是否意味着切换基础设施更容易了?降低锁定的风险了?嘿,甚至还有跨平台的基础设施即代码的工具呢,是不是就完全消灭这些担忧了?
至于存储方面,AWS S3 如何?其它云供应商提供了 S3 兼容的 API,所以 S3 可以视为兼容多云,没有锁定了,但 S3 的确是 AWS 的专属阿。还可以把所有数据访问藏到抽象层之后,然后适配本地环境,这样总算可以了?
看起来避免锁定不那么简单,甚至会让你迷失在逃离锁定之路上。尽管如此,我推荐 Simon Wardley 的 Take on Hybrid Cloud
电梯架构师(乘着架构师电梯上上下下的人)眼中的锁定是灰色的,而不是象有些人的眼里的非黑即白。在考虑系统设计时,他们会意识到象锁定或者耦合这种事情并不是一个非此即彼的事情。两个系统并不能简单的判断耦合与否,同样地,也无法简单的判断是否被锁定到一个产品。这种问题的内部是有一些微妙之处的。例如锁定问题可以拆分成多个维度:
总的说来,锁定绝对不是简单的二元世界,理解了各种不同的锁定方式,有助于作出更加清晰的决策。这个列表也戳穿了一些常见的谬误,例如开源软件神奇的解除锁定的能力。开源软件能够防止厂商锁定,但是绝大多数其它的锁定同样存在。这当然不是说开源软件的坏话,只是说,开源软件并非治愈锁定的良药。
有经验的架构师不会只盯住阴暗面,他们会执行优秀的决策纪律。纪律很重要,因为我们的决策能力往往比我们的自我感觉要差得多。如果这方面有疑问,建议阅读 Kahneman 的 Kahneman’s Thinking, Fast and Slow。
提高决策能力的最有效方法就是使用模型。就算是简单的模型,也能在改善决策的过程中提供很大帮助:
简单但令人回味的模型是伟大科学家的标志,过分的细化和参数化通常意味着平庸。 George Box
所以不要嘲笑深受管理咨询行业宠爱的二乘二矩阵,我们接下来会发现,这是一种非常简单有效的模型。
下一个事关模型的关键点:常识告诉我们,面对不确定性,必须尽快响应——毕竟世界一直在变。但是事与愿违:当我们必须处理很多相互依赖、高度不确定性以及小概率事件时,糟糕的决策会把事情搞得更糟。模型能帮助我们把更多的结构化和规律加入决策过程。是否接受锁定、接受什么样的锁定,都是这样的问题,所以我们要使用一些模型。
一个简单的模型能够让我们克服以锁定为耻的观念。首先我们必须意识到,很难完全杜绝锁定的发生,因此一定程度的锁定在所难免。第二,如果锁定能带来与之相配的收益,那么我们也会乐见其成的,例如一个竞争对手所不具备的的独特的功能。
我们把这些因素用一个最简单的模型来表达——二乘二矩阵:
上面的矩阵使用以下的两个维度来描述我们的选择:
我们可以看看这四个分区了:
这个模型的确很简单,把你的软件(或者硬件)组件放到这个矩阵里面是个值得尝试的做法。这样的方法不仅为你的风险进行了可视化,还把你的决策传达给了利益相关者。
举一个日常的例子,你可能决定使用下列物品,这些物品有各自的功能,也有锁定风险(从右上角开始逆时针方向)。
这里要注意的就是唯一实用价值:每个供应商都会提供一些唯一功能——这就是差异化。然而这里需要关注的是这些功能是否能转化为唯一价值。例如有的云供应商提供了能够服务于十亿用户的强大全球网络。这令人印象深刻,也具备唯一性,但这对普通的企业来说却没什么意义,他们可能只服务于百万用户,也仅在单一国家内提供服务。当然也有人在有限速的小国家开法拉利的,并非所有决定都是理性的,但法拉利和云平台不同,可能给出不同的实用价值。
这个简单的矩阵太有用了,完全停不下来。前面的矩阵把切换成本作为单一元素(维度),现在可以将其拆分为两个维度:
这个矩阵把替换的成本从替换的可能性(主动或者被动)拆分开来。较低的替换可能性结合较低的替换成本应该不会令人困扰,但是相对的替换成本较高、又有较高替换概率的就值得注意了。在另外一角,虽然替换成本高企,但是发生的可能性不大——这一区域可能需要做一些保全措施,措施包括限制更改范围,或者增加运维成本。你也可以选择接受这种风险——在 Oracle 和 DB2 之间进行切换的机会并不多。最后如果切换的可能性很大,成本又不高,那就无需费神了——拥抱变化,设计系统,完成切换。但奇怪的是,尽管大量的小范围变化很容易实现,但这种场景往往不会象左上角那样得到大量关注,这就是决策过程中经常出现的错误:难于完成的戏剧化场景,往往因为一个“万一”,吸引了更多的注意力。
在我们谈论锁定的意愿时,可能需要在多个角度考虑一下切换的理由:供应商退出业务、提价、或者无力支持现有规模以及功能需求。有趣的是,减少锁定的愿望经常成为谈判的手段:在续约谈判中,你可能会提示你的供应商,在产品架构设计角度来看,从他们的产品中切换是可行的,成本也是可以接受的。这样你就给出了 BATNA(Best Alternative To a Negotiated Agreement)够低的信息。这种架构方式虽然不一定会用起来,但它会产生实际的威慑力,就如冷战期间的物资储备一样。你可能只是伪装,并不会真的去除锁定,但是这种情况下,你最好是个好玩家,以免被供应商翻了底牌——比如和你的开发人员打探消息。
再回到我们起初提到的选项类比问题,如果避免锁定给了你(多个)选项,那么切换成本就是这个选项的执行价格。有价值的选项应该能降低切换成本。我们当然希望所有系统都能在绿色区域中,具备最小的切换成本,但是实际发生的投资可能并不总能降低。
例如很多架构师会反对锁定到特定的数据库或者云供应商。然而发生切换的机率如何?5% 或者更少?那么你怎么才能把切换成本从 50000(假设)美金降低到接近于 0?切换成本远远大于 2500 美金(50000 * 5%)。因此最小化转换成本并非(架构设计的)唯一目标,很容易变成过度投资。这也类似过度保险:支付巨额溢价,能把免赔偿额度降低到 0,但这通常不是最经济最合理的选择。
一个最终模型(这是唯一一次不使用矩阵方式)能够帮助你决定,在降低切换成本上投入多少才是合适的。下图的蓝线,是转换可能性和转换成本的乘积,代表了转换的负债。这张图展示了它和前期投资的关系:
进行投资肯定能减少债务,或者降低执行成本、降低切换可能性也都能降低。例如使用 ORM 框架是一个较小的投资,能够降低对数据库厂商的锁定。还可以创建一个元数据语言,能够转换成每个厂商的数据库的本地存储过程语法。这能让你在不被锁定的情况下释放数据库的所有性能,但是这就需要为一个相对比较小众的场景进行大量投资了。
红线很有意思,表达的是前期投资和潜在债务的累计。这是应该尽量降低的总体花费。在多数情况下,随着前期投资的提高,会进入一个最佳区域。针对降低锁定的额外投资实际上会导致更高的总体成本。原因也很简单:投资回报率,尤其是在切换概率较低的时候。如果我们把架构做成超级有弹性,我们可能会进入过度投资的范围。Yagni(You ain’t gonna need it)的家伙们会走向另外一端——中庸之道是快乐之源。
现在在锁定方面我们对锁定的成本做了一些研究,我们需要更进一步的看看避免锁定的总体成本,前面的模型,我们假设避免锁定是一个简单的成本问题。实际上这个成本能够分解为几个不同方面。
架构师要计算减少锁定的成本,应该对这个列表做一个检查,看是不是存在什么盲点。同样地,避免锁定的尝试可能会是有泄漏的,例如 Terrorform 是个好工具,但是它的脚本使用了很多供应商特定的构造。实现细节的泄漏,就会提高云间切换的成本。
有了这么多的理论铺垫,我们看看一些贴地气的例子。
一个公司会把他们的代码打包为 Docker 容器,部署在 AWS ECS 上,所以它们锁定在了 AWS 上。应该引入开源的 Kubernetes 来避免锁定么?速度是它们的主要问题,当前的 ECS 解决方案表现很好,我认为迁移可能难有回报。切换云供应商的概率很低,它们有更重要的事情可以做。
建议:接受锁定。
很多应用程序会使用关系型数据库,有很多厂商和开源产品。然而 SQL 的方言、存储过程以及定制的管理控制台都是锁定的。你要投资多少来避免锁定呢?多数语言和运行时通用框架(例如 Hibernetes)都以低成本提供了某种程度的数据库中立。如果希望降低执行价格,还应该避免使用 SQL 函数以及存储过程,但这会降低产品性能或提高硬件水平。
建议:使用低成本机制来降低锁定程度。不要想着零成本切换。
除了把数据库从一个供应商切换到另一个,你可能更感兴趣的是把应用和数据库迁移到云上。除了技术考量之外,你需要考虑一下有些供应商的授权协议可能会让这种迁移很不划算。这种情况下,选择一个开源数据库可能是个更好的办法。
建议:如果能够满足你的需要,那么选择一个开源的数据库,可能需要接受某种程度的锁定。
很多企业痴迷于可移植到多云的想法,病体除了更复杂、更精密也更昂贵的计划,这些计划表面上可以让它们免于被云供应商锁定。然而大多数这些尝试,都在否定上云的初衷:低阻力以及使用托管服务(例如存储和数据库)的能力。
建议:谨慎从事。参考我在多云方面的文章。
似乎人们可以投入大量时间去关心锁定的问题。有些人甚至会因为我们的方法太过“学术性”而不予理会,学术性这个词我通常都无法认为是个贬义词,这是我们受教育的地方。不过老式的非此即彼的架构方法,是不是更简单,可能还更高效呢?
事实上,思维的速度很快。只需要几分钟就能够读完这篇文章里提到的所有模型,并作出良好的决策——无需任何花俏的工具,只需要纸或白板。快速完成架构思考的关键是集中注意力。而要做出精致的幻灯片,需要提前几周进行安排,通常也不会有具备实际专业知识的人参与并作出决策。
感谢作出有益反馈并提供输入的几位朋友:
Manlio Grillo
Michael Plöd
Michele Danieli
Scott Davis