聊聊微服务架构

微服务概述

微服务,顾名思义微小的服务,当传统的单体应用规模和复杂度达到一定程度的时候,应用的管理、扩展、可靠性等方面就会出现瓶颈,一个基本原则就是分而治之,把一个大的复杂应用拆分成多个小的服务,让每个小服务可以单独进行管理、扩展,微服务由此演化而来。

微服务强调拆分后服务的独立性,麻雀虽小,五脏俱全,每个微服务有自己独立的数据库,有自己的业务实现,各自运行在独立的进程中,对外提供设计好的接口,服务间去耦合,通过 RPC、HTTP 等协议进行远程交互,服务内部功能可以使用任意语言和框架实现,对外是不可见的。

微服务架构特点

去中心化

传统的单体应用只有一个服务,这个服务就是系统的中心,而微服务架构是去中心化的,把复杂的系统拆分成多个简单的分布式组件,每个组件都是服务化的,能够独立部署独立升级。

除了业务逻辑去中心化,数据同样也要去中心化,微服务要有自己独有的数据库,每个服务只对自己的数据负责,也不允许直接读写别人的数据库,就像自家的资产只能自己处置,别人不能随便动。

专注做好一件事

微服务架构的关键在于业务功能的合理拆分,以最终实现分布式系统的高内聚、低耦合,如果拆分不合理还会导致后期代码维护和功能扩展越发困难。

通常架构设计时尽可能使每个微服务专注做好一件事,合理划分服务边界,使数据结构易于独立,对外接口简洁通用,一个好的设计理念就是领域驱动设计 (Domain Driven Design),根据领域的边界设计服务范畴。

技术多样性

单体应用通常只能采用单一语言开发,但每种编程语言都有各自优势,协作团队中通常每个人都有各自擅长的语言框架,单体应用限制了这种自由,而在微服务系统中没有这些限制,各个服务相互独立,每个服务都可以用不同的编程语言实现,每个人都可以发挥自己的特长。

事实上,技术的多样性对一个系统的健壮性也大有裨益,除了可以发挥多种语言框架的优势,还可以逐步引入新技术,有利于系统的演进升级。

服务容错保护

我们知道在分布式系统中,节点失效应被视作常态而不是意外,即节点失效是一定会发生的,要实现系统高可用,必须要提前做好预备措施。微服务体系中,由于服务间错综复杂的依赖关系,一套完整的服务往往有很长的调用链路,对微服务进行容错降级是很有必要的,当某个服务实例出错时及时进行降级、隔离,既能提高响应速度,还能防止请求积压造成雪崩。

服务容错保护和业内常提的异地多活、Design For Failure 等思想一脉相承,一方面是服务提供方的多实例冗余,另一方面是服务消费方的降级保护,都是为分布式系统的高可用所做的预备措施。

当然任何系统都很难保证绝对可用,前不久就连 AWS 和 Google Cloud 都发生过服务中断事件,它们在服务高可用方面是业内首屈一指的,但仍然会发生事故,因此我们只能通过各种容错手段尽量避免此类事件发生。

开发运维一体化

开发运维一体化即流行的 DevOps,谁开发的谁运维,这样开发人员能更快地响应业务需求,更好地保障服务后续运行和升级,同时避免团队间大量的无效沟通和摩擦。

现在流行的各种 CI/CD、自动化运维技术也在促进开发运维一体化。

拥抱容器技术

有人说容器和微服务简直是天生一对,容器的轻巧高效恰好匹配微服务的灵活多变,结合 Docker 容器技术和微服务架构有助于应用的持续集成、持续交付和持续部署,目前备受追捧的云原生技术就是直接把微服务构建在容器基础设施上。

随着 Kubernetes 等容器基础设施的日趋成熟,容器逐渐成为微服务的标准载体,在容器基础设施上构建运行高可用、高可扩展的微服务将越来越简单。

微服务的挑战

微服务作为近年来流行的软件架构风格,它能帮助我们实现系统的高可用和高可扩展性,但微服务也会有各种挑战。

应用的挑战

  • 由于微服务将整个系统进行拆分,所以系统的架构、开发工作量和复杂度会增加不少

  • 原来的单体应用变成一系列微服务,就要花费更多精力去管理和协调这些服务,系统的运维复杂度会增加不少

  • 原来调用的本地方法变成了服务间的远程调用,可能会使系统性能有所降低,这意味着要增加硬件投入

架构的挑战

除了应用中的挑战,微服务架构本身也面临挑战,根据 CAP 理论,在分布式系统中数据一致性 (Consistency)、服务可用性 (Availability)、分区容忍性 (Partition tolerance) 三者不可能同时满足,最多只能实现其中两点,那么如何根据业务特点做出最佳权衡和取舍,就是微服务架构面临的挑战。

孟老夫子说过鱼和熊掌不可兼得,则舍鱼而取熊掌者也。在分布式系统中,分区容忍是必须要满足的,所以一般在一致性和可用性之间进行权衡,要么舍弃部分一致性,追求高可用;要么严格强调一致性,损失部分高可用。

到底是高可用重要还是一致性重要,这在服务注册中心也对应着两种流派:一种是 Eureka 为代表的 AP 流派,强调高可用,弱化一致性;另一种是 CP 流派,典型的就是 ZooKeeper 这类注册中心,为保证强一致性,在某些时候(如 leader 选举期间)会牺牲可用性。

一种常用的折中方案就是 BASE 原则,它是指基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventual Consistency),也就是放弃强一致性,获得较好的可用性,允许节点间有暂时的不一致,只要最终一致就行了。

实际应用中要根据系统对高可用和一致性等各方面的要求程度,做出适当的权衡和取舍,比如在社交媒体应用中高可用比强一致更重要,而在金融交易系统中则必须保证强一致性。

是否采用微服务

对一个系统来讲,架构是逐步演进的,是否采用微服务架构要根据具体的团队和业务情况来定,一般来讲,如果团队规模和业务复杂度达到一定程度,单体应用已经力不从心的时候就该上微服务了。