初探 Server-Mesh
本次技术分享只做技术宏观思维与认知上的分享,具体配置细节与部署不在此次讨论范围。
前言
本次讨论围绕三个点展开:
- 微服务的局限性
- 了解 Server-Mesh 的功能与实现方式
- 目前基于 Server-Mesh 而实现的 Serverless
我们最熟悉、最常用的 Java、Spring-Cloud、Spring-Cloud-Alibaba 等技术体系,归属于传统微服务的架构设计。此设计存在 SDK 强耦合问题,每次底层 SDK 版本的更新极大可能影响到业务层面的服务稳定性。SDK 与代码环境强耦合,就会存在诸多限制,不能完整地运用市面上不同语言与其对应的生态组件来做更擅长的领域,例如:灵活快速的 Go、Python 语言及其对应的协程、爬虫、神经网络等组件;严谨并且没有垃圾回收开销的 Rust 语言,更适合企业级中间件高效率低内存占用场景。所以每种语言有它各自的优势与生态环境,以更长远的发展来看,大体量的龙头企业将会把业务部署与实现落地到不同的语言上进行迭代是一种趋势。
传统微服务体系图:

并且如今 JVM 引以为傲的跨操作系统优势,其特性也被 K8S、Docker、Containerd、CRI-O、Kata 等容器技术与生态体系取代。垃圾回收机制、动态代理、Agent、ZGC 等高级特性也被其他语言借鉴。目前来看支撑 Java 语言地位的是长年积累下来的生态体系(Apache、Spring、Ali、Huawei 等开源社区注入新的中间件,例如知名的 Kafka、Hadoop、Hbase、RocketMQ、Flink、Seata 等等,以及后续继续推出的中间件来保持语言生态的活跃)。但随着时间的推移,长远看来(20-30 年以上,主观预言,仅供参考),这些优势将可能被后起之秀所占据,下一代微服务体系势必将会在各类语言优势的基础上进行迭代更新。
个人思考:Java 已被 Oracle 收购,但 Oracle 并不是技术激进型企业,后续很有可能会限制住 Java 的发展。虽然有开源版本,但开源力量不如企业集中。目前 IT 界大佬 Google 的 Go 语言已经迅速崛起,并已占据 Java 部分市场,这可能也是字节、B站、腾讯、百度、京东、小米等企业选择它的原因之一。
服务网格
简介
回到我们关注的 Server-Mesh(服务网格),其目前主要的实现思路是 Sidecar(边车模式)。K8S 中我们用 Pod 来做基本部署单元,Sidecar 则是在一个 Pod 中部署 Proxy 容器,Proxy 容器与业务 Server 容器部署在同一个 Pod 中(Pod 容器注入),并且 Proxy 容器将会代理掉 Server 容器的所有流量。
Istio 实现 Server-Mesh 架构宏观图:

citadel: 负责身份认证和证书管理的核心安全组件。
galley: 负责配置的管理组件,如验证配置文件格式和内容的正确性,并将这些配置信息提供给 pilot 和 mixer。
pilot: 控制中枢,包含了服务发现和规则转化与下发。
proxy: 由 C++ 开发的 Envoy 与 Pilot-agent 实现,提供了动态服务发现、负载均衡、TLS、熔断、健康检查、流量拆分、灰度等功能,另外生成遥测数据,为微服务提供可观测能力。
Ingressgateway: 入口处的 gateway,即网格外访问网格内的服务就是通过这个 gateway 进行的。
通过 Proxy 容器,实现了业务代码与其 SDK 完全解耦,并且将获得许多功能特性:流量镜像、灰度发布、服务注册发现、远程调用、流量熔断、降级、链路追踪、平面控制、内网数据加密传输(分布式事务目前没有特别的解决方案,因为事务严格来说不属于服务治理层面)。并且对程序员来说完全透明,开发人员不需要了解其部署细节,几乎完全按单机版开发,没有语言限制,不依赖任何微服务 SDK。企业又可以选用不同的语言特性开发不同的功能模块(可能会带来更大的代码管理成本、沟通成本,团队掌握的语言更加广泛)。
官方 Demo
官方 Demo Book-Info 微服务,可通过 Helm 一键部署到 K8S 环境,即可体验其特性(Book-Info 架构图):
Bookinfo 微服务使用了 Istio 进行边车部署,使用了 4 种不同的语言程序,并且 Java 语言开发的 Reviews 服务提供了 3 个不同版本的应用,可以很好地体现出 Istio 在多版本控制、流量管理、流量迁移、整合等多方面的能力。大家可以自己去部署体验一下,可以很直观地感受到 Service-Mesh 的功能之强大、配置之灵活(都是秒级生效的配置,无感知流量迁移)。
市面上最常见实现
Istio
Istio 是由 Google、IBM 和 Lyft 发起的开源 Service Mesh 框架。该项目在 2017 年推出,并在 2018 年 7 月发布了 1.0 版本,截至目前 2022-12-06 版本为 1.16.0。Istio 是 Service Mesh 目前实现的典型代表,如果说 Sidecar 是整个 Service Mesh 的数据面,那么 Istio 主要在控制面上做了更多的改进。Istio 使用 Envoy 作为 Sidecar,控制面相关全部使用 Golang 编写,性能上有了很大的提升。Istio 首先是一个服务网格,但又不仅仅是服务网格:在 Linkerd、Envoy 这样的典型服务网格之上,Istio 提供了一个完整的解决方案,为整个服务网格提供行为洞察和操作控制,以满足微服务应用程序的多样化需求。
Linkerd2
Linkerd 是 Buoyant 公司 2016 年率先开源的高性能网络代理,是业界的第一款 Service Mesh 框架,主要用于解决分布式环境中服务之间通信面临的一些问题,如网络不可靠、不安全、延迟丢包等。Linkerd 最初使用 Scala 语言编写,其版本 Linkerd2 使用 Go 与 Rust 重构。
The world’s lightest, fastest service mesh.
Conduit
Conduit 于 2017 年 12 月发布,是 Buoyant 继 Linkerd 后赞助的另外一个开源项目,作为 Linkerd 面向 Kubernetes 的独立版本。Conduit 旨在彻底简化用户在 Kubernetes 上使用服务网格的复杂度,提高用户体验,而不是像 Linkerd 一样针对各种平台进行优化。Conduit 的主要目标是轻量级、高性能、安全并且非常容易理解和使用。同 Linkerd 和 Istio 一样,Conduit 也包含数据平面和控制平面,其中数据平面由 Rust 语言开发,使得 Conduit 使用极少的内存资源,而控制平面由 Go 语言开发。
Buoyant. All of the service mesh. None of the service mess.
不同架构对比图

小结
Kubernetes 的出现已经解决了运维中容器部署、高可用、多副本、容器迁移、弹性扩容、滚动更新、镜像版本管理、服务探活、计算资源分配、计算节点监控等的大部分问题,拥有优秀的自动运维机制。但 K8S 在应用层 Service 容器上的监控与流量管理、容器之间的相互调用、监控、注册、配置、流量治理等功能并未提供。为了补充此功能模块则出现了 Server-Mesh 体系的技术,来扩展 K8S 在这方面的能力,使得微服务不再关注具体配置、环境细节,侧重关心业务功能实现,并且摆脱语言环境的限制。
Serverless
简介
随着微服务理念不断深入人心,越来越多的企业把自身的应用逐步由单体转变成微服务架构,Container 容器技术的出现也加速了这个转移过程。虽然它有效地解决了众多服务运行环境差异问题,但是随着服务数目的增多,容器的编排与管理成为了新的问题。Kubernetes 的出现则解决了大规模微服务容器编排部署所带来的挑战,让整个行业意识到 PaaS 的落地能够成为现实。而当微服务体系下的容器数目越来越多,服务治理、流量管理成为必然要解决的问题,因而 Istio 出现了,基于网络代理与控制相分离的实现策略,允许对服务控制策略进行有效合理的管控。
架构的迭代到这里仿佛到了很美好的阶段:
- 微服务:解决应用内聚、臃肿的问题。
- Container:解决服务运行环境差异和部署问题。
- Kubernetes:解决大量微容器编排管理、"聚合"部署问题。
- Istio:解决服务上线面临的流量、发布、治理等一系列容器相关的问题。
这个阶段乍一看,构建容器云仿佛有了一个完整的链路和解决方式,一切都将变得那么"完美"。
但让我们回过头来深入分析一下,微服务体系下的服务交互目前是否存在问题。首先,不管是 HTTP 还是 RPC,本质上都是服务与服务的远程调用,开发应用程序中无法做到服务与服务间的彼此透明。这会导致一个问题:不管微服务业务拆分多么"精细",本质上业务单元之间仍然不能独立运行和迭代发展,没有彻底解耦;同时在面向不同开发领域衍生时,无法选择最合适的实现方式。所以我们希望可以基于不同的"模板"、"配置"把开发环境标准化处理,同时提供"事件"机制,将服务与服务交互的耦合度降到最低。其次是服务线上运行的动态伸缩问题:当下 Kubernetes 环境下的弹性伸缩,需要由客户收集监测数据并自主手动实现,但是我们更希望服务线上能够更加自动化和智能化。
最后是服务标准化问题。我们希望服务内部的模型是标准的、能够快速复制和快速构建的;服务通信是标准的:协议标准,格式标准;运行环境是标准的:快速部署,快速迁移。
于是 Knative 的出现恰好解决了远程直接调用、服务线上自动扩容、版本快照以及一系列标准化问题。
Knative
Knative 是 2018 年 Google 推出的 Serverless 世界的利器,可在任何公有或私有云上实现无服务器架构,这样用户可以使用无服务器编程技术。目前参与的公司主要是 Google、Pivotal、IBM、Red Hat,于 2018 年 7 月 24 日对外发布,当前还处于快速发展的阶段。与 Kubernetes 不同,K8S 需要始终运行至少一个 Pod 实例才能为应用程序提供服务,而 Knative 可以缩容到零(冷热启动技术)。当客户端请求访问您的应用程序时,Knative 才开始实际运行应用程序的 Pod。这可以节省大量用于保持应用整年运行的费用。例如访问不那么频繁、低频率使用的功能模块,可以考虑冷启动应用,以节约内存和计算资源(可通过技术手段优化容器启动时间,减少冷启动延迟【最快毫秒级启动】,目前国内做得最好的应该是阿里云)。
官网地址:
官方文档 knative.dev/docs 与 github.com/knative
Knative 的目标是在 Kubernetes 之上为整个开发生命周期提供帮助。它的具体实现方式是:首先使你作为开发人员能够以你想要的语言和方式来编写代码,其次帮助你构建和打包应用程序,最后帮助你运行和伸缩应用程序。Knative 主要由 Build、Serving 和 Eventing 三大核心组件构成,正是依靠这三个核心组件,驱动着 Knative 这艘 Serverless 巨轮前行。
Build(编译系统)
- 内部构建:它的构建完成是在 Kubernetes 中进行的,快速地把函数编译上线,与整个 Kubernetes 生态结合更为紧密。
- 标准化:它旨在提供一个通用的标准化构建组件,可以作为其他更大系统中的一部分;部署脚本标准化结构化,可以更好地将服务进行迁移部署。
Serving(服务系统)
- 快速部署:快速部署 Serverless 容器。
- 按需扩容:支持自动扩缩容和收缩到 0 实例。
- 路由策略:基于 Istio 组件,提供路由和网络编程。
- 版本快照:支持部署快照(生产环境容器快照,可长期保存,并任意恢复到某个快照版本)。
Eventing(事件系统)
Source(源)、Channel(通道)、Subscription(订阅)
事件系统使得生产和消费事件变得容易,抽象出事件源,并允许操作人员使用自己选择的消息传递层。Serverless 中最重要的是基于事件的触发机制,也就是说当某件事发生时,就触发某个特定的函数。事件概念的出现,让函数和具体的调用方能够解耦:函数部署出来不用关心谁会调用它,而事件源触发也不用关心谁会处理它。简而言之,在我们的代码中并不需要去书写具体调用方 Service,只需要关注事件发送与处理事件即可(相信对 MQ 队列熟悉的人已经心里有底了,不过 Eventing 的事件系统更加完备一点,有多种事件处理模式)。我们的 Service 在远程 RPC 或 HTTP 调用时,不需要关注具体服务实例,也不需要去订阅注册中心,只需要发出事件源即可,具体事件的返回数据全部由 Eventing 完成,真正实现了服务间的透明,解决了服务耦合问题。【正所谓耦合与解耦往往只是差了一个中间层】

整体优势
便利性:Knative 以 Kubernetes 作为其底层框架,因此无论是线上还是线下,任何 Kubernetes 集群,无论是云上 Kubernetes 服务还是自建 Kubernetes 集群,都可通过安装 Knative 插件快速搭建 Serverless 平台。
标准化:Knative 联合 CNCF,把所有事件标准化,统一为 CloudEvent,提供事件的跨平台能力,同时让函数和具体的调用方能够解耦。
服务间解耦:使用 Knative 使得应用不再与底层依赖服务强绑定,可以跨云实现业务互通。
成熟的生态:Knative 基于 Kubernetes 体系构建,与 Kubernetes 生态结合更紧密。
自动伸缩:监控应用的请求,并自动扩缩容,借助于 Istio(ambassador、gloo 等)天生支持蓝绿发布、回滚功能,方便应用发布流程。
应用监控:支持日志的收集、查找和分析,并支持 metrics 数据展示、调用关系 tracing。
快照部署:对每次发布的服务记录其快照信息,并可长期保存,可在任意时间节点无感知地恢复到某个快照版本。
总结
Serverless(无服务器架构)成为了目前新的技术热点,它是在传统容器技术和 Server-Mesh 服务网格上发展起来的。无服务器云函数可以让开发者无需关心服务器的部署运营,只需开发最核心的业务逻辑或者函数,即可实现上线运营,并自动具备分布容灾能力、依据负载自动扩缩容,在公有云中按照实际调用次数、执行时长、计算资源消耗来计费,做到没有计算资源浪费,更好地节约企业开销。
Serverless 大体上可以分为两种类型:【BaaS 是后端即服务,FaaS 是函数即服务】
BaaS: 无服务器首先用于描述显著或完全包含第三方云托管应用程序和服务的应用程序,以管理服务器端逻辑和状态。这些通常是"富客户端"应用程序——比如单页网络应用程序或移动应用程序——使用庞大的云可访问数据库生态系统(例如 Parse、Firebase)、身份验证服务(例如 Auth0、AWS Cognito)等等。这些类型的服务以前被描述为"后端即服务",也就是我们的 Spring-boot、Tomcat、Dubbo、Weblogic、Gin、Flask 等后端常用的容器与服务中间件。
FaaS: 无服务器也可以指服务器端逻辑仍然由应用程序开发人员编写的应用程序。但与传统体系结构不同,它在无状态计算容器中运行,这些容器是事件触发的,只需要实现一个函数,无需关心其他环境,是短暂的(可能只持续一次调用),并且完全由第三方管理。理解这一点的一种方法是"作为服务的功能"或 "FaaS"。国外 AWS Lambda 是目前函数即服务平台最受欢迎的实现之一,国内目前提供 FaaS 服务的有阿里云上的 FC 函数计算服务。
简而言之,无服务器架构的出现不是为了取代传统的应用,而是从具有高度灵活性的使用模式及事件驱动的特点出发,帮助我们减少部署、提高扩展性并减少代码背后基础设施的维护负担,为我们提供更多的可能性去选择更适合企业的部署方案。
后续思考
-
未来的部署架构会怎样发展?其高可用、高性能、高并发 3H 的特性将会如何衍生新的技术体系?企业部署的私有云可靠性如何做到 6-12 个 9 的可用性【6 个 9:(1-99.9999%)*365*24*60*60=31秒,一年停机时间不能超过 31 秒;但 12 个 9 可就是不小的挑战,从企业成本角度来说没必要,甚至不可能去实现,一年停机时间不能超过 (1-99.9999999999%)*365*24*60*60=0.00003秒】?配合异地多活的架构体系,又可以衍生出多少新的中间件技术呢?
-
这种架构就只有优点没有缺点吗?其开销与体量、可控性是否适合所有企业?企业抛开业务场景直接上 Serverless 体系是否科学?
-
有没有发现软件上的容器生态技术,与硬件超融合技术有异曲同工之妙?其目的都是弹性、迁移、节约成本、灵活、敏捷、更可靠。
如有不足欢迎各位补充,留言交流。
评论 / COMMENTS