一、微服务架构的产生与问题
早期的很多系统都是单体服务的,就是把所有组件都塞在一个应用内,但是随着软件复杂性和并发用户数的急剧增加,单体应用无论是从开发效率和运维管理方面都已经不能适应时代的发展了。于是把各种服务独立出来,每个服务只关注自己的业务领域,与其它服务松耦合的微服务就应运而生了。
微服务架构具有以下几个优点:
1、单⼀职责:拆分后的单个微服务,通常只负责单个高内聚自闭环功能,因此很易于开发、理解和维护。
2、架构灵活:不同微服务应用之间在技术选型层面几乎是独立的,可以⾃由选择最适合的技术栈。
3、部署隔离:相比巨无霸单体应用,单个微服务应用的代码和产物体积大大减少,更容易持续集成和快速部署;同时,通过进程级别的隔离,也不再像单体应用一样只能同生共死,故障隔离效果显著提升。
4、独⽴扩展:单体应用时代,某个模块如果存在资源瓶颈(e.g. CPU/内存),只能跟随整个应用一起扩容,白白浪费很多资源。微服务化后,扩展的粒度细化到了微服务级别,可以更精确地按需独立扩展。
但是,微服务带来很多优点的时候,也出现了很多新的问题,最大的问题,就在于服务间通信的问题,具体来讲,就是如下几个问题:
- 如何找到服务的提供⽅?
- 如何保证远程调⽤的可靠性?
- 如何降低服务调⽤的延迟?
- 如何保证服务调⽤的安全性?
于是,为了解决这些问题,微服务技术特有的通信语义就出现了,如熔断策略、负载均衡、服务发现、认证和授权、quota限制、trace和监控等等,服务根据业务需求来实现一部分所需的通信语义。
但是,这样做的问题也非常明显,那就是,在这个过程中,开发人员需要花费大量的时间去编写与业务功能无关的代码。虽然框架本身屏蔽了分布式系统通信的一些通用功能实现细节,但开发者却要花更多精力去掌握和管理复杂的框架本身,在实际应用中,去追踪和解决框架出现的问题也绝非易事。
另外,开发框架通常只支持一种或几种特定的语言,没有框架支持的语言编写的服务,很难融入面向微服务的架构体系,想因地制宜地用多种语言实现架构体系中的不同模块也很难做到。同时框架以lib库的形式和服务联编,复杂项目依赖时的库版本兼容问题非常棘手框架库的升级也无法对服务透明,服务会因为和业务无关的lib库升级而被迫升级。
于是,为了解决这些问题,Service Mesh诞生了。
二、Service Mesh:微服务时代的TCP/IP协议
Serice Mesh的诞生,就是为了将微服务时代的通信语义剥离出来,从而使得微服务本身更加关注业务逻辑,它为每个微服务提供了一个代理,而这个代理如同TCP/IP协议一样,把微服务时代所需要的通信语义放在一个层面完成,从而使得业务开发者们从繁重的工作中解放出来。而这个代理,就是大名鼎鼎的Sidecar(边车)模式了。
Sidecar原意是指从二战时开始被广泛使用起来的挎斗摩托车。这个名字也是一种著名的饰以红樱桃的混合鸡尾酒,同时也指在三人以上多人运动中,在旁边处于辅助地位或者拍摄的人。
在Service Mesh中,监视、日志、限流、熔断、服务注册、协议转换、冪等……" 这些功能,其实都是大同小异,是完全可以做成标准化的组件和模块的。在这种情况下,边车就像一个微服务的 Agent,这个服务所有对外的进出通讯都通过这个 Agent 来完成。这样,我们就可以在这个 Agent 上做很多文章了。
这样,所有的微服务通过Sidecar连接起来之后,就像一个网格一样,这也是Service Mesh名称的由来。
那么,Sidecar具体的作用是什么呢?我们以Service Mesh概念的提出者Buoyant出品的Linkerd为例,来解析一下边车模式的服务流程。在Linkerd里面,一个服务请求的处理流程包括以下几个部分:
1、动态路由:根据上游服务请求参数,确定下游目标服务;除了常规的服务路由策略,Linkerd还可以通过这一层动态路由能力,支持灰度发布、A/B测试、环境隔离等非常有价值的场景。
2、服务发现:确定目标服务后,下一步就是获取对应的实例的地址列表(e.g. 查询service registry)。
3、负载均衡:如果列表中有多个地址,Linkerd会通过负载均衡算法(e.g. Least Loaded、Peak EWMA)选择其中⼀个合适的低延迟实例。
4、执行请求:发送请求到上一步所选择的实例,并记录延迟和响应结果。
5、重试处理:如果请求未响应,则选择另⼀个实例重试(前提:Linkerd知道该请求是幂等的)。
6、熔断处理:如果发往某个实例的请求经常失败,则主动从地址列表中剔除该实例。
7、超时处理:如果请求超期(在给定的deadline时间点之前仍未返回),则主动返回失败响应。
8、可观测性:Linkerd会持续收集和上报上述各种行为数据,包括Metrics和Tracing。
而这些服务,就类似于TCP服务提供的网络传输处理逻辑了,类似于TCP服务解决了网络传输中通用的流量控制问题,将技术栈下移,从服务的实现中抽离出来,成为操作系统网络层的一部分一样,Service Mesh也将微服务间通信所需要的通用功能剥离出来,将技术栈单独抽出一层,从而成为分布式系统的一部分。
三、主流Service Mesh实现
目前主流的Service Mesh实现包括Linkerd、Envoy、Istio、Conduit等。