Spring Boot + Spring Cloud 仍是 Java 生态最主流的框架
2014 年 4 月 Spring Boot 发布 1.0 版本,经过 8 年时间的发展,Spring Boot 已然成为 Java 开发框架的事实标准。在分布式微服务领域,2016 年 1 月 Spring Cloud 发布 Angel.SR5 版本。Spring Cloud 延承了 Spring Boot 最核心的组件化、低配置快速集成的核心思想,同时定义了一套标准的微服务 SPI。基于这套 SPI 出现了 Spring Cloud Netfix 等优秀的微服务解决方案实现套件。在远程服务调用框架方面,Feign 和 RestTemplate 基于普适的 HTTP 协议,在易用性、可观测性、跨语言等方面具备天然的优势。所以 Spring Cloud 自 2016 年发布第一个版本之后蓬勃发展。
从行业情况看,Spring Boot + Spring Cloud 是目前 Java 使用最广泛的开发框架之一。
2018 年开始以 Istio 为代表的 ServiceMesh 开始在社区中孵化,到 2022 年已经有非常多的 ServiceMesh 产品。ServiceMesh 核心思想是下沉服务调用相关的基础能力到独立的 Sidecar 进程,通过流量代理的方式治理流量。任何一种方案都不是万能药, Sidecar 模式也存在一些问题。例如:高度依赖底层 Paas 能力治理 Sidecar (注入、版本管理、升级等)、Sidecar 需要额外占用一定的资源、增加一定的网络延迟、增加排障难度等。所以国内真正能够落地 ServiceMesh 的企业并不多。
综上所述,我们认为在未来很长一段时间内 Spring Boot + Spring Cloud 仍是 Java 主流的微服务解决方案,虽然它看上去没有像 Istio、Dapr 那样的先进。在满足企业业务发展诉求的前提下,低成本、高效、稳定的架构方案才是最好的方案。
腾讯 2021 年开源的北极星(PolarisMesh)提供了一站式微服务解决方案
北极星是一款集注册中心、配置中心、服务治理中心为一体的一站式微服务解决方案,在腾讯内部已覆盖 90% 的业务,注册的实例节点数更是达到了 500 万的规模。在 21 年开源之后,在社区内也有外部公司生产落地。
公司内部的架构师经常会做一些技术选型,比如注册中心用 Zookeeper、Consul、Nacos 等,配置中心用 Apollo、Nacos,限流熔断用 Sentinel 。多组件也意味着需要维护多套服务,占用更多的资源,用户体验上也难以做到一致性。
所以一站式微服务解决方案能够大大简化技术选型、运维、资源成本。当然也可以把北极星当做方案里的一部分,例如只用北极星的服务注册发现,配置中心仍然选型 Apollo。毕竟还是那个道理,没有万能的方案,适合企业业务自身诉求的方案才是最好的方案。
另外北极星在某些能力横向对比上也有一定的优势。例如完全无状态的注册中心更加便于运维,强大的服务路由能力支持复杂的业务场景等。具体的产品功能在第二部分会更加详细的介绍。
小结
基于以上两点核心原因,把北极星作为 Spring Cloud 一个开箱即用的实现套件就顺理成章了。既能满足 Spring Cloud 的用户,又能满足北极星 Java 的用户。当然 Spring Cloud Tencent 目前只对接了北极星的能力,后续会支持更多腾讯开源的优秀产品。
目前 Spring Cloud Tencent 主要提供了微服务领域常见的服务注册与发现、配置中心、服务路由、限流熔断以及元数据链路透传能力。接下去会详细介绍每一部分的能力。
Spring Cloud Tencent 能力大图
服务注册与发现是 Spring Cloud Tencent 最为核心的功能之一,通过实现 Spring Cloud 的服务注册与发现的标准接口,提供微服务应用快速接入北极星服务注册中心的能力。开发者通过简单的引入 Spring Cloud Tencent 服务注册与发现的依赖,即可使用北极星的服务注册与发现功能。接入服务注册与发现之后,还能按需使用北极星提供的强大服务治理能力,例如场景化的服务路由能力、服务熔断能力等。方便开发者针对微服务的实际生产场景作出个性化的服务治理配置。
北极星的服务模型包括命名空间、服务和服务实例。
命名空间
命名空间提供了一种在同一个注册中心下资源的逻辑隔离的机制,同一命名空间下的服务命名必须唯一,但是跨命名空间允许存在同名的服务。命名空间常用于区分不同的环境或者多个业务之间的服务隔离。
服务
服务也是逻辑的概念,提供一个特定业务领域的服务能力。例如订单服务,用户服务,转账服务等。
服务实例
服务实例是服务下的一个具体的物理节点。
服务实例详情
Spring Cloud Tencent 在基础的服务注册发现上,提供了一些拓展能力。首先,Spring Cloud Tencent 集成了北极星的一些路由插件,通过在北极星控制台页面更改服务实例的隔离状态或者权重值,都可以实现服务实例的动态上下线的特性,如上图所示。
Spring Cloud Tencent 还提供了多服务注册与发现的进阶功能。举个例子,公司内部多个部门或组织使用了不同的服务注册中心,当决策技术栈统一或是迁移到北极星注册中心时,需要使用平滑的方式进行业务改造,而非直接替换原有的 SDK 接入北极星注册中心。此时可以使用 Spring Cloud Tencent 的多服务注册与发现的能力,帮助开发者的微服务应用过渡技术栈转换的尴尬期。
Spring Cloud Tencent 提供的这样一系列针对服务注册与发现的周边功能,完善了微服务架构的治理与管控能力。
今年上半年北极星开始支持配置中心的能力。北极星配置中心核心配置三元组模型为:
Namespace
用于逻辑隔离集群的能力,例如常用于隔离环境。
FileGroup
配置文件组,一组配置文件的集合。在 Spring Cloud Tencent 里,我们推荐的最佳实践是一个应用为一个 FileGroup。对于框架类的配置,以框架名作为一个 FileGroup, 例如 dubbo。
File
配置文件,例如 properties 、yml 格式的配置文件。配置文件为最小管理单元,而不是配置文件里的配置项。
[Namespace, FileGroup, File] 唯一定位一份配置文件。我们在设计模型的时候,参考了业界主流的配置中心产品,我们认为配置文件、配置文件组的概念,是开发者广泛认知且理解成本最低的配置领域模型,例如本地磁盘的文件夹和文件的概念。
配置中心核心能力是配置管理能力以及动态实时推送能力。在配置管理方面,一个应用往往具有非常多的配置文件,如何清晰的管理配置文件是一个非常重要的能力。我们在管控台设计 UI 时,开创性的把文件名以 / 作为分隔符树状形式展示。如下图所示,可以按应用模块划分目录,通过目录方式能够清晰管理一个应用下杂乱的配置文件。
配置文件管理页面
另外,在 Spring Cloud 集成方面,众所周知 Spring Boot 会自动加载应用 resources 目录下的 application.yml
、application.properties
以及优先级更高的 application-${activeProfile}.yml
文件。在 Spring Cloud Tencent Polaris Config 集成时,我们完全沿用了这套原生的配置加载机制。也就是 Spring Cloud Tencent Polaris Config 在启动时,会自动加载应用文件组下的 application.yml
和 application-${activeProfile}.yml
文件到 Spring 容器里。用户在做迁移时,只需把 resources 目录下所有的配置文件原封不动的上传到北极星即可。
在微服务领域,由于服务做了细粒度的拆分部署服务变的非常的轻量灵活。在结合 k8s 云原生极速弹性能力之后变的更加的强大。但是底层的 Paas 能力只是提供了基础弹性能力,真正发挥能力需要依赖上层的流量调配的能力。
放眼 Spring Cloud 生态,能够深度整合 Spring Cloud 提供场景化服务路由能力的组件套件并不多。这里解释一下场景化,服务调用框架根据一定的规则实现服务路由的能力我们称之为底层原子能力。原子能力是非常通用的能力,但是很多时候并不能直接用于具体的业务场景。例如常见的测试环境分组,就近路由,蓝绿发布等称之为场景。服务路由只有做了场景化之后,才能真正做到开箱即用服务于业务。
Spring Cloud Tencent Polaris Router 目前实现了两种场景化的路由能力以及一种非常灵活的规则路由的能力。
元数据路由
服务实例都会附属一组元数据,例如环境信息,机房信息等等。元数据路由简单的讲就是以元数据信息作为路由的依据进来路由。这样讲还是有些抽象,我们以一个测试环境例子来解释一下。
开发环境示意图
上图是非常经典的用于解决测试环境冲突的方案。一次迭代中 SvcA 需要和 SvcD 联调,当团队人数少的时候,可以直接把 stable 环境部署成开发分支代码然后进行联调。但是当多个开发任务并行的情况下就会出现环境争抢的情况。一种解决方式是每个开发任务独立部署一套全链路的环境,这种方式耗时耗力效果还很差。业界最主流的做法就是上图所示,每个开发任务子环境只需要部署联调的应用即可,链路上不在子环境里的服务都路由回 stable 稳定环境。
使用 Spring Cloud Tencent 为了达到以上的目的,只需要每个服务部署的时候,增加以下两个环境变量即可实现。
SCT_METADATA_CONTENT_ENV=dev1
SCT_METADATA_CONTENT_TRANSITIVE=ENV
Spring Cloud Tencent Polaris Router 组件会自动读取以上环境变量,并在每次服务调用时优先调用到跟当前实例 ENV 值一样的目标实例。
元数据路由使用的场景非常广泛,更多的细节请查阅 Github Wiki。
规则路由
元数据路由本质上是基于服务实例的元数据进行筛选,是为了支持具体特定的场景而内置的服务路由能力。无需下发任何路由规则,使用起来非常简单。
而实际业务场景非常复杂,例如以下几种典型的业务场景:
内部员工路由到一套生产灰度环境,外部普通用户则路由到生产正式环境
VIP 客户路由到一套高保环境,普通客户路由到普通环境
以上两种业务场景,则无法通过元数据路由实现。因为涉及到业务请求参数,而不是系统维度的环境变量。规则路由就是用于满足复杂业务场景而实现的一套基于规则的服务路由实现。
一个典型的规则如下图所示:
路由规则配置页面
上图表达的含义是:HTTP Query Param 的 uid 参数值为 100 时,调用到 ENV=gray 的实例分组。通过路由规则能够描述出绝大多数复杂的业务场景。
为了便于使用, Spring Cloud Tencent 内置了一套表达式标签规则,自动从 HTTP 请求中解析标签值。目前支持的表达式规则有:
${http.query.xxx}
${http.header.xxx}
${http.cookie.xxx}
${http.method}
${http.uri}
规则路由相对比较复杂,更多的细节请查阅 Github Wiki。
就近路由
生产环境服务为了高可用、容灾等能力往往需要多机柜、多机房、多地域部署。
部署模型图
如上图所示,范围从小到大依次为: Campus < Zone < Region < All 其中 Campus、Zone、Region 在服务注册发现领域模型里统一定义为元数据,是一种特殊的位置元数据(Location Metadata)。
就近路由顾名思义,服务调用时按照同 Campus、同 Zone、同 Region 的优先级从高到低依次选取目标服务实例。核心是减少服务调用因物理距离增加的网络耗时。本质上,就近路由是一种基于特定一组位置元数据的元数据路由。
通过 Spring Cloud Tencent 实现就近路由,只需要在服务实例上打上以下环境变量即可。
SCT_METADATA_CAMPUS
SCT_METADATA_ZONE
SCT_METADATA_REGION
随着业务发展的日益壮大,网络请求量也越来越多,导致在某些场景下,业务应用的服务端会出现爆发式的流量涌入,因此需要对服务提供方的给予一些保护手段。通过服务限流功能,开发者可以通过控制 QPS 的方式,以避免被瞬时的流量高峰冲垮,从而保障系统的高可用性。服务限流主要有两个应用场景,过载保护 和 业务防刷 。过载保护是保护业务不被突发流量打垮,业务防刷是防止恶意用户发送过多流量影响其他正常用户。Spring Cloud Tencent 内置了针对 Spring Web 和 Spring WebFlux 场景的限流 Filter 帮助业务快速接入北极星的限流能力。
Spring Cloud Tencent 支持北极星提供的两种类型的服务限流能力,即单机限流与分布式限流。
单机限流
单机限流是针对单个被调实例的级别的限流,流量限额只针对当前被调实例生效,不共享,如下图所示。单机限流一般适用于保护服务自身不被打垮,按照每个服务集群单机的容量来计算配额。
单机限流示例图
单机限流的效果分为 快速失败 和 匀速排队 。快速失败指的是当 QPS 到达限流规则指定的配额时,立刻返回一个限流类型错误响应给所有超过阈值的请求。而匀速排队是一种基于漏桶算法实现的削峰填谷限流方式,帮助服务端能够在流量洪峰到达时,还能保证一个匀速处理的状态,让一部分请求在一段排队等待时间后还能被处理,而不是直接失败。关于匀速排队的详细介绍可以参考 Github 官方 Wiki。
分布式限流
分布式限流是针对服务下所有实例级别的限流,多个服务实例共享同一个全局流量限额,如下图所示。分布式限流一般适用于保护第三方服务或者公共服务(比如保护数据库);或者是在网关层进行限流,对通过网关接入的后端服务进行保护。
分布式限流示例图
Spring Cloud Tencent 提供了自定义限流规则能力,开发者可以根据自身的业务场景定制对应的限流规则。
限流规则配置界面
在微服务架构的运维场景下,有时候会遇到单点服务实例故障的情况,如果不能及时剔除,那么仍旧会有请求转发到故障的服务实例上。Spring Cloud Tencent 提供了服务熔断的能力,通过上报每次服务间调用的结果,判断被调方服务是否出现故障,进而将其屏蔽,并启动定时任务对熔断实例进行探活。在达到恢复条件后对其进行半开恢复。在半开恢复后,释放少量请求去进行真实业务请求探测。并根据真实业务探测结果去判断是否完全恢复。这个功能能有效剔除异常的服务实例,为服务治理提供了重要的帮助。
以上只是简单介绍了 Spring Cloud Tencent 部分能力,想详细了解更多的能力请访问我们 Github 官方主页。
文章开头提到我们为什么要做 Spring Cloud Tencent。我们坚信在 Java 领域 Spring Cloud 在很长一段时间内仍是微服务的主流方案。我们希望结合北极星一站式微服务能力,降低微服务架构门槛,为广大企业提供开箱即用的全套微服务解决方案。从而使企业更加聚焦自身业务的发展,提高生产力。
一款好用的产品需要经受丰富的场景打磨稳定性、易用性,以及不断完善自身的产品力。以下是我们目前想到的一些需要支持和完善的点。当然随着产品的发展、使用的用户越来越多,会有更多的诉求,我们会持续不断的迭代下去。
SCT 规划
如果你也是 Spring Cloud 的爱好者
如果你的公司正在使用 Spring Cloud 并且有一些好的实践
如果你的公司正在做微服务技术选型
… …