文档

服务网格工作原理

更新时间:
一键部署

培训视频

观看以下视频,快速了解服务网格工作原理:

MOSN 形态现状

目前 MOSN 属于数据面的产品,以 Sidecar 的模式和应用部署在同一个 Pod 或者在虚拟机中,属于独立进程。MOSN 最早支持基于轻量 SDK + Mesh 的方式接管网格流量。目前主要支持 3 种流量劫持方式:

  • 轻量级 SDK 端口欺骗的方式接管流量。

  • 基于修改配置 IP+Port -> 127.0.0.1 的方式接管流量。

  • 基于透明劫持 iptables 接管流量。

目前自研 MOSN 已经支持国内主流框架,比如蚂蚁的 SOFA RPC、社区 Dubbo 和 Spring Cloud 技术栈 。服务发现继续使用经典的注册中心机制,内部注册中心产品是 SOFARegistry。Image 2

数据面 MOSN 产品目前支持虚拟机和容器场景部署,应用接入 MOSN。作为服务提供方,MOSN 会将自身端口号写入注册中心。作为消费方,MOSN 会从注册中心订阅服务,也就是拿到了服务方 MOSN 的 IP+Port,然后完成服务通信。

MOSN 配置关联关系

为了帮助您梳理清楚 MOSN 的一串配置关系,这里从链路关系逐一讲解。以静态配置为例,目前配置主要分为几大类,如 listeners、routers 和 clusters 等。配置截图如下:Image 3

  • listeners 主要是 TCP、UDP 等端口监听配置,包括制定端口和协议绑定关系等。

    • RPC 类别,主要支持 request-response 等通信模型,比如 Dubbo、SOFA、Spring Cloud 等私有协议。

    • MQ 场景,处理消息框架通信场景。

  • routers 主要保存和协议相关的路由配置映射,匹配 Header 中 Service 信息到具体的 Cluster。

  • clusters 主要保存 Cluster 中真实的服务地址列表。针对 RPC 场景,一般 Cluster 的 name 是接口,根据接口对应地址列表的映射关系。

上图中的数字代表流程进度:

  1. 客户端 MOSN 监听 30530 端口,等待客户端应用 App 调用。

  2. 在 MOSN 配置中,我们指定 30530 端口给私有协议 SK 使用,因此协议叫做 SK。

  3. MOSN 静态配置中指定路由配置映射关系 name 为 egress_sk_router,一般规则为 egress_协议名_router,如果是服务提供方,一般规则为 ingress_协议名_router。可以理解为这个配置映射关系是数组,里面会存储很多 Header 中包含 Service 的不同值(一般值是接口名),并且根据不同值映射到具体的 Cluster。值 .* 是特殊值,代表只要 Header 中有 Service 这个 Key,则直接转发到目标 Cluster 对应的名称。

  4. 请求 Header 包含 Service 任意值,转发到 skClientToWsServer 这个集群。

  5. 集群 skClientToWsServer 中包含的地址列表都会被 MOSN 选择调用。

如果理解静态配置和寻址关联关系,MOSN 在运行时,也会动态构造这些 Cluster 信息,因为路由都是在客户端处理的。当服务提供方上线时,MOSN 客户端会收到地址列表推送,MOSN 会去根据推送的 dataId(一般是接口名)去找到 Cluster,并且把地址列表动态更新。

值得一提的是,listeners 中 SOFARPC 目录包含较多私有协议扩展,MOSN 启动的时候默认都会加载并且开启对应端口监听,输出到专有云一般无用的协议,我们会通过 Dockerfile 文件删除无用的协议。

MOSN 调用关系

为了通俗易懂的理解 MOSN 调用链路,需要彻底弄懂 ingress 和 egress 的概念和区分。

站在 Sidecar 视角去理解 egress 和 ingress,比如 MOSN 接收流量后转发给远端还是本地:

  • egress:出口流量,MOSN 接收流量需要转发给远端的服务提供方。

  • ingress:入口流量,MOSN 接收流量无脑转发给本地的服务提供方

MOSN 调用关系图示如下:Image 4

以上入为例,MOSN 的调用链路关系如下:

  1. 服务提供方 MOSN 会将自身 ingress 的协议端口写入到注册中心。

  2. 调用方 MOSN 会从注册中心订阅地址列表。

    第一次订阅也会返回全量地址列表,端口号是服务方 ingress 绑定的端口号。

  3. 注册中心会实时推送地址列表变更到客户端(每次都是全量地址列表)。

  4. 客户端 App 发起业务 RPC 请求,请求会被 SDK 转发到本地客户端 MOSN 的 egress 端口号上。

  5. 客户端 MOSN 将 RPC 请求通过网络转发,将流量通过负载均衡转发到某一台服务方 MOSN 的 ingress 端口处理。

  6. 最终服务到了服务端 ingress listener,会直接转发给本地 App Server 应用。响应返回时,会根据原来的 TCP 链路反向转发。

Mesh 核心转发流程

MOSN 作为数据面,整体分为 4 层:

  • Network/IO 主要负责网络读写。

  • Protocol 主要负责协议编解码。

  • stream 主要负责 request、response 等模型转发和协调。

  • proxy 主要负责路由等功能。

原始的 MOSN 简介,请参见 MOSN 架构简介

为了便于理解,本文将 MOSN 的流程简化为 12 个步骤,如下图所示:Image 6

  1. MOSN 在启动期间,会暴露本地 egress 端口接收客户端 App 的 RPC 请求。MOSN 会开启 2 个协程,分别死循环去对 TCP 进行读和写处理。MOSN 会通过读协程获取到请求字节流,进入MOSN的协议层处理。

  2. MOSN 会通过 streamconn 实现类中循环解码,直到解析到完整的请求报文。一旦解析到请求报文,会创建和请求 frame 关联的 xstream

    这里的 xtream 用来保持和客户端 App 的 TCP 关联,后续用来用于响应 response。

  3. MOSN 需要将请求转发到服务集群的某一台机器,会到达 proxy 层创建 downstream。

    此步骤实现目的如下:

    • 执行 filter 请求/响应链。

    • 执行路由匹配。

    • 执行负载均衡。

  4. 在选择服务集群的某一台后,MOSN 会首先初始化选中 IP 对应 host 的连接池。

    此时 MOSN 的角色变成了中间人的角色。一方面需要承担客户端 App 的服务端,另一方面需要承担远程服务方的客户端。

    upstreamrequest 对象起到关键作用:

    • 保持着对客户端 App 的 TCP 引用。

    • 保持着对转发服务端 TCP 引用,转发客户端 App 请求以及响应服务端 response 时的通知。

  5. 在 upstream 的 appendHeaders + appendData 阶段,会用第 4 步骤中选择的 host 创建 sender xstream。

    这个 xstream 是客户端的流对象,主要有 2 个目的:

    • 充当 Client 角色,初始化客户端请求信息,将待转发的请求创建对应的 stream 绑定关系。

    • 在真正转发前,需要替换请求 ID 信息,用来解决连接 IO 复用导致请求互相覆盖的问题。

      说明

      出现请求相互覆盖问题的原因:客户端 App 有多个 TCP 连接,MOSN 转发到服务端只有 1 条 TCP 连接。如果客户端 2 个 TCP 连接同时有个 id=1 的request,MOSN 会通过同一条 TCP 转发给服务端,因此响应回来时,MOSN 没办法区分 id=1 的 response 属于哪个客户端 App 的 TCP 连接。

      这里的解决办法是 MOSN 转发到服务端的 1 条 TCP 连接,会重新修改请求的 ID 成全局,就不会混淆请求和响应关联关系了。

  6. 因为 MOSN 在转发之前修改了请求 ID,因此会重新 encode 请求。

    一般优化手段不会 encode 完整报文,只会修改协议头的个别几个字节。

  7. 一旦客户端 xstream 准备转发就绪(endOfStream),就会通过第 4 步骤中选择下游 host 直接发送。

    此时请求的携程会被阻塞。

  8. MOSN 转发给服务端 host 时,会新建 TCP 连接。此时,每个 TCP 连接也会有 2 个携程去处理读写。

    MOSN 客户端 xstream 的会通过读 IO,收到响应 byte 字节流,并且交付上层 protocol 去解码。

  9. 一旦完整解码成 response 对象,会通知 upstream request 对象。

  10. upstream request 持有客户端请求的 downstream,唤醒 downstream 阻塞的协程。

  11. 对应步骤 2 中 MOSN 作为服务方 xstream 被唤醒,会将收到的响应 response,重新替换回正确的 reqest id,并能且去调用协议层重新 encode 成字节流。

  12. xstream 中持有客户端 App 请求时的 TCP 连接,直接将响应写会客户端,并且销毁 MOSN 中所有请求相关的资源。