Service Mesh架构的持续演进 单体模块化 SOA 微服务 Service Mesh
架构不止-严选Service Mesh架构的持续演进
同严选的业务一样,在下层承载它的IT系统架构一样要生存、呼吸、增长和发展,否则过时的、僵化的IT系统架构会使我们的组织和业务陷入停顿,无法面对新的机遇和挑战。这些年业界的服务端架构理念一直在持续演进,从单体模块化架构,到SOA,再到微服务,最后到Service Mesh。严选服务端架构的演化正是它的一个缩影,在某些方面我们甚至还领先于业界的发展。
架构成熟度
- 单体模块化架构强调业务逻辑按模块划分,高内聚低耦合。模块间通信通过同进程内的方法调用进行。
- 面向服务的架构(SOA)强调业务逻辑在应用粒度的复用,收口和归一散落的业务逻辑,可以理解为是业务逻辑的水平拆分。服务间通信通过企业服务总线进行,总线上会耦合少量业务逻辑。
- 微服务架构强调业务逻辑在应用粒度的解耦,可以理解为高内聚低耦合业务逻辑的垂直拆分。服务间通信通过RPC进行。
- Service Mesh强调业务逻辑与服务治理逻辑的分层及解耦,这是另外一种层面的分层和解耦,在业务逻辑和基础实施逻辑间划分出清晰的边界。Service Mesh架构下,服务间通信通过网格进行代理。所有这些架构模式无一不在强调解耦和复用,而Service Mesh是所有架构模式中解耦和复用最彻底的,它不仅仅强调业务逻辑的解耦和复用,更强调基础设施的解耦和复用。
什么是Service Mesh
先来看Service Mesh的定义,这个定义是Service Mesh的先驱公司Linkerd的CEO William提出来的。
“Service Mesh是一个基础设施层,用于处理服务间通讯。云原生应用有着复杂的服务拓扑,服务网格负责在这些拓扑中实现请求的可靠传递。在实践中,服务网格通常实现为一组轻量级网络代理,它们与应用程序部署在一起,而对应用程序透明”
这个是Service Mesh比较早期的定义,现在Service Mesh涵盖的范围更大更广。在微服务体系里面,除了服务本身之外,其它的服务相关的可管理可治理的的部分都可以理解为是Service Mesh的范畴。
所以Service Mesh归根结底是一个服务治理平台,它基本上包含了服务治理的所有方面。这些通过Spring Cloud这种全家桶的方式也能实现,但是与业务逻辑耦合在一起,部署、运维都耦合了微服务本身的操作。比如一个RPC框架的bugfix会引发所有微服务旷日长久的升级发布,同时带来业务开发人员开发、测试、回归、发布的巨大重复工作量。Service Mesh通过将与业务逻辑无关的服务治理逻辑下沉,让业务开发人员与基础技术开发人员关注点分离,各司其职,大大提升了研发效能。业务开发人员更关注的是对业务的理解、建模,他们的核心价值体现在业务实现上。Spring Cloud/Service Mesh之类的服务治理平台对于他们来说只是工具和手段,而不是终极目标。在这些工具的学习和使用上耗费大量时间和精力成本对他们来说得不偿失。基础技术开发也能专注于自己的技术领域,不需要为了推动技术的升级换代而去理解、学习业务,不需要耗费大量时间精力去协调和推动业务的变更,不需要共担业务线上变更的风险和压力。
第一代——基于Consul+Nginx的严选版Service Mesh
严选/邮件版Service Mesh(也即Consul+Nginx,后简称cNginx)诞生之时,Service Mesh的概念还没有提出,大家也没想到当初做的那些事情竟然让他们成为Service Mesh的先行者。当初的想法很简单:为跨语言业务应用提供无侵入性的基于Consul的服务路由功能。并利用 Nginx 的原生特性,在高性能的前提下提供负载均衡、集群容错等机制。当时所做的主要工作是对consul与nginx的扩展开发,把这2个组件的能力融合在一起,以解决我们遇到的问题。
严选版Service Mesh整体架构
- 数据面以consul client+cNginx 组成我们的sidecar,这里的sidecar模式是单向的client sidecar模式,当时我们关注的问题单sidecar的模式已经完全能解决。在数据面实现的服务治理能力主要以nginx为基础。
- 负载均衡
- timeout治理
- 重试
- FailOver
- 控制面控制面也即我们的consul admin管理平台,有3大模块,分别实现各自职责边界内的服务治理能力。
- 流量调度对流量进行调度、路由、流量权重、泳道隔离等操作。
- 服务注册/发现对服务实例进行上线、下线、剔除、健康检查等操作
- 限速&熔断对服务调出在调用方进行速率限制或直接熔断。
架构收益
通过融合Consul+Nginx的功能,我们建设了简单服务治理能力,落地了简版的Servcie Mesh。cNginx对业务应用透明,由基础技术团队统一开发、部署和运维,其实现的服务治理功能不需要各个业务方重复去建设或从第三方引入,可以将更多时间专注于自己的业务逻辑。同时在跨语言的多个应用之间,我们建设了统一的通信层,保证了通信策略的一致性落地。成本方面,我们也节省了框架性中间件(比如RPC框架)的研发和投入,降低了中间件与业务代码之间额外的耦合成本。
第二代——基于istio的Service Mesh
随着业务的快速发展,cNginx实现的简版服务治理能力已经不能满足我们日益增长的需求。而云基础设施的成熟让云原生架构越来越具有普适性,严选也在基于轻舟落地我们的容器云战略,cNginx无法与k8s、docker等云基础设施有效融合,必须选择新的Service Mesh平台进行替换。毫无疑问,我们的最终的选择的是istio,当前Service Mesh的事实标准。
istio整体架构
stio在架构上同样分为数据面和控制面两大块。
- 数据面数据面控制服务所有进出流量,并植入服务治理逻辑。数据面同时负责控制面制定的策略的执行,并上报遥感数据至控制面。istio数据面默认的sidecar为envoy,envoy是L4/L7的高性能网络代理组件。
- 控制面控制面由Pilot、Mixer、Citadel、Galley四部分组成。
- Pilot提供服务发现、流量动态路由和服务间的弹性能力(超时、重试、速率限制、熔断等)。
- Mixer承担ACL、策略执行、黑白名单等职责,并收集服务遥感数据。
- Citadel提供安全证书下发和管理的能力。
- GalleyGalley提供抽象的、统一的配置校验能力。
一些重要决策
1.Client Sidecar模式
istio本身提供了3种sidecar的模式:Client Sidecar、Server Sidecar、Both Sidecar,经过权衡,我们最终决定暂时使用Client Sidecar的模式,只在服务调用方启用sidecar,原因如下所述。
- 模式上的继承性严选第一代Service Mesh的实现cNginx也是 Client Sidecar的模式,而第二代istio本来就是一个很新很前沿的的东西,为了降低大家理解上和使用上的复杂性,同时让业务进行无缝对接,我们对第二代Sidecar模式的变更暂时采取了保守的态度。
- 性能考虑从我们的压测结果来看,istio client sidecar 模式与cnginx相比略微差一点,而both sidecar的模式由于网络上多了一跳性能也有更多的折损,为了不让业务方在响应性、吞吐量等感知上出现过多的变化,我们暂时选择了client sidecar模式。
- 治理能力的差别Client模式与Both模式在治理能力上的差异部分,我们现有的基础设施都能够补足。比如服务可观察性,我们有完善的APM平台和日志平台。所以在治理能力上我们并不Care Server端是否启用了sidecar。
2.按需使用
istio就像一把瑞士军刀,它提供的功能非常非常多,初次使用它你可能会陷入迷茫。严选对istio的使用一直秉承按需的原则,我们初期只要求使用和cnginx对等功能,后面再逐步覆盖其它功能。对于一些目前版本istio的实现上有性能问题的功能,我们是坚决弃用的。比如Mixer的策略执行功能,因为每一次调用envoy都会同步调用Mixer进行一次策略检查,导致性能下降的非常迅速。关于这一点,社区也已经意识到并着手进行优化了,优化完成后我们会考虑使用。作为Mixer的策略执行的替代品,istio的rbac也是可以满足一部分功能的,比如服务白名单我们就是通过rbac来实现的,这样就避免了Mixer的性能陷阱。
3.与k8s融合
Service Mesh本身是平台独立的,但与k8s融合有非常多的优点,已经逐步成为了业界主流的标准(也即云原生架构),严选也采用了这种方式。
- sidecar自动注入,自动接管流量
- 一致的服务发现,统一基于K8S数据做服务发现
- 治理规则基于K8S CRD,无需专门管理服务
- 服务发现无需主动注册,声明为k8s service即可自动注入
过渡期架构方案
过渡期会存在cNginx(云外)与istio(云内)两种类型的Service Mesh共存的情况,为了让业务无感知,我们设计了过渡期的架构方案
- 对于云内服务来说,如果服务提供方没有在云内部署,则自动兜底路由到云外服务。
- 对于云外服务来说,云内服务提供者统一抽象成云外服务的一个逻辑服务实例,往云内的导流通过cNginx控制这个逻辑服务实例流量权重即可。
性能陷阱Service Mesh最受人误解而诟病的是它的性能问题,很多人认为调用路径上网络多了一跳/两跳就觉得Mesh性能会很差。从我们的实践和压测来看,只要我们做好抉择和裁剪,Mesh的性能问题并没有那么恐怖。
- 1600rps+40个并发(主机配置均为8C16G)
从压测数据来看,在40个并发基础上,rps在1600(注:单机1600rps对于严选的业务来说,容量的冗余已经非常充分了)时,istio(client模式)的RT overhead是0.6ms左右,cnginx的RT overhead在0.4ms左右。istio和cnginx的性能差别非常小,基本上可以等价。而且Spring Cloud/dubbo这种框架本身也会引入资源开销、性能开销,所以替换成Service Mesh只是对性能开销进行了转移支付,性能影响相较而言就更小了。严选使用的istio是杭研版的istio,当前杭研同学正在对istio的性能做更深一步的优化。目前性能优化后初步测试结论如下。
- 方案1:采用eBPF/xDP(sockops),优化路径为SVC <-> Envoy,延迟性能提升10-20%。Envoy部署方式per-pod,跟社区方向一致,也是目前严选采用的部署方案。
- 方案2:采用DPDK+Fstack用户态协议栈,优化路径为Envoy <-> Envoy,延迟性能提升0.8-1倍。Envoy部署方式为per-node,功能和运维层面的限制还在评估当中。
当然性能问题依然是个很核心的问题,所以我们会建设我们的常态化压测机制,对任何变更都进行压测回归。
总结从cnginx到istio,我们的服务治理能力和治理体系化实现了与时俱进和现代化。架构落地的收益最终都是通过研发效能来体现,通过Service Mesh架构持续实践和落地,我们解耦了业务逻辑和基础设施逻辑,进一步解放和发展了生产力,驱动了业务更好更快的发展。
作者简介
王育松,2017年加入网易,负责严选基础技术中间件体系的建设以及严选服务端架构设计,历经2年时间从零到有建设了严选敏捷中间件体系。曾就职于支付宝、用友公司,负责了支付宝三大收单平台之一的账单平台的去O、分库分表、FO以及异地多活架构改造,主导了蚂蚁金服第一个基于OceanBase的异地无损容灾系统的建设。