Service Mesh Webinar 是由 ServiceMesher 社区和 CNCF 联合发起的线上直播活动,活动将不按期举行,为你们带来 Service Mesh 领域的知识和实践分享。
本文根据5月28日晚 Service Mesh Webinar#1 多点生活平台架构组研发工程师陈鹏,线上主题分享《多点生活在 Service Mesh 上的实践 -- Istio + Mosn 在 Dubbo 场景下的探索之路》整理,文末包含本次分享的视频回顾连接以及 PPT 下载地址。html
随着多点生活的业务发展,传统微服务架构的面临升级困难的问题。在云原生的环境下,Service Mesh 能给咱们带来什么好处。如何使用社区解决方案兼容现有业务场景,落地成符合本身的 Service Mesh 成为一个难点。git
今天主要给你们分享一下 Service Mesh 的一些技术点以及多点生活在 Service Mesh 落地过程当中适配 Dubbo 的一些探索。github
首先咱们从三个方面入手:web
说到为何须要改造,应该先说一下 Service Mesh 和传统微服务架构的一些特色。json
微服务通常有这些模块:数组
这些模块在传统的微服务架构中有的是和 SDK 结合在一块儿,有的是一个独立的中间件。安全
特色:网络
正是因为技术多样性,个人微服务系统可使用不一样的语言进行开发,好比我一个商城系统,订单系统使用 Java 开发,库存系统使用 Go 开发,支付系统使用 Python 开发,微服务之间经过轻量级通讯机制协做,好比:HTTP/GRPC 等。好比目前多点使用的 Dubbo(服务治理框架),随着多点生活的业务发展,目前遇到最棘手的问题就是中间件在升级过程当中,推动很慢,须要业务方进行配合,接下来咱们看看 Service Mesh。架构
优势:负载均衡
缺点:
看了 Service Mesh 的优缺点,若是咱们 Mesh 化了以后就能够解决咱们目前的痛点,升级中间件只须要从新发布一下 Sidecar 就行了,不一样语言开发的微服务系统能够采用一样的服务治理逻辑,业务方就能够尝试更多的技术。
在谈 Dubbo 场景下的改造以前咱们先介绍一下 Istio 相关的技术点,而后结合 Dubbo 场景应该如何进行适配
MCP(Mesh Configuration Protocol)提供了一套用于订阅(Watch)、推送(Push)的 API,分为 Source 和 Sink 两个角色。
MCP 的订阅、推送流程图:
为了和实际状况结合,咱们就以 MCPServer 做为 Source,Pilot 做为 Sink 来介绍订阅、推送流程,其中 MCP 通讯过程当中所传输的「资源」就是 Istio 定义的 CRD 资源,如:VirtualService、DestinationRules 等。
configSources
的一个数组配置(Istio 1.5 以后没有这个配置,须要本身添加)、存放的是 MCP Server 的地址;这样的订阅、推送流程就保证了 MCPServer 和 Pilot 资源的一致。MCPServer 只能经过 MCP 协议告诉 Pilot 资源发生变化了么?固然不是,MCPServer 可使用建立 CR 的方式,Pilot 经过 Kubernetes 的 Informer 机制也能感知到资源发生变化了,只是经过 MCP 传输的资源在 Kubernetes 里面看不到,只是存在于 Pilot 的内存里面,固然也能够经过 Pilot 提供的 HTTP debug 接口(istiod_ip:8080/debug/configz)来查。
https://github.com/champly/mcpserver 提供了一个 MCPServer 的一个 demo,若是须要更加细致的了解 MCP 原理能够看一看。
更多 debug 接口能够查看: https://github.com/istio/istio/blob/5b926ddd5f0411aa50fa25c0a6f54178b758cec5/pilot/pkg/proxy/envoy/v2/debug.go#L103
Pilot 负责网格中的流量管理以及控制面和数据面以前的配置下发,在 Istio 1.5 以后合并了 Galley、Citadel、Sidecar-Inject 和 Pilot 成为 Istiod。咱们这里说的是以前 Pilot 的功能,源码里面 pilot-discovery 的内容。
Sidecar 经过动态获取服务信息、对服务的发现 API 被称为 xDS。
Pilot 资源类型发生变化须要下发的 xDS 资源对照:
资源名称 | CDS | EDS | LDS | RDS |
---|---|---|---|---|
Virtualservices | ✔ | ✔ | ||
Gateways | ||||
Serviceentries | ✔ | ✔ | ✔ | ✔ |
Destinationrules | ✔ | ✔ | ✔ | |
Envoyfilters | ✔ | ✔ | ✔ | ✔ |
Sidecars | ✔ | ✔ | ✔ | ✔ |
ConfigClientQuotaspecs | ✔ | ✔ | ||
ConfigClientQuotaspecbindings | ✔ | ✔ | ||
Authorizationpolicies | ✔ | |||
Requestauthentications | ✔ | |||
Peerauthentications | ✔ | ✔ | ✔ | |
Other | ✔ | ✔ | ✔ | ✔ |
以上内容是根据 源码 整理的
MOSN 是一款使用 Go 语言开发的网络代理软件,做为云原生的网络数据平面,旨在为服务提供多协议、模块化、智能化、安全的代理能力。MOSN 是 Modular Open Smart Network 的简称。MOSN 能够与任何支持 xDS API 的 Service Mesh 集成,亦能够做为独立的4、七层负载均衡,API Gateway,云原生 Ingress 等使用。
MOSN:https://github.com/mosn/mosn
配置文件:
其中 address
就是 MOSN 监听的地址。
filter_chains 在 MOSN 里面的 network chains
,实现的还有:
和 network chains
同级的还有 listener chains
、stream chains
, 其中listener chains
目前只有 original_dst
实现。stream chains
能够对请求中的
进行 BeforeRoute
AfterRoute
这些关键步骤进行修改请求信息。
全部的 filter
都只有两种返回结果:
filter
那就执行后续 filter
;filter
就再也不继续执行了;看图中的配置信息 config
的内容, downstream_protocol
和 upstream_protocol
这里若是配置不一致,就须要协议转换。好比 HTTP1
转换为 HTTP2
,MOSN 就会先把 HTTP1
转换为 common
的中间协议,而后再把 common
转换为 HTTP2
,这样就实现了协议之间的转换。若是须要本身实现其余协议转换,那么只须要编写转换 common
的内容和 common
转换为当前协议的内容便可实现协议之间的互转。
咱们再来看 filters
里面的 proxy
,这个就是一个会通过路由的代理,配置信息里面配置了router_config_name
,就是要路由的router
名字。
根据 listener
里面的 proxy
的配置信息里面的 router_config_name
会找到一个 router
,如上图所示。而后就会根据请求里面的 domains
去匹配 virtual_hosts
, 这里的 domains
里面在 HTTP
里面就会是 host
,当在 Dubbo 协议里面咱们能够把 service
(有些地方叫作 interface、target,咱们这里统一叫 service) 放到 x-mosn-host
这个 MOSN 的 Header
里面,MOSN 就能够根据这个去匹配 domains
。
而后匹配到一个 virtual_hosts
以后,就会获得对应的 routers
,这里又会根据 match
里面的匹配规则进行匹配,HTTP
协议里面能够根据 path
、queryparam
、header
等信息进行匹配,具体匹配规则经过 VirtualService 下发,若是是 Dubbo 协议,那么能够套用 HTTPRoute
规则,而后把 Dubbo 的 attachment
解析出来看成 header
去用,目前 MOSN 没有解析 attachment
,咱们本身实现了一个。
匹配到了以后会获得一个 route
,图中所示只有一个 cluster_name
,若是是有多个 subset
(DestinationRule 定义),那么就会有 weighted_cluster
,里面会有 cluster_name
和 weight
构成的对象的数组,例如:
"route":{ "weighted_clusters":[ { "cluster":{ "name":"outbound|20882|green|mosn.io.dubbo.DemoService.workload", "weight":20 } }, { "cluster":{ "name":"outbound|20882|blue|mosn.io.dubbo.DemoService.workload", "weight":80 } } ], "timeout":"0s", "retry_policy":{ "retry_on":true, "retry_timeout":"3s", "num_retries":2 } }
其中 weight
之和必须为 100(Istio 定义的),必须是非负数的整数。
下面有一些 timeout
、retry_policy
服务策略。
匹配上了以后会获得一个cluster_name
,而后咱们再看 cluster
在 routers
里面匹配出来的 cluster_name
做为 key
在 cluster
里面会找到这么一个对象。
其中 lb_type
就是节点的负载均衡策略,目前 MOSN 支持:
hosts
里面的 address
里面也能够配置权重,这个权重必须是大于 0 或小于 129 的整数。能够经过 Istio 1.6 里面的 WorkloadEntry
来配置权重。而后根据负载均衡策略拿到 host
以后直接请求到对应的节点。
这就完成了流量的转发。接下来咱们看看 Dubbo 场景下应该如何改造。
全部的改造方案里面都是要把 SDK 轻量化,关于服务治理的逻辑下沉到 Sidecar,咱们在探索的过程当中有三种方案。
这个方案是 Istio+Envoy 的方案,是参考的华为云的方案: https://support.huaweicloud.com/bestpractice-istio/istio_bestpractice_3005.html
这种方案若是须要解析更多的 Dubbo 内容,能够经过 WASM 扩展。
这种方案的话就不须要 Istio。
这种方案就是咱们如今采用的方案,包括:
咱们有一个理念就是若是能经过标准的 CRD 最好,若是描述不了的话咱们就经过 EnvoyFilter 进行修改。这里特别说一下,咱们一开始也有一个误区就是 EnvoyFilter 是做用于 Envoy,其实不是的,是对生成好的 xDS 资源进行 ADD, MERGE 等操做,目前只能够修改 LDS、RDS、CDS,这个修改也是有必定局限性的。若是 EnvoyFilter 修改不了某些特定的场景(好比 Istio 1.6 以前的 ServiceEntry 里面的 Endpoint 不能单独为每一个实例指定不一样的端口),那么咱们只能修改 pilot-discovery 的代码,xDS 是不会做任何修改的。按照这个理念,咱们开始探索如何改造。
首先有三个端口须要说明一下:
步骤:
这个只是经过静态配置实现的,若是 provider 这些信息如何经过 Pilot 下发呢?
MOSN 自己支持 xDS API,配置信息能够经过 xDS 下发,而不是静态配置。咱们有一个对接配置中心,注册中心的程序咱们叫 Adapter,这个主要获取注册中心的服务信息,而后根据配置中心的服务治理策略(好比流程比例,还有一些咱们内部的一些单元的信息)构建出 Istio 支持的 CR,而后建立 CR,Pilot 本身感知 CR 变化 或者 经过 MCP 把这些信息直接发送给 Pilot,触发 Pilot 的资源变化,而后 Pilot 根据资源的变化去下发一些 xDS 资源,Sidecar 收到资源变化后,就能够动态调整路由策略,从而达到服务治理的目的。
最终架构图如图所示:
注册(灰色部分):
配置下发(蓝色部分):
服务请求(黄色部分):
以上就完成了服务注册、发现、治理的全部逻辑。
Istio 1.6 以后能够经过 WorkloadEntry + ServiceEntry 这两种 CRD 资源来描述集群外的服务,当实例上线或者下线的时候就会直接触发 EDS 增量下发。
首先要说明一下:
具体操做能够按照 mosn-tutorial,里面的istio-mosn-adapt-dubbo
。即便你没有 Kubernetes 环境也能够尝试的,后期这个会移植到 MOSN 官网,敬请期待。
mosn-tutorial:https://github.com/mosn/mosn-tutorial
以上就是本期分享的所有内容,感谢你们的收看。
陈鹏,多点生活平台架构组研发工程师,开源项目与云原生爱好者。有多年的网上商城、支付系统相关开发经验,2019年至今从事云原生和 Service Mesh 相关开发工做。
PPT 下载:https://github.com/servicemesher/meetup-slides/tree/master/2020/05/webinar
视频回顾:https://www.bilibili.com/video/BV15k4y1r7n8