微服务架构是一种应用架构风格,其应用由各种微服务组件组成。尽管对“微服务”这种架构风格尚没有精确的定义,但其具有一些共同的特性,如围绕业务能力组织服务、自动化部署、智能端点、对语言及数据的“去集中化”控制等。
近年来,架构风格逐渐从整体式演变为微服务式。整体式架构(Monolithic Architecture)是一种提供所有能力的大型应用,微服务架构(Micro-Services Architecture, MSA)则包含若干个较小的应用,每个应用都是整体的一部分,可以降低开发难度、增强扩展性,便于敏捷开发。
面向服务的架构(Service-Oriented Architecture, SOA)也逐渐演变为微服务架构。面向服务的架构以集成为导向,将多个应用程序模块集成为整体服务,使用技术API接口。微服务架构则以解耦为导向,将单体应用解耦为多个面向业务的功能模块,注重业务能力,使用业务API接口。
面向服务的架构并不特指一种技术,而是一种分布式运算的软件设计方法。软件的部分组件(调用者)可以通过网络上的通用协议调用另一个应用的组件运行、运作,让调用者获得服务。SOA原则上采用开放标准与软件资源进行交互,因此能跨厂商、产品与技术。一项服务应视为一个独立的功能单元,可以远程访问并独立运行与更新。
如图2.8所示,在SOA中,我们把整个软件划分成一个个模块,每个模块可以作为服务提供者(Provider)或消费者(Consumer)来提供服务或使用服务。同时,模块之间的通信使用企业服务总线(ESB),而非模块直接连接和调用。
图2.8 SOA
采用这种机制,我们把整个企业里纷繁复杂的业务逻辑划分成一个个独立的单元,每个单元与其他单元都在统一的通信频道上沟通,可以大大地简化企业内部的复杂IT系统架构。以银行业来说,大部分银行的IT系统或多或少都有SOA体系思想的引入。
1.为什么要引入微服务架构
(1)企业面临的问题:更新和修复大型整体式应用变得越来越困难;企业被迫将其应用迁移至现代化用户界面架构以便能兼容移动设备;许多企业在SOA投资中得到的回报有限,SOA可以通过标准化服务接口实现能力的重用 [6] ,但对于快速变化的需求,受到整体式应用的限制,有时候显得力不从心;随着应用云化的日益普及,基于云端的应用具有与传统IT不同的技术基因和开发运维模式。
(2)微服务架构的好处:小范围的、独立的、可扩展的组件能够实现最快的交付和推出市场速度;具有可扩展性,能够实现弹性可伸缩和工作负载编排;具有敏捷性,具有更快的迭代周期,具有边界清晰的上下文(代码与数据);具有弹性(快速恢复能力),可减少相互依赖性,快速试错。
2.微服务架构的7个原则
(1)清晰定义业务边界:应用程序的模块化梳理是微服务应用设计的最核心要素。从传统瀑布式开发向面向对象开发转型会让很多程序员不太习惯,瀑布式开发流程更多关注实现细节以及功能之间的耦合,是一种自底向上的构建思路。而面向对象开发则相反,它把整个应用程序以对象互动的形式进行高阶设计,对象之间的联动部分以接口的形式体现,每个对象内部的实现细节对外部隐藏,这样进行测试框架的设计以及未来代码的替换会非常容易。微服务架构也一样,微服务之间完全隔离,但是为了避免成千上万个微服务互相编织在一起,在微服务的上层往往需要定义业务域,将不同的微服务放置在不同的业务域中,业务域之间的交互通过一些特定的对外微服务体现。而业务域内部的数据结构、微服务之间的消息结构对业务域之外同样需要做到隐藏。
(2)自动化能力提升:此原则在真实业务场景中至关重要。微服务架构的应用对开发者来说意味着一大堆新框架的引入,而对于运维者来说,最大的挑战就在于自动化运维。微服务的初衷是敏捷,它需要将集群拓扑调整、服务流程变换、持续发布流程、模块的功能性能测试、版本管理、灰度发布等融入自动化框架。手工维护一套复杂的微服务框架,不出错基本是不可能的。所以,想要真正实现微服务框架,运维层面需要有非常健壮的PaaS平台。
(3)隐藏实现细节:这个实际上和第一个原则差不多,只不过更强调的是在每个业务域之内的数据结构与代码实现,对于外部的业务域来说要做到完全无感知。一般来说,业务域之间的微服务通信采用标准的JSON或XML协议进行数据交换,而业务域之内的通信协议则由部门内部自行处理,同时对于数据库的结构必须做到对外完全隐藏。
(4)自治原则:尽可能实现完全自治,不再需要一个中央的负责人或模块统一管理。例如,最简单的资源申请尽可能做到流程自动化,可能最多需要一两道审批工作,不再需要像过去一样,购买一台设备需要耗费数月时间进行审批。可利用自助化服务、共享监管、自助操作、内部开源、智能终端等服务尽可能给予人们自己完成全部工作的自由。
(5)独立部署:在微服务部署的过程中,每个微服务都可以从逻辑到物理与其他微服务完全解耦,运行在完全隔离、只有网络互通的环境中。举例来说,过去我们编写应用程序,依赖包必须存放在指定的目录中,否则Java代码可能无法加载。但是在微服务的设计理念中,所有的依赖关系只能通过网络通信,每个微服务内部一定是完备的,不需要与其他任何应用的逻辑产生物理层面的依赖。
(6)故障隔离:在微服务中,成千上万个小的服务通过网络互相编织在一起。编写这些服务代码的可能有年轻的程序员,也可能有资深的程序员,大家对代码严谨性和测试的完备性的理解可能都不大一样。那么,如何避免牵一发而动全身,一点点错误造成整个系统雪崩呢?这就涉及故障隔离。故障隔离可以包括熔断机制,如果流量过高或者有其他异常行为,或者通过现在流行的AIOps自动检测到非预期的行为,一方面会产生警告,另一方面会自动将某些模块下线或者降速,以达到故障隔离的目的。而像灰度发布是把新代码和旧代码同时运行一段时间,流量上做到逐步向新代码切换,而不是一刀切全都转移到新代码逻辑上。
(7)可视化监控:可视化监控也是和运维息息相关的。在调试分布式系统应用的过程中,出现任何问题,通过逐个服务查看日志的方式进行故障排查是极其困难的。所以,微服务中所有的监控和日志分析必须做到可视化和可关联,当然,也必须把会话ID等关联ID在日志中合理体现出来,否则在多个微服务之间进行会话逻辑关联分析会非常困难。