老马的微服务特性解读
前不久伍斌(Ben)前辈在其微信公众号北京设计模式学习组
上发布了一篇文章:“微服务”博客中译完整版,并分享到了朋友圈,我看到后就拜读了一下。
说实话,当时很多地方没怎么看明白,虽然我们的团队也在做微服务架构的尝试,但理论和现实还是有很大的差距,而且James Lewis和Martin Fowler两位大师是从高屋建瓴的宏观层面来描述微服务的特性,说的比较抽象,理解起来还是有点费劲。
Ben是国内我非常推崇的一位技术前辈,心无旁骛专注于技术二十多年,在新技术的探索和推广上做了很多的尝试,特别是在敏捷开发领域,功力深厚。
他从2013年开始尝试做编程操练社区——北京设计模式学习组,至今为止差不多举办了30多次的编程道场活动,让很多像我一样的程序员在实际操练中体会到了TDD和结对编程的魅力,喜之乐之,心向往之。
后来Ben还把这诸多次编程操练的体会和经验总结、提炼、升华,出版成书——《在编程操练中悟道》,有兴趣的同学可以买来一读。
我一直把Ben的技术探索方向作为自己学习的风向标,:)。既然他对老马的微服务博客这么推崇,不辞辛苦的翻译出来,并免费的发布到公众号上让国内的技术同学学习,我们作为这些宝贵资源的受益者,怎么能不好好领会,细细品味呢?
所以,后来我又在茶余饭后、休憩蹲厕之余拿出来反复玩味,体会大师的精髓,竟然也稍有体悟,欣喜之余,不敢独享,也学习前辈大师们的精神,分享出来,以供诸同学们参考。
什么是微服务?
对什么是微服务,大师们并没有下一个确切的定义。这也正是大师们的严谨和高明之处。因为对一个事物的定义往往让思维进入刻板与僵化的领域,而变化正是新生事物的重要特征,基于演化的观点,不对微服务过早的下定义,是一个很明智的做法。
但大师们对微服务的特征和模式做了一些概括,以让我们能够对这个新的架构模式有一个比较清晰的认识。
讨论微服务架构的时候,离不开一个基本的参照系——单块(monolithic)应用架构,它的基本特征可以总结如下:
- 是以一个整体的单元来构建,通常是以单个进程的方式来运行。
- 典型的单块应用风格的企业应用系统通常包含三个部分:客户端的用户界面,中心数据库系统和后端的服务应用。
- 研发的组织结构也会按照这三大块来切分:负责前端开发团队,负责后端开发团队,和管理数据库的团队等。
- 单块应用内有规范统一的技术栈实现。
对应于上述单块应用的特征,大师们对微服务的架构模式总结了九大特性,下面我就解读一下这九大特性。
微服务的九大特性
特性一:组件化与多服务
软件开发一直以来都有一个梦想:像搭积木一样来构建应用,尽可能的模块化、组件化,方便可更换可升级的目的。
一个组件就是一个可以独立更换和升级的软件单元。
在微服务架构之前,构建单体应用之时,大家也是朝这个目标努力,一个很好的例子就是使用各种公共软件库。公共软件库也算组件的一种形式:一定程度上可更换可升级。
但使用公共软件库构建应用的一个很大的问题是:一旦公共软件库升级后,就需要重新构建部署整个的应用系统,即使别的组件没有变化,也要这么做,这种不合理因素就逐渐凸显出来。
微服务作为组件的更高级形式,解决了这个问题:服务可以被独立部署,对一个服务修改只需要构建和重新部署这一个服务,对系统的其它服务没有影响,但前提是服务的接口协议没有发生变化,只是服务内部的升级。如果涉及到服务的接口协议的升级,那么情况就要复杂一些,跟调用这个服务相关的其它服务可能也会修改升级。
特性二:围绕业务功能组织团队
** 著名的康威定律:**
任何设计系统的组织,都会产生这样一个设计,即该设计的结构与该组织的沟通结构相一致。
——梅尔文•康威(Melvyn Conway), 1967年
根据康威定律,当面对一个大型的应用系统时,管理层会根据目前的组织架构来分解系统:前端团队负责用户界面,后端团队负责后端服务,数据库团队负责数据库运维,一个根据组织架构而产生的设计架构应运而生——又一个单体怪物的雏形开始孕育。
而微服务的架构自然而然的打破了这种组织的界限,因为微服务采用”业务功能“来分解系统,而针对各个业务功能需要提供多层次广泛的软件实现,包括用户界面、数据库存储以及对外的协作等,那么开发微服务的团队就需要是跨职能的,拥有软件开发所需的全方位技能。
这对团队组织是一个新的挑战,但也在不确定中孕育着新的契机。
特性三:做产品而不是做项目
传统的应用系统开发模式是项目模式,开发团队负责开发,开发完成后移交给测试团队测试,测试完成后再移交给运维团队部署运行。一旦系统部署上线,之前的开发团队就认为万事大吉了,开始转向下一个项目。
微服务强调采用产品模式:构建微服务的团队对其整个的生命周期负责,包括部署上线以后。最著名的理念就是亚马逊提出的”谁构建,谁运行”,开发团队对一个在生产环境下运行的软件负全责。
这样做的好处不言而喻,相信任何开发人员都不希望在大周末陪家人享受幸福时光的时候被电话叫回公司修复线上的Bug,特别是那个服务还是自己构建的。这对自己将是一种刻骨铭心的痛。
关于亚马逊的“谁构建,谁运行”原则的理论基础,请参考这篇文章。
特性四:智能端点与傻瓜管道
我个人认为这个特性是老马的博客中比较难理解的一部分,因为作者引入了两个比较抽象的概念——智能端点
和傻瓜管道
。
什么是智能端点,什么是傻瓜管道?这需要从微服务的运作特点来理解。
微服务是依照”业务功能“来构建,那么它的实现目标就是尽可能的”高内聚和低耦合”,微服务内部拥有独立而完整的业务逻辑,微服务之间像管道(Pipe)那样传递消息流。这种模式就像经典的Unix系统上过滤器(filter)的工作机制,接收请求,按照业务逻辑进行处理,最后产生响应消息。
智能端点就是指拥有独立而完整的业务逻辑的微服务,它们从管道上获取消息,进行智能处理,然后产生处理后的消息,放回管道。
傻瓜管道就是指连接微服务进行消息传递的通信机制,它们只负责消息流的传送,不承载更多的关于业务逻辑上的分析和处理。
傻瓜管道的协议类型通常有两种:同步的协议类型,比如REST风格的HTTP协议和轻量级的RPC协议(Thrift等);异步的协议类型,比如各种消息队列(Apache kafka等)。
特性五:去中心化地治理技术
我认为这个特性是使用微服务最明显的优势,每一个微服务都可以采用最适合的技术栈来构建,而不至于像原先构建单体应用那样,统一到单一的技术平台和标准。
想要使用Node.js来搞出一个简单的报表页面?尽管去搞。
想用C++来做一个特别出彩儿的近乎实时的组件?没有问题。
想要换一种不同风格的数据库,来更好地适应一个组件的读取数据的行为?可以重建。
It's cool for programmers!
做自己擅长的事,并把擅长的事做到极致!——这句话也很好地表述了微服务的精神特性。
特性六:去中心化地管理数据
传统的应用系统使用一个中心的数据库来管理数据,这样方便事务操作,可以保证数据的一致性。
微服务主张数据去中心化,各个微服务拥有自己内部的数据存储方案,对外不暴漏数据的细节,跟外部打交道的只有设计良好的API。
但是这种数据模式的变化,对于数据的一致性保证是一个巨大的挑战。微服务的这种数据方式使得事务操作不再可行,而且通过简单的视图方式展现数据的方法也不再可能。这真是一件令人头疼的事情啊!
但微服务要想朝着高内聚低耦合的目标努力,就必须这样分而治之,别无选择!
我们能做的就是应对这个挑战,拿出切实可行的方案解决这个问题。但如何解决,老马没有展开说。这一点我们团队在实践中做的也不好,需要更多的探索和尝试。
特性七:基础设施自动化
微服务架构的实施跟自动化技术密不可分,也可以说,没有自动化技术的支撑,微服务架构的实施会遇到瓶颈。
为什么这么说呢?因为一个大型的应用系统,如果采用微服务的架构,意味着可能会有成百的微服务被构建出来,这种数量规模的微服务系统,相对于之前的单体应用系统,在构建、部署和运维上要复杂很多,如果单靠人工操作,没有自动化流程的支撑,将是一场噩梦。
当然,基础设施的自动化技术在近几年里飞速发展,特别是各种云平台的出现,已经大大降低了构建、部署和运维微服务的操作复杂性。这是一个非常好的发展微服务的契机。
微服务构建、测试、部署这个流水线的自动化是必不可少的,大致包括几大方面:
-
自动化测试
- 编译
- 单元测试
- 功能测试
- 验收测试
- 集成测试
- 用户验收测试
- 性能测试
-
自动化部署
- 部署到构建的环境
- 部署到集成的环境
- 部署到用户验收测试的环境
- 部署到性能测试环境
- 部署到生产环境
特性八:容错设计
单体应用分解成诸多独立的微服务,虽然有诸多的优点,但凡事必有两面性,你享受微服务优势的同时,也必然要忍受其缺陷。
而使用微服务架构的一个很大缺陷就是故障发生的概率将会成倍的增加,所以对应的就需要为此添加很多的容错设计。
总结一下这个问题,就是:当服务提供方不可用时,客户端如何优雅的应对这种情况?
具体的应对措施有以下几种:
-
网络超时:当等待响应时,不要无限期的阻塞,而是采用超时策略。使用超时策 略可以确保资源不会无限期的占用。
-
限制请求的次数:可以为客户端对某特定服务的请求设置一个访问上限。如果请 求已达上限,就要立刻终止请求服务。
-
断路器模式:记录成功和失败请求的数量。如果失 效率超过一个阈值,触发断路器使得后续的请求立刻失败。如果大量的请求失败, 就可能是这个服务不可用,再发请求也无意义。在一个失效期后,客户端可以再试, 如果成功,关闭此断路器。
-
提供回滚:当一个请求失败后可以进行回滚逻辑。例如,返回缓存数据或者一个 系统默认值。
特性九:演进式设计
在这一部分,专家们对微服务技术采取谨慎保守的态度。
这是可以理解的,因为任何完美的系统都不是一蹴而就的,都有一个从无到有,从小到大的演化过程。
专家们建议,从一个单块系统作为起点,保持其模块化,当这个单块系统达到一定的规模,开始出现问题后,再将其拆分成微服务,是一个不错的开始。我很认同这个建议,因为这是一个可行的起点。
当然,在系统演化的过程中,我们要考虑模块化和组件化,这是走向微服务之路的必要保证。一个组件的关键属性,是具有独立更换和升级的特点,想象一下,能够在一个点上重写该组件,而无须影响该组件的其它合作组件,是一个考虑组件是否独立更换和升级的好方法。
专家们对使用微服务采取谨慎的态度还有另外一种考量,那就是一个团队的技能因素——新技术往往会被技术过硬的团队所采用。对于技术过硬的团队而更有效的一项技术,不一定适用于一个技术略逊一筹的团队。一个糟糕的团队,总会构建一个糟糕的系统——不管是单体架构的应用,还是微服务架构的应用。
可见,不管是什么技术和工具,使用它们的人至关重要。提升自己、提升团队的能力,是保证正确地做事的关键。
写在最后
上面是大师们给我们揭示的微服务的一些核心特性,我个人认为有点过于的抽象和概括,没有对诸多的问题做深入的分析和提出相应的解决方案,需要我们自己努力的去探索。
但从宏观层面,让我们对微服务做了很好的把握。这就像展开一个地图的卷轴,首先映入眼帘的是七大洲四大洋,以及各个国家大的版图,具体到各个国家的详细面貌,山川河流,就需要我们自己去游历探索。
我们应该期待这样激动人心的旅程。