本节将介绍微服务系统架构的优缺点、微服务设计的原则、随着微服务而火的领域驱动设计、微服务的部署,以及微服务与云原生架构的区别。

1 微服务的优点和缺点

1.1 微服务的优点

1.1.1. 易于开发和维护

    微服务架构中的单个微服务仅关注某一特定的业务功能,因此单个微服务的开发代码量少、业务复杂度低、业务逻辑清晰、维护容易。
    由于整个微服务架构时由许多业务单一且服务自治的单个微服务组成的,因此整个的微服务开发和维护处于一种简单、可控、高效和科学的状态。

1.1.2. 启动速度更快

    与功能模块都集中在一起的单体应用相比,单个微服务的启动速度更快,这是因为:单个微服务是业务单一的,具有更少的代码,关联更少,并且不需要等待其他功能模块加载完成。

1.1.3. 局部修改后容易部署

    在系统的开发和运行过程中,经常需要对局部进行修改。但这种修改在单位应用中实现起来非常麻烦:需要在修改完成后重新发布和启动整个项目。
    在微服务架构中则不同:在修改了单个微服务后,只需将微服务重新发布、部署即可。还可以利用“蓝绿发布” “灰度发布” 实现不停机维护。

1.1.4. 技术栈不受限

    单体应用的开发常局限于一种开发语言,模块之间的通信基本上是通过调用同一种语言的功能函数来实现的。
    微服务架构可以做到与语言工具无关,开发团队可以根据自己的技术情况和业务需求,自由选择适合的语言和工具来开发模块。

1.1.5.按需伸缩

    一般而言,需求总是在不断变化的,在单体应用中,如果想扩展某个模块的功能,则需要考虑其对其他模块的影响。而在微服务架构中,则可以灵活地按需伸缩,不会对其他模块产生性能和扩展能力的影响。根据需求,微服务可以实现细粒度的扩展,比如,可以结合微服务业务的特点来增加相应服务的硬件资源(如果是计算密集型服务,则增加CPU资源;如果是I/O密集型服务,则增加内存和硬盘资源)。

1.1.6. 松耦合

    微服务的业务单一和服务自治,使得其内部是高内聚的,而微服务之间是松耦合的,因此每个微服务可以很容易按需扩展。

1.1.7. 弹性强(允许部分故障)

    由于微服务很容易实现高可用的服务集群,并采用服务治理组件来实现服务的治理,因此,部分服务出现故障不会对整体的服务能力和可用性造成很大影响。

除此之外,微服务的优点还有:测试和调优简化、水平扩展独立、复用性高、运维自动化、组织上并性、灵活性高等。

1.2 微服务的缺点

    微服务架构虽然是时下极为流行的架构,但也有缺点。微服务存在以下缺点。

1.2.1. 运维要求较高

    单体应用的运维非常方便,只需要维护整个应用,不涉及太多的集群管理和监控。
    而完整的微服务系统一般是由数十个、数百、数千个独立的微服务实例构成的。在生产环境中,还需要实现微服务的高可用集群部署(部署多个同样功能的微服务),因此即使在较小规模的微服务系统中,微服务实例的数量也可能达到数万或数十万个。庞大的微服务实例数量使得微服务实例之间的通信、调用、链路跟踪、容错管理变得非常困难和复杂。这给开发和运维都带来了巨大的挑战。

1.2.2. 分布式问题
(1). 分布式的复杂性

    对于微服务架构来说,分布式是必要的技术,但是分布式本身的复杂性会导致微服务架构变得更加复杂。在分布式系统中,系统的容错能力、网络延迟、分布式事务、依赖服务的不稳定等都会带来巨大的挑战。

(2). 分布式的事务问题

    分布式的事务一致性问题在微服务系统中更为突出明显。事务一致性方案有以下三种:

  1. 可靠事件模式(Reliable Event Mode): 通过保证事件收发的高可靠性来保证事务的一致性。
  2. 补偿模式(Confirm Cancel): 如果最终确认失败,则全部逆序取消。
  3. TCC(Try Comfirm Cancel): 补偿模式的一种特殊实现,通常转账服务会采用这种模式。
(3). 分布式的同步调用问题

    在微服务架构中,需要保证“在不确定的环境中交付确定的服务”,即在无法保证所依赖的服务的可靠性的情况下,要保证自己能够正常地提供服务。这个问题可以用SEDA(Staged Event Driven Architecture,分阶段的时间驱动架构)架构来解决。
    SEDA的核心思想:将一个请求处理过程划分为多个Stage(阶段),不同资源消耗的Stage使用不同数量的线程进行处理,各个Stage之间采用事件驱动的异步通信模式。

1.2.3.接口调整成本高

    接口调整主要需要面对以下问题。

(1) 调用的修改。

    微服务的实例数量众多,如果要调整调用的接口,则可能需要对相关的微服务实例进行调整。

(2) 接口文档的编写。

    在调整接口后,需要重新发布的接口文档。如果接口文案过期了,则可能会对其他服务的调用带来影响,因此需要对接口文档进行管理。在开发过程中,可以使用诸如Word、Wiki、ApiDoc、RAP 、DOCLever、CrapApi、Swagger、Yapi等工具来管理接口文档,解决接口管理和维护的问题。

(3) 变更难以跟踪

    微服务的变更变得难以跟踪,可能会出现以下几种情况:

  • 接口文档过期。
  • 接口文档已经更新但未及时通知。
  • 微服务的调用方未能及时处理最新接口文档。
  • 依赖的相关数据还没有准备好,不能及时地根据文档验证功能。

    技术无法解决所有的问题,需要一套管理体系来协助整个系统的工作。

1.2.4. 重复劳动

    在单体应用中,常常可以通过构建抽象的工具类来解决重复编码的问题。但在微服务架构中,尽管很多单个的微服务具有相同的功能,却没法将这些功能抽取出来供服务集群或其他微服务使用,因为微服务之间的调用是远程调用。
    尽管共享库算是一种解决方案,但在跨语言环境中共享也不一定可以使用。因此,在跨语言、跨团队、跨系统的微服务架构中,常存在部分模块重复构建的情况。
    对于以上几个问题,可以通过技术、开发原则和规范,以及管理来解决。例如,

  • 制定文档管理规定。
  • 实现统一的认证、配置、日志框架、综合分析监控平台。
  • 搭建持续集成平台。

    这些问题也可以通过使用诸如Spring Cluod 这样的成熟微服务架构框架来解决。

2 微服务的设计原则

    微服务的设计原则应遵守以下原则。

2.1 业务单一原则

    业务单一原则是拆分微服务的主要原则,它使得微服务的开发更加优雅、交付更敏捷。在这一原则下,单个微服务模块只关注功能单一、有界限的业务逻辑,从而完成某个特定的功能。比如:

  • 会员模块只完成会员注册、登录功能。
  • 认证模块只完成认证功能。
  • 授权模块只完成对资源的授权功能。

    这3个微服务模块组成会员的注册登录,实现对资源的认证和授权功能。即,每个微服务可独立运行在自己的进程里,一系列独立运行的微服务模块共同构建起整个系统。
    业务单一原则指导着微服务拆分的粒度大小。微服务的粒度是微服务开发中的一个重点和难点,也是一个争论的焦点。是把粒度划分为最小,还是根据代码量的多少来控制粒度,又或是根据业务复杂度来控制粒度,并没有特定的标准,必须根据业务本身进行设计。在微服务的最初设计阶段就应该明确其边界,但一定要做到高内聚、独立和低耦合。

2.2 服务自治原则

    服务自治是指,每个微服务都应具备独立的业务能力和运行环境;开发、测试、构建、部署都应该可以独立运行,包括存储的数据库也应是独立的;微服务是独立的业务单元,而不应该依赖其他的微服务,并应能与其他微服务高度解耦。
    服务自治带来的好处如下。

  • 技术选型灵活:技术选型不受遗留系统技术栈限制,因为微服务与微服务之间采取的是与语言无关的集成,因此不同的业务可以选择不同的技术栈。
  • 团队独立和自治:技术团队对服务的整个生命周期负责。在整个微服务架构中,实现“谁开发,谁维护”,这使得整个微服务开发变得高效和独立。
  • 开发和演进独立:服务自治使得开发和演进比较独立,微服务之间不相互影响。
  • 有利于持续集成和持续交付:在服务自治的原则下,灵活的代码组织方式、可控的发布节奏为持续集成和持续交付奠定了基础。

2.3 轻量级通信原则

    由于构成微服务系统的微服务数量众多,因此,微服务之间的通信机制应该是轻量级的。轻量级的通信机制应该具备以下两点。

  • 体量较轻:通信的语言非常轻量。
  • 能跨语言、跨平台:通信方式需要能跨语言、跨平台,这样每一个微服务都有足够的独立性,可以不受技术的限制。例如,REST协议是一种轻量级的通信机制,而RMI(Remote Method Invocation,远程方法调用)绑定了java 语言的通信协议,不属于轻量级通信协议。在微服务架构中,常用的通信协议有REST、RPC、AMQP、STOMP、MQTT等。

2.4 接口明确原则

    微服务之间存在调用关系,为了避免以后因为某个微服务的接口发生变化而导致其他微服务都需要调整,所以在设计之初就要让这些接口尽可能具有通用性和灵活性。

2.5 弹性(容错性)设计原则

    弹性几乎是所有系统的基本要求。在微服务系统中,在依赖的服务宕机、网络连接出现问题时,应能自动隔离服务、限制使用资源,或者对服务降级,即系统具有自我保护能力。
    成熟可选方案,比如Hystrix,它提供了熔断、回滚等功能。

2.6 自动化原则

    微服务架构也面临着许多的挑战,我们最好提供一套自动化方案来解决这些问题,因为在复杂的微服务体系下,以人工方式来运维显然是不合理的。能够自动化的一定要实现自动化,应该用自动化和标准的方法拉提高效率,降低成本。

  1. 自动化测试
    在微服务架构中,测试是一个极其复杂的过程。自动化测试可以减轻测试的负担,并且能够保证大量的微服务模块正常工作。
  2. 自动化监控与管理日志。
    监控和管理日志是指,监控微服务的状态、快速定位异常或错误。在微服务架构中,这两个功能尤为重要,因为微服务实例数量庞大、服务间调用极为复杂。
    监控功能主要包括监控服务的可用状态、请求流量、调用链、错误计数、服务依赖关系等内容,以便及时发现问题并解决问题。也可以根据监控状态来及时调整系统负载、过载保护等,从而保证系统的稳定性和高可用。
  • 微服务可用性的监控,可以使用Spring Boot Admin组件。
  • 熔断器机制可以使用Hystrix。它还可以收集一些请求的基本信息(比如请求响应时间、访问统计、错误统计等),并提供现成的Dashboard 将信息可视化。
  • 性能监控和调用链追踪,可以使用Dynatrace、Sleuth、或Zipkin。
  1. 持续集成和持续交付。
    持续集成是指,频繁地将代码集成到主干。这样做可以迅速发现错误,防止分支过度偏离主干,从而实现快速迭代并保证软件质量。
    持续交付,频繁地向测试人员和用户交付系统的新版本,以便进行测试和评审。
  2. 持续部署
    持续部署是持续交付的下一个步骤,是指将通过的代码自动部署到生产环境中,自动化部署是减少发布和部署的难度、复杂性和繁琐程度的过程。现有很多成熟的解决方案,比如Jenkins+Fastlane( Jenkins能自动检测Git代码的上传,然后调用脚本代码)。
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐