乐趣区

关于sofa:MOSN-多协议扩展开发实践

Service Mesh 是当今云原生的要害局部,蚂蚁曾经在生产环境实现了大规模的落地,然而业界整体 Service Mesh 革新水平还不高。其中安稳的进行 Mesh 化革新是能够对已上线的业务进行 Mesh 化革新的前提,在安稳革新过程中,协定的反对又是最根底的局部。MOSN 提供的多协定扩大开发框架旨在升高应用公有协定的场景进行 Mesh 化革新的老本,帮忙业务疾速落地。

MOSN 是蚂蚁自研的一款高性能网络代理,次要用于 Service Mesh 的数据面 Sidecar。Service Mesh,是近几年来云原生方向比拟热门的话题,其宗旨就是构建一个基础设施层,用来负责服务之间的通信。次要就是有一个和服务利用独特部署的 Sidecar 来实现各种中间件的根底能力,实现基础设施的标准化、和业务逻辑解耦,做到业务无感知的根底能力疾速演进。目前国内很多公司都开始拥抱 Service Mesh,和蚂蚁单干的一些企业,如中信银行、江西农信等也基于 MOSN 实现了 Mesh 化的革新。

Service Mesh 架构的目标就是为了升高基础设施革新降级对业务造成的影响,然而如何平滑的从传统微服务架构转向 Service Mesh 架构也是一个十分有挑战的工作,这里波及的细节很多,然而无论如何有一个最根底的问题就是咱们在进行灰度 Mesh 化革新的时候,曾经 Mesh 化的节点须要能和没有 Mesh 化的节点维持失常通信。而不同的公司抉择的通信协议都有所不同,这就间接导致在技术选型的时候,抉择的 Sidecar 须要可能反对所应用的协定。一些受到广泛应用的协定可能还会被陆续的反对,而有的协定可能还是公司本人定制的,因而不可避免的是须要基于 Sidecar 的扩大能力,进行二次开发以反对公有的协定。

多协定扩大框架

谈到 Service Mesh 的 Sidecar,就不得不提到 Envoy,这是一款被广泛应用的 Service Mesh Sidecar 代理。Envoy 的扩大框架反对开发者进行二次开发扩大,其中 Envoy 目前反对的不少协定就是基于其扩大框架开发实现的。在 Envoy 的扩大框架下,要扩大一个协定能够参考 Envoy 中 HTTP 协定解决的流程,包含 4 层 Filter 实现编解码局部与 Connection Manager 局部,在 Connection Manager 的根底上再实现 7 层的 Filter 用于反对额定的业务扩大、路由的能力、和 Upstream 的连接池能力。能够看到一个协定解决的流程简直是贯通了各种模块,实现一个协定扩大老本还是比拟高的。

再来看一下 MOSN 的框架。MOSN 在一次协定解决上能够划分为四个档次,除开根本的从网络 IO 中获取数据的网络层以外,还能够划分为 protocol 层、stream 层与 proxy 层。其中 protocol 层负责协定解析相干编解码的工作,负责将数据流解析成 MOSN 能够了解的协定帧,或者将协定帧编码成二进制流;stream 层负责的内容就比拟多了,包含解决不同的申请类型,初始化申请的上下文,关联事件,响应与申请之间的关联,还有 upstream 连接池相干的解决等,不同的协定解决的细节也会有所不同;proxy 层是一个协定无关的代理转发层,负责申请的路由与负责平衡等能力,同时也具备七层的扩大能力用于不同业务实现的扩大。依据这个架构,能够看到协定解决的外围就在于 protocol 层和 stream 层,相比于 Envoy 的设计来说,路由、七层扩大等局部是具备多协定复用的能力的。然而同时也能够看到 stream 层波及的细节比拟多,实现起来难度也是比拟大的,为此 MOSN 在此基础上又提出了一个多协定扩大的框架,用于简化协定的实现。

MOSN 的多协定框架次要就是针对 stream 层的复用扩大能力,在 MOSN 的协定解决分层设计中,network 层和 proxy 层在设计上就是协定无关可复用的,如果能做到 stream 层也进行复用,那么协定实现就只须要关注 protocol 层的编解码自身,实现难度就会大大降低了。那么 stream 层是不是具备可复用的能力的呢,咱们认为对于大部分协定,尤其是 RPC 协定来说是能够的。首先咱们对协定进行一个形象,定义成 XProtocol 接口,示意任意的协定。每个协定实现都是实现一个 XProtocol 接口,它包含根底的编解码接口、一些非凡申请响应的结构接口(如心跳、异样)、还有协定的模型(如相似 HTTP 的 pingpong 模型,常见的 RPC 多路复用模型等),以及协定匹配的接口。所有的 XProtocol 协定实现通过 XProtocol Engine 关联起来,除了通过配置指定应用哪种协定进行解决以外,对于实现了协定匹配接口的协定来说,能够基于申请特色进行自动识别。而后咱们对于 XProtocol 解析出的协定帧也进行对立的形象,包含多路复用相干的接口、协定类型的判断(是申请,还是响应,或者是相似 Goaway 一类的管制帧,申请又能够细分为心跳申请、无响应的 oneway 申请等)、反对对协定帧的数据进行批改(Header/Body 的批改)、还有对立的状态码治理映射等。

在 MOSN 的协定解决分层机制下,以及有了以 XProtocol 和 XFrame 的形象定义为外围的多协定扩大框架当前,咱们在 stream 层就能够齐全基于接口进行协定的解决,而不同的协定扩大实现者只须要专一于协定编解码自身,以及对编解码后的后果进行简略的接口适配,就能够实现在 MOSN 中的接入,由此取得 MOSN 中各种通用能力的反对,如限流扩大、路由引流等。比照 Envoy 中扩大协定实现局部能够看到是简化了不少的。当然 MOSN 这个多协定框架不能满足所有的协定状况,然而对于目前咱们看到的大部分 RPC 协定,在配合上 proxy 层中七层 stream filter 扩大的根底上,都是能够很好的满足的。

实际案例

上面以 MOSN 在社区合作伙伴中 Dubbo 协定落地的案例来具体的理解 MOSN 的多协定扩大。这里很多代码也是 MOSN 社区的同学奉献的。
在这个案例中,除了要求协定须要反对 Dubbo 以外,还心愿应用像限流等这些根底的扩大能力,同时须要蓝绿分组等路由的能力,抉择的管制面是 Istio,用于动静配置的下发。那这些需要在 MOSN 中是如何实现的呢?

首先是协定解析局部,这里采纳了基于开源的 dubbo-go 框架做协定实现,基于 dubbo-go 封装出了 MOSN 的 XProtocol 和 XFrame 模型;限流、xDS 等能力间接复用 MOSN 已有的实现,无需额定实现。然而这里有一个问题点就是 Istio 动静下发的路由配置是 HTTP 相干的,HTTP 的路由配置模型与 Dubbo 还是存在肯定差别的,而批改 Istio 的老本会比拟高,在这里就做了另外一层扩大。基于 MOSN 七层的 StreamFilters,在进行路由匹配之前对 Dubbo 协定进行定制化的解决,用来满足 HTTP 的路由格局。次要有两个点,一个是 HTTP 的 Host,应用 Dubbo 的 Service 对应到 Host,另外一个是 HTTP 的 Path,这部分就间接增加一个默认的 Path 进行通配;同时在这个扩大 Filter 中,还会获取机器的 Labels 增加到 Header 中,用于匹配路由的蓝绿分组性能。通过 MOSN Filter 扩大的配合,咱们在实现了规范的 Dubbo 协定反对的根底上,满足了应用 HTTP 路由配置形式满足 Dubbo 路由的性能。

插件化扩大

通过 MOSN 多协定框架的介绍,能够理解到当一个场景须要接入 MOSN 还不反对的自定义协定的时候,就须要进行扩大实现,而后和 MOSN 的框架代码一起进行编译,取得一个反对自定义协定的 MOSN。尽管曾经尽量简化了协定扩大实现的复杂度,然而仍然会存在一些问题,比方咱们商业版的代码中,不同的合作伙伴,对应不同的场景,应用的都是不同的协定,那么随着业务的倒退,协定这部分相干的代码就会越来越多,对应的开发保护代价也会变大。这都还好说,还有一些场景,客户协定一些细节出于某些需要可能并不想把相干的实现代码提交到 MOSN 的仓库中,而商业版代码不同于开源的,可能也不能间接将源代码交给客户,那这里编译就会遇到问题。为了解决这种矛盾,也为了更进一步让协定扩大变得简略,MOSN 还做了基于插件模式扩大协定的能力。

MOSN 插件扩大模式架构如图,MOSN 提供对立的插件扩大框架能力,MOSN 独立编译成二进制当前,利用插件机制动静加载不同的协定扩大插件,来取得对应的协定反对能力。这样协定扩大的实现也能够以插件的模式独立保护,甚至更进一步还可能反对非 Go 语言的扩大,比方基于 WASM 扩大能力对接其余语言实现的协定扩大。MOSN 的插件扩大能力有两种模式,一个是基于 Go Plugin 机制的扩大,一个是基于 WASM 的扩大。

首先来看一下 Go Plugin 的机制。这是 Go 语言提供的一种 SO 的加载能力,咱们能够把 Go 编写的代码编译成 SO,而后能够被其余 Go 文件加载。然而这个机制有一些比拟大的局限性,首先一点就是主程序与扩大插件编译的 Go 环境必须统一,包含 Go 的版本,GoPath 等环境变量;另外一点就是主程序与扩大插件依赖的库必须统一,这个是准确到 Hash 的,就是说不是两个库接口是兼容就能够,而是必须截然不同,这个限度就比拟大了。因为咱们预期是 MOSN 的代码和协定扩大的代码相互独立保护,协定扩大代码是须要依赖 MOSN 框架的,依照 Go Plugin 的机制每次 MOSN 框架的代码改变都会要求插件的代码也同步更新再从新编译插件,这个太麻烦了。

为此,咱们将 MOSN 框架进行了拆解,拆分出一些绝对稳固的接口和通用能力,作为 MOSN 主程序和协定扩大独特依赖的根底,如 XProtocol 和 XFrame 相干的 interface 定义独自定义到了 API 这个库中,而后在插件加载的时候,只须要将对应的一些接口注册到 MOSN 框架中就能够了。因为 API 定义和工具变动绝对较少,协定扩大插件依赖从 MOSN 框架变成 MOSN 的 API 定义,最大水平的缩小 MOSN 框架代码更新导致的插件代码必须更新的状况。而对于编译环境这个就好办了,咱们提供了一个对立的、用于编译的 docker 环境,只须要让 MOSN 和插件都基于同样的 docker 编译就能够。通过 Go Plugin 实现的插件扩大和间接将代码合并而后编译的后果是一样的,只是让协定扩大的代码能够独立进行保护。

再来看一下 WASM 的扩大机制。简略介绍一下 WASM,它是一个开发、高效、平安,并且领有社区统一标准的一种扩大能力,WASM 实践上是语言无关的一种能力,而且有一个被宽泛认可的网络代理场景的 ABI 标准,因为 MOSN 也反对了 WASM 的扩大能力,它也能用于 MOSN 的协定扩大。

MOSN 的 WASM 扩大具体介绍能够参考【WebAssembly 在 MOSN 中的实际 – 根底框架篇】

基于 WASM 的协定扩大形式,与之前提到的协定扩大有所区别。WASM 插件须要实现的是 proxy-wasm 的 ABI 规范,而不必关怀 MOSN 的多协定框架,也就是说这个 WASM 插件实践上是还能够被用于其余遵循 proxy-wasm ABI 标准的利用的。而在 MOSN 侧,则是实现了一个名为 WASM Protocol 的胶水层,这个胶水层实现了 MOSN 多协定框架的封装,而后通过 WASM ABI 与 WASM 插件进行交互。在 MOSN 多协定框架的视角下,看到的是一个由 WASM Protocol 封装的 XProtocol 实现,多协定框架也不了解 WASM ABI 交互的局部。和 GoPlugin 扩大不同,目前 MOSN 的 WASM 框架也还处于初级阶段,基于 WASM 的协定扩大也还只有 POC,而出于稳定性、性能等多方面因素的思考,还没有正式利用在生产环境中,还须要更多的优化和测试。

瞻望

最初谈一下 MOSN 在协定反对上后续的一些瞻望和打算,次要就是包含更多类型的协定反对,如存在流式、双工模式的 gRPC 协定、音讯类型的协定如卡夫卡、MQ 等,还有就是将 WASM 的协定扩大在生产环境落地可用。

本周举荐浏览

  • MOSN 子项目 Layotto:开启服务网格 + 利用运行时新篇章
  • 开发 Wasm 协定插件指南
  • Protocol Extension Base On Wasm——协定扩大篇
  • WebAssembly 在 MOSN 中的实际 – 根底框架篇

更多文章请扫码关注“金融级分布式架构”公众号

退出移动版