# 微服务

# 微服务

:Microservices ,一种服务器架构,将业务系统从单个大型程序,拆分成多个小型程序,称为微服务。

  • 优点:

    • 将程序从单体架构拆分成微服务架构,有利于模块化的设计模式。
    • 低耦合:每个微服务作为一个独立程序运行,通过 TCP、HTTP 等协议相互通信。不同服务可由不同团队同时开发,甚至可采用不同的编程语言。
    • 容易扩展:想更新一个功能时,单体架构需要整体更新部署,而微服务架构只需要更新部分服务,不会中断其它功能。
    • 故障隔离:某个功能故障时(比如进程崩溃),单体架构可能整个系统不可用,而微服务架构只是部分服务不可用。
    • Docker 技术流行之后,微服务变得容易部署。通常将每个微服务部署到一个 Docker 容器中,用 k8s 编排。
  • 缺点:

    • 微服务架构存在一定难度,比如要提供服务发现机制、维护分布式系统。
    • 单体服务执行一个事务时,通常要调用多个内部函数。而微服务执行一个事务时,通常要调用多个微服务的 API ,进行网络通信,因此耗时更久。
  • 从头搭建微服务系统很麻烦,通常使用开源的微服务框架。例如:

    • Spring Cloud
      • :一个 Java 框架。微服务之间通过 RESTful API 进行通信,性能比 RPC 低。
    • Dubbo
      • :一个 Java 框架,由阿里巴巴公司发布。微服务之间通过 RPC 协议进行通信。

# API Gateway

  • 假设 client 需要访问多个 server ,分别发送 API 请求。可引入一个服务器作为网关,让 client 将请求统一发送到网关,然后网关再将请求转发到各个 server 。
    • 使用网关便于批量管理 API ,进行路由、身份认证、权限控制、监控等操作,比单独在每个 server 处操作更方便。
    • 单体服务通常对外暴露的 API 少,没必要用 API 网关。而微服务之间需要相互调用,存在大量 API ,因此通常使用 API 网关。
  • API 网关的软件举例:
    • Zuul
      • :由 Netflix 公司开源,成为了 Spring Cloud 自带的组件。
      • 性能较差,因此出现了试图取代它的新项目 Spring Cloud Gateway 。
    • Kong
      • :一个基于 OpenResty 服务器的网关。
      • 提供了 4 层代理(TCP/UDP)、7 层代理、动态路由、健康检查、限流、身份认证、权限控制、日志等功能。
    • APISIX
      • :一个基于 OpenResty 服务器的网关。借鉴了 Kong ,但功能更多、性能更好。

# Service Mesh

:服务网格, 2016 年提出的一种微服务技术。

  • 特点:
    • 在服务器增加一个网络代理层,处理各个微服务收、发的网络流量,比如过滤、修改网络包。并提供服务发现、负载均衡等功能。
    • Spring Cloud 等微服务框架只适用于特定的编程语言,还需要修改业务代码来适配。而 Service Mesh 属于透明代理,与编程语言无关,不侵入业务代码,即可管理网络流量。因此可将传统程序直接迁移到服务网络中,变为微服务架构。
  • 几种框架举例:
    • Envoy :2016 年,由 Lyft 公司发布,后来捐赠给 CNCF 基金会托管。采用 C++ 语言开发。
      • Envoy 的核心是一个透明代理软件,支持代理 TCP、UDP、HTTP、gRPC 等多种协议的流量。还提供了服务发现、健康检查、负载均衡等功能。
    • Linkerd :2016 年,由 Buoyant 公司发布。采用 Golang 语言开发。
    • Istio :2017 年,由 Google、IBM、Lyft 公司联合发布。采用 Golang 语言开发,基于 Envoy 代理流量。
    • Consul Connect :2018 年,由 HashiCorp 公司发布,作为 Consul 的新功能。

# 标签路由

  • 微服务系统中,可能某个服务同时部署了多个版本,需要供不同客户端访问。常见的解决方案是标签路由。

  • 仅网关的标签路由方案:

    • 原理:
      1. 服务 A 部署多个版本的实例,分别添加 env=v1、env=v2 等标签,表示服务版本。
      2. 客户端发送 HTTP 请求给网关,通过 uri、headers 等方式传递 env=xx 标签。
      3. 网关收到 HTTP 请求,发现该请求指向服务 A ,并且标签为 env=xx 。于是网关找到正确版本的服务实例,将请求转发过去。
    • 优点:
      • 实现简单。只有少量服务时,可用 Nginx 反向代理,不需要修改服务代码。有大量服务时,可用 Nacos、k8s 等服务发现平台,记录每个服务实例的标签。
    • 缺点:
      • 只在网关处进行了标签路由,服务之间没有标签路由。如果服务 A 还会调用服务 B ,而服务 B 也部署了多个版本,则会调用任一版本的服务 B 实例。
  • 全链路的标签路由方案:

    • 原理:
      1. 部署每个服务实例时,都添加形如 env=xx 的标签。
      2. 每个服务收到 HTTP 请求时,都会从 uri、headers 等信息中提取 env=xx 标签。如果该服务需要调用其它服务,则只能调用与当前标签相同的其它服务实例。
    • 假设服务 A 收到 HTTP 请求,其中标签为 env=v1 。然后服务 A 需要调用服务 B ,只能从服务 B 的多个实例中,找出与当前标签相同的实例,调用它。
      • 服务 A 调用服务 B 时,会在 HTTP 请求中传递 env=v1 标签,以便服务 B 继续调用服务 C ,实现全链路的标签路由。
      • 如果不存在相同标签的服务 B 实例,则服务 A 可以调用默认版本的服务 B 实例,或者报错 HTTP 503 。
    • 优点:
      • 标签不同的服务不会相互调用,从而在逻辑上隔离网络流量,称为不同泳道。
        • 例如给生产环境的所有服务实例设置 env=prod 标签,然后临时部署一组实例用于测试,设置 env=test 标签。这样可以快速、低成本地创建一个小型测试环境,适合灰度发布、线上调试。
    • 缺点:
      • 需要修改服务代码,主动进行标签路由。
      • 传统的部署方式中,生产环境与测试环境通常物理隔离,使用不同的服务器主机。而标签路由只是流量隔离,测试实例依然有可能影响正式实例,比如访问同一个数据库、中间件。
  • 基于 Service Mesh 的自动化标签路由方案:

    • 以 Istio 的 VirtualService 为例,当一个 HTTP 请求发送到服务 A 时,可通过 match 条件,判断应该路由到服务 A 的哪个 subset 。
      • 例:
        apiVersion: networking.istio.io/v1alpha3
        kind: VirtualService
        metadata:
          name: service-a
        spec:
          hosts:
            - service-a.default
          http:
          - match:
            - headers:
                env:
                  exact: v1
            route:
            - destination:
                host: service-a.default
                subset: v1
          - route:
            - destination:
                host: service-a.default
                subset: v2
        
      • 当服务 A 收到 HTTP 请求而调用服务 B 时,需要传递 env=xx 标签。可通过 Istio 的 EnvoyFilter 自动修改服务 A 发出的 HTTP 请求,根据当前的 k8s label 取值,在 headers 中添加 env=xx 标签。
    • 优点:
      • 不需要修改服务代码。
    • 缺点:
      • 需要为每个服务添加标签、VirtualService 配置,依然有些麻烦。可用自研的运维平台自动完成这些操作,使得开发人员能一键部署一套 env=xx 的服务实例,并自动配置标签路由,用完则一键销毁。

# 相关概念

  • 南北流量(North-South traffic)
    • :指客户端与服务器之间的网络流量。因为绘制网络架构图时,通常服务器、客户端分别位于上下两侧。
  • 东西流量(East-West traffic)
    • :指服务器内部,各个服务之间的网络流量。
    • 对于微服务架构,东西流量比南北流量更复杂、流量更大。
    • API Gateway 擅长处理南北流量,但也可处理东西流量。Service Mesh 擅长处理东西流量,但也可处理南北流量。