Microsevices陷阱: 本质与陷阱

最近两年,“微服务”这个词从最初的争议,到随后的逐渐接受,如今已经成为许多时髦的技术人员常挂在嘴边的词汇。在他们看来,似乎你不“微服务”就落伍了——因为你看,好像全世界都在“微服务”。然而当一些自诩为技术先驱的人开始尝试将其落地,并且后来发现自己当初根本就不了解到底“微服务”真正意味着什么时,我们才发现,要想革现代软件工程的命,远没发几篇文章、或者侃侃而谈来的容易。

1. 微服务的本质

可能你见过或者听过某些自称正在构建“微服务架构”的人,坦白的说,“微服务架构”真的不是指什么具体的软件架构,和大多数与之相关的早期技术一样,也没有一个标准告诉你什么是微服务、如何通过以下几个步骤构建微服务、或是让你参加培训,结束之后取得XXX认证,就证明你掌握了微服务架构。

其实微服务更像是一系列前沿软工思想的汇集,至于它为什么叫“微服务”,本系列的第一篇文章就已经提到过(虽然至今都有争议),但你可能会觉得它有点标题党——这也影响不了它拥有这个名字的既定事实。撇开名字,我们来看看微服务所承继的几个软件领域:

基于业务概念建模

从稳定性的角度考虑,围绕业务边界上下文所构建的接口要比来源于技术概念的接口更加不易变更,从而降低风险。这部分来源于领域驱动设计的主张。

自动化

自动化涉及方方面面,包括自动化测试、自动部署、自动配置管理乃至整个持续交付流程,都被认为是微服务落地的重要途径。

隐藏内部实现细节

隐藏实现的好处在于,一方面数据隐藏能够显著降低数据访问代码的耦合性;另外,服务内可以采用异构技术栈来实现,无论使用何种技术,你都可以用REST、RPC来实现服务间通信。

一切去中心化

去中心化的核心是组织自服务团队。近年来我们已经尝过自动化带来的好处,但鉴于Conway法则,设计开始来自领域而非现有的技术架构,而为了保证每个团队能够独立开发、测试和部署,按照服务划分现有团队是一个趋势(而非现实)。自服务团队能显著降低实施自动化的复杂度,更加贴近业务领域,并且形成一个分散的系统架构。与ESB或类似的编配系统完全相反的是,去中心化强调采用编排以及哑管道,并且在服务边界上采用智能终端来表现关联逻辑和数据,从而实现低耦合。

独立部署

强调每个服务都必须是可独立部署的,甚至当发生重大变更时,也倾向于采用版本共存终端来保证各自的独立性。独立部署能够带来更快的feature发布、强化自动化部署流程的一致性(而非经常需要人工编配部署管线)。推荐采用单服务-单主机的部署架构,从而避免部署单个服务时带来的边际效应;采用蓝绿部署/金丝雀发布来降低出错的风险;并且使用消费者驱动契约测试来保证集成接口的一致性。

错误隔离

分布式系统能够做到比单一系统更加可靠——前提是做好应对各种错误的万全准备(这也是人类毕生追求的目标…)。如果我们不能保证下游服务的正确性,系统就有可能发生级连式的灾难,且比单一系统脆弱的多。因此要时刻考虑网络的不可靠性、服务间通信的各种潜在问题:超时、隔板、断路器等在应对灾难时的作用、理解网络分区带来的后果、以及权衡一致性和可用性两种方案。

完备监控

传统意义上的监控,恐怕只是一个简单的dashboard,列出所有运行中节点的状态,并且当某个节点的指标超过阈值时产生警告。但随着去中心化的深入,传统监控方式根本不能应对复杂架构出现的各种问题。因此,采用语义化监控、综合化监控去模拟用户的真实行为,聚合用户日志和统计数据,采用关联ID跟踪消息在系统内的传递路径。

严格的说,不具备上述特征的系统就不能被称作微服务。事实上,当你开始尝试上述某个或某几个新的领域时,多数情况下你的系统无疑蕴涵了极大的风险——因为只有整体采用才能实现微服务的闭环,否则只能是一个摇摇欲坠的怪胎。有的人可能认为可以从简单模型开始演进——但注意,这里所谓的演进并不是从某个独立的方面出发,而是要在一开始就要做通盘设计,并且以简单方式先落地而已。

那么企业费尽千辛万苦、从事如此巨大的迁移工程——效果真的能够立竿见影吗?

2. 发觉陷阱

一些谨慎的开发者认为,可以先从单一系统入手,再逐渐向微服务过渡。对此,微服务的拥簇者声称:“你将无法(或很难)精炼出微服务架构,如果不在项目的最开始就设计成那样”。

“这无疑又在扯过早做大型设计的蛋(That’s BDUF Baloney)。”

Uncle Bob更倾向于“迫使无知”,即好的架构应尽量保证组件对部署和内部通信方式的透明,这样就可以根据实际情况选择部署成微服务,或多个单一系统+应用服务器,亦或纯粹的单一系统。这种“实际情况”有时可能是需要大规模扩展的、只需要少量部署的、以及单个节点足矣的。

一旦打破了“迫使无知”,则很有可能会造成过度设计,使得太多因素过早被考虑进来,最终却形成一堆烂摊子。对于微服务强调的其它几个方面,例如跨语言的服务实现——确实,采用REST的通信架构使得服务间实现强解耦,包括语言、数据库等。但是,什么样的业务需求会导致项目初期就要切割成不同语言、甚至采用不同的数据库技术呢?这种高配置复杂度的架构随之带来的好处又能有多少?

而对于“单一系统”的说法,Uncle Bob更认为这种广告式的宣传,使得采用非微服务形式的系统听起来就像是一块又大又丑的“石头”,造成受众对微服务架构的盲目崇拜,进而为布道者带来利益。

比起微服务,Uncle Bob更加倾向于一种“整洁架构”的风格,后者是对近年来一些流行系统架构的全面总结,焦点主要集中在代码架构方面,而对微服务强调的独立部署、异构数据库等持开放的观点。

3. 稳步向前

当然,无论是微服务,还是整洁架构,能最终轻松玩转的仍然是极少数。例如,从源头的设计出发,对领域的理解会影响边界上下文的稳定性,你要确信自己真的“彻底认识”了该领域,否则后面的一切都是空谈,还不如老老实实把单一系统做好。

另外,如果任何环节存在未知领域,就尽量不要采取过于激进的做法——这是遏制风险的关键。

对于任何一种架构,只有当整体规模增加到一定限值时,才能够真正考验架构的有效性,而面向未知又十分危险——因此强烈不建议如此激进地改变根本架构。毕竟在整个生态圈中,技术团队只是起到实现和保障作用,过早、过度引入风险是完全没有必要的。

那么何时才能选择向前呢?如今声称自己正或多或少实现微服务架构的团队包括Amazon、Netflix、REA和Gilt等,无一不是从现有实践中持续发掘存在的问题,并为此开发了一系列工具、平台甚至整体实践,其中的部分已经成为流行的开源项目——可见,对于某些技术能力领先世界的公司来说,微服务之路尚且存在各种困难,而剩下积累不深却大谈微服务的团队,要么是盲目追新,要么就是醉翁之意不在酒了。

Comments