微服务架构概览

在正式讨论微服务架构前,有必要用简短的篇幅,讨论下微服务以及这种架构风格的优点和缺点。

在微服务出现之前,我们的架构多数是单体应用架构。会有一个或者少数几个”巨无霸“进程,里面可能包含了”用户管理“、”订单管理“、”支付确认“、”物流“等等各种复杂的业务逻辑和功能。这种传统的单块应用架构风格是很直观、自然的,然而在现代软件开发领域,特别是互联网开发领域中,单块架构遇到了一些问题。

单块架构的缺点

  • 耦合严重:单块服务内的各个逻辑之间,往往缺乏清晰的边界。导致内部耦合严重,正所谓“牵一发而动全身”。
  • 维护困难:单快服务包含了过多的业务,代码量严重膨胀。开发人员难免”失焦“,不知道如何下手。
  • 团队协作困难:如果多人同时开发同一个单块应用,势必导致代码冲突成为常态,团队协作成本急剧上升。
  • 测试困难:单块服务是作为一个整体进行开发、上线的。尽管你只对A功能进行了修改,但难免会影响B功能。随着单块应用的愈发膨胀,测试工作量会提升数倍。

上述单块应用的缺点,在传统软件开发中,尚可通过“小心规划”、“人海战术”等方法解决。但到了互联网时代,就很难实现了。为什么这么讲呢?互联网软件开发,讲究的是“快糙猛”,对迭代速度的要求非常高。对于成熟的互联网企业,一个项目在一天内上线好几次,都是稀松平常的事情。试想一下我们的单块“巨无霸”服务,稍微改动一点,就要经过复杂的代码评审、测试验证,如何才能跟上快节奏的迭代和上线呢?

尽管微服务不是银弹,但微服务的出现,确实从一定程度上改善了这种情况。微服务是⼀种架构⻛格,将单块应⽤划分成⼀组⼩的服务,服务之间相互协作,以组合的形式,实现复杂的业务功能。

微服务架构的优点

  • 低耦合:在单块服务中,不同业务的逻辑耦合在一起。做微服务拆分后,微服务内只包含有限的业务逻辑,耦合也随之大大降低。
  • 易维护:微服务内部只包含单一业务逻辑,功能更为集中,更容易开发人员聚焦问题和修改。
  • 适合团队协作:拆分为微服务后,每个服务中涉及的代码和功能更少,可以将不同微服务划分给不同团队甚至个人负责。各司其职后,有效降低了开发和代码冲突,使得其适合团队协作。
  • 测试成本低:在单块服务中,哪怕只改动了一点点代码,也需要对整个巨无霸服务进行测试。微服务拆分后,功能的修改,只需要涉及改动的个别微服务进行测试,有效降低了测试工作量。
  • 易横向拓展:在单块服务时代,巨无霸服务已经占用了大量资源,机器的配置已经很高,若要再单独部署一个结点做负载均衡,成本会非常很高,所以多数情况下,都是通过纵向拓展的方式提升系统性能(如加内存,换个更好的cpu)。采用微服务拆分后,各个微服务占用的资源更少,可以轻松的通过增加节点的横向拓展方式,提升系统性能。更进一步的说,根据阿姆达尔定律,微服务拆分后,各个微服务对性能的要求并不一致,可以优先拓展那些具有性能短板的微服务,有效降低了拓展成本。
  • 技术选择更多样:由于微服务是各自独立的进程。各个团队可以根据自己的需要选择不同的技术方案。然而在实践中,我并不推荐这么搞,这会在后面技术选型时展开。
  • 加快迭代速度:上面已经提到,微服务低耦合、易维护、适合团队协作、测试起来成本更低,也更易于横向拓展。采用微服务架构后,可以显著的提升迭代速度。

尽管微服务具有这些优点,我想再次强调:“”微服务不是银弹“”,他解决了单一服务的软件复杂度,提升了迭代速度,但也带来了一些缺点。

微服务架构的缺点

  • 运维难度加大:在单块架构中,不管改动多少需求,只需要上线一个服务。而采用微服务后,为了一个需求,可能要上线一堆服务。
  • 开发能力要求高:在单块架构中,巨无霸服务的逻辑都在一个项目中。采用微服务后,逻辑分散在不同的项目中,在加上微服务架构本身引入的新技术,对开发能力提出了更高挑战。
  • 调试难度更大:在单块架构中,我们只需要关注一个或少数几个服务。应用微服务架构后,后端系统演变为分布式系统,可能会出现A调用B,B调用C,甚至C还要调用D的长调用链,势必增加了调试和问题排查的难度。

幸运的是,通过容器等的新技术的引入,以及合理的架构设计,这些缺点都可以得到一定程度的缓解。本书会在后续章节对这些问题进行展开。

在讨论了微服务的优缺点之后,我们可以看一下微服务的整体架构了。

微服务整体架构

如上图所示,微服务架构可以大致分为五个层次,我们自底向上,逐层做一下解释。

  • 基础设施层
    • 微服务是后端服务,最终一定要部署在基础设施的某台机器上。基础设施层可以是自运维的服务器或机架,也可以选用云计算的虚拟机。
    • 在这一层,我们重点关注底层“物理资源”^1的可用性及调整:计算资源(CPU 和 GPU)、存储资源(内存、硬盘)、网络资源(交换机、路由)。对这些基础设施的维护,或者是直接在机房维护,或者是操作云平台的API。
    • 举几个例子:大促前预估系统容量不足,我们要加半个机架的机器;直播平台今晚要来大V,预计带宽不足,要增加带宽。这些都是在基础设施层要关注的内容。
  • 运维平台层
    • 对于后端服务的运维工作,持续交付是最重要的能力。由于微服务数量众多,一般需要构建一个持续交付系统,来完成微服务的自动运维,如微服务的初始化、发布、回滚、扩容。
    • 采用微服务架构后,上线的次数、频率都会显著提升,这就需要一个上线的镜像版本管理系统,记录上线的镜像版本。在微服务架构中,一般采用容器技术来实现微服务的自动运维。
    • 容器是轻量级资源,隔离能力相对较弱,我们需要对容器资源进行监控,调度和管理。举个例子:我们有三台物理机,现在物理机A和C各运行了20个容器,物理机B运行了22个容器,假设每个容器的资源占用完全一致,那么资源调度系统会自动地,将B的两个的容器调整到物理机A和C上。
  • 微服务设施层
    • 假设服务A需要调用服务B,那么A服务如何获取服务B的地址(例如IP和端口)呢?在传统的单块架构中,服务数量很少,尚可采用同在配置中写死IP、端口的方法来解决这个问题。但在微服务时代,面对动辄成百上千的微服务,这种做法将不再可行。因此,如何自动注册、发现微服务的多个实例,是架构必须解决的核心问题。
    • 微服务拆分后,我们的系统从单机演化为分布式系统,为了防止分布式系统的雪崩效应^2、微服务设施需要有的熔断和限流的能力。
    • 面对众多的微服务,逐一修改配置的方式显得更加笨拙,我们需要有一个中央配置平台,快速完成微服务的配置修改。
    • 前面已经提到,微服务的分布式架构,会加大调试难度,所以日志的收集和预警显得更加重要,同时,我们可以根据业务日志来进行一些监控预警,这和平台层的容器监控预警是不一样的。
    • 微服务需要集成一些后端组件,如数据库、消息队列、缓存等。
  • 业务服务层:在提供了微服务的基础设施后,我们可以放手开发各个微服务了。业务服务层是一些“基础微服务”或“业务微服务”,他们“各司其职”,服务之间的耦合应当做到最低。
  • 接入网关层:微服务面向的“用户”,一般是Web、移动端、PC端等。出于用户体验的考量,服务端提供给客户端的的接口应当尽量实现结果聚合,减少请求次数。因此,一般要设置一层接入网关,他负责调用业务微服务A B C等,完成结果聚合后,一并返回给客户端。

在绝大多数的公司中,业务规模不会很大,所需要的机器也非常有限,基础设施层往往会使用云平台或机房托管的外包方式完成。因此,本书将不对基础设施层做过多讨论。