2021值得考虑的一类新型微服务架构:ServiceMesh
本期与大家共同探讨微服务当下最新的框架 —— ServiceMesh 。
微服务框架
微服务,简单而言,就是将原有的一个整体的应用,拆成多个细粒度的小应用,同时具备分布式的特点。化整为零后当然会带来一系列的问题,就好比一个开小卖铺的后来开成了连锁店一样,一定会带来很多跟进货、卖货没关系的问题。那么微服务带来的这一系列问题,就需要通过微服务框架来解决。
通常狭义的“微服务”仅指的是 SpringCloud、Dubbo 这一类的传统微服务框架,也是国内使用较多的开源微服务框架。另外一类新型的微服务框架就是服务网格(ServiceMesh),也在近两年逐渐变得热门,比如 Linkerd、Consul、Istio 等都属于服务网格的框架。
ServiceMesh的特点
做微服务首要解决的问题是通信问题:服务寻址、访问控制、流量限流、熔断降级等等,都是通信上的问题,而微服务、服务网格的框架就是用来解决这类问题的。但是在解决的方式上,传统的微服务框架、新型的服务网格框架则有所不同,而且是大有不同。两者之间的区别我们可以看一下这个图:
传统微服务框架以 SpringCloud 为例,开发的时候需要引入 SpringCloud 相关的所有依赖,也就是将通信部分包到了引入的依赖(SDK)里,当然这也考验开发人员的能力,需要开发人员熟悉 SpringCloud 框架才能用,并且目前只支持 Java 语言。服务网格类的框架,说来也简单,就是把上面的 SDK 拿出来,单独运行,只要能实现该 SDK 的功能,目的也就达到了,而抽出来单独运行的 SDK 称之为 Sidecar,在服务网格的管理中属于数据面的管理。
当然 Sidecar 也有一系列需要解决的问题,比如 Sidecar 要全权代理其通信,即流量劫持;服务发现、服务健康检测要有相应的机制;策略下发和统一管理也都需要考虑。在服务网格的管理中属于控制面的管理。
与传统微服务框架相比,服务网格确实是有很多优势。服务的业务与通信拆成两个部分,业务开发人员不用关心微服务框架、微服务治理的事情,开发的时候也不会涉及框架的学习,甚至不用关心使用哪种开发语言;运维管理组或者架构组,也不用担心自己在通信架构上的优化,很难升级到运行中的系统上。用专业的术语来说就是将业务与治理解耦,微服务治理能力下沉至运维层,降低开发难度,在架构上更容易实现层次化、规范化、体系化。
性能是不是服务网络最大的挑战?
我们知道当单体应用拆分成微服务以后,本来进程内的调用却变成了网络间的调用,性能自然是不如从前。那么同样的道理,现在是将每个微服务又拆成了两个运行的程序,同样需要通过一个网络的调用,这岂不是又加重了性能的问题?如果我们把每一次服务间的调用,都比做是搭乘公交车,原本 A 服务调用 B 服务,就好似搭乘了一趟公交,那么带上 Sidecar 的服务调用就是 A 服务->Sidecar->Sidecar->B 服务,这样好比是中间换乘了两次公交,这样算来延迟可增加不少,几近于原来的三倍?
其实仔细分析一下会发现,从处理时间上来说,ServiceMesh 其实并没有增加通信性能的消耗。举个例子,在没有引入 ServiceMesh 时,A 服务调用 B 服务,消耗的时间主要是:
● A发出信息之前,首先会经过自身的框架(SDK)做处理,因为传统的微服务框架基本上都是客户端负载均衡,所以在这里会过一些负载均衡、算法选址、熔断降级等治理功能,耗时在1ms左右;
● A->B的网络通信时间,网络畅通的情况下,不超过0.1ms;
● B接收到数据后,也首先是框架(SDK)处理,比如访问权限、黑白名单等,姑且叫做治理功能处理,大概也是会消耗1ms;
● 治理相关处理完以后,就是业务处理了,首先是协议编解码,然后是业务代码的处理,一个不是很复杂的业务服务处理,应该是在10ms左右。
这样算下来,A->B的微服务调用,从 A 出口算起到 B 处理完成,粗略的估计是12.1ms,我们再来看A->Sidecar->Sidecar-B的业务处理,大概需要花费的时间:
● A服务发出通信信息,到A服务的 Sidecar 上,这个网络传输的时间一定在0.1ms以内,通常都是主机内的本地调用,因此也不占据网络资源;
● A服务的 Sidecar 接收信息后,会做类似于之前的 SDK 一样的处理,也就是熔断、限流、访问控制就在这里做好了,处理时间也类似大概1ms。注意服务网格的访问控制、黑白名单也是在调用端处理的;
● A服务的Sidecar将信息传输到B服务 Sidecar ,与传统微服务的A到B的传输相同,传输时间也相同,姑且算0.1ms;
● 信息到B服务的 Sidecar 以后,如果不是加密传输,那么B服务的 Sidecar 不用做任何处理,因为治理相关的功能已经全部放在了调用端,所以B服务的 Sidecar 直接透传,几乎不消耗时间;
● B服务的 Sidecar 将信息传送到B服务,网络也按照0.1ms算;
● 最后B服务的协议编解码、业务处理,也是将近10ms。
统计一下服务网格平均一次调用的消耗大概是11.3ms。延迟的消耗不增反减,这也是前期我们经过很多次的压测以后发现的一个规律。
意料之外,情理之中
经过上面的性能分析,结果大出我们的意料之外,本以为将近三倍的延时,却发现几乎没有太大变化,这是我们有意抬高 ServiceMesh ,还是其本身架构就是向着性能优化的方向走的呢?
其实了解 Sidecar 的处理机制以后,也就能明白这个意料之外的事情其实并不奇怪。
首先 Sidecar 不是一个服务,不处理报文体中的详细业务内容,只做转发。拿到报文头中的目标信息以后,原报文体不做任何处理,其次在转发的时候执行负载策略、熔断限流、路由策略等,然后就是通信信息的记录,以便于监控、日志等管理。为了实现 API 粒度的管理,比如 API 粒度的访问控制、熔断限流,Sidecar 还需要有 URL 的路由策略功能,通过不同的 URL 策略,实现细粒度的 API 或 API 组的治理,这也就是 Sidecar 整体的处理流程。
说到这里,大家有没有发现 Sidecar 跟一个 API 网关的功能、作用好像差不太多?实际上 Sidecar 就是通过 API 网关来实现的,为每一个微服务实例配置一个 API 网关实例,全权接管其流量和通信,以达到透明化的治理。所以在性能方面,CPU、内存的消耗是必然,而通信延迟上却并不足为虑。
总结
服务网格从 2010 年就被提出,到 2017、2018 年的时候就普遍受到了技术人员的关注,2020 年也被叫做是服务网格落地的元年。了解了服务网格的原理,也就普遍能被市场所接受了,毕竟核心的技术也就在于 API 网关上,而 API 网关又是一个已经完全成熟的一个技术。所以如果现在做微服务化的转型,ServiceMesh 也是值得考虑的一种技术规范。
在接下来的文章中,我们会将 API 网关、Mesh、Sidecar 做一个统一的介绍和对比,敬请期待~