导语
北极星是腾讯开源的一款服务治理平台,用来解决分布式和微服务架构中的服务管理、流量管理、配置管理、故障容错和可观测性问题。在分布式和微服务架构的治理领域,目前国内比较流行的还包括 spring cloud,apache dubbo 等。在 kubernetes 的技术领域,也有以 istio 为代表的 servicemesh 技术。本篇 blog 主要分析北极星的优势,及其服务注册发现的技术实现。
我是如何看待这些技术
要做好一个服务治理框架,核心功能和要素至少包括以下几点:
-
服务注册发现
-
路由,熔断,限流
-
配置中心
-
可观测性, 日志、度量、链路追踪
从功能实现方面来看,不管是 springcloud,apache dubbo,istio 还是北极星,基本都实现了这些功能,那它们的实现思路有什么不同呢?
springcloud
springcloud 是完全架构在 springboot 基础上的,是 springboot 开发框架很自然的延伸,因此继承了 springboot 框架所有的优点,可以非常灵活的集成各类服务注册发现、服务治理、可观测组件。例如 springcloud 框架自身开发了 spring-cloud-config 和 spring-cloud-sleuth 组件,分别提供了配置和部分可观测性的能力;在其他能力方面,早期版本主要由 netflix 提供的 eureka, ribbon, hystrix等组件提供了服务注册发现,服务治理的能力; 随着 netflix 很多组件生命周期结束, springcloud 又通过自定义的 abstract loadbalance/route 接口及实现, 以及集成的 resilience4j/sentinel 等熔断限流组件,继续为用户提供统一的服务注册发现,服务治理等方面的能力。
springcloud 在实际使用过程中, 可能会给人一种没有一个统一的服务治理模型的错觉, 这是因为 springcloud 保持了自身的胶水框架的特性和思路, 可以集成和融合各类治理组件,例如熔断限流就提供了 hystrix、resilience4j、sentinel 等方式。这样的框架特性,优势是灵活,可以融合各类框架,劣势是抽象统一的治理模型比较困难,因此 springcloud 并没有提供一个统一的服务治理控制面,即使是 spring-cloud-admin 的扩展,也更多是基于 springboot actuator 提供可观测的管理,并没有提供服务治理的控制面能力。
servicemesh-sidecar 模式
servicemesh 解耦了业务逻辑和服务治理逻辑,它将服务治理能力下沉到基础设施,在服务的消费者和提供者两侧以独立进程的方式部署。这种方式提升了整体架构的灵活性,减少对业务的侵入性并很好的解决了多语言支持的复杂性。劣势是一方面服务通过 sidecar 的调用多了一道 iptables/ipvs 的转发,降低了一些性能,sidecar 也增加了少量的资源使用;另一方面是中小团队很难对框架灵活扩展,虽然 envoy 提供了 wasm 机制,其自身也能通过 c++ 扩展 filter,但是不管哪种方式,都需要团队有一定经验的人员来完成,中小团队很难提供这样的人员保障。
另外,istio 虽然也能提供基于虚拟机/物理机的部署,但是本身还是基于kubernetes 设计的,也对 kubernetes 部署最友好,对于未使用 kubernetes 的团队有一定的挑战。
polarismesh
polarismesh 从个人的角度看,是融合和兼容了很多技术的解决方案。
一方面,它可以看作是 springcloud 服务治理实践的一种自顶向下的正向思考过程,springcloud 是自底向上的一种构建思路,它提供了各类服务发现、服务治理、可观测组件的集成和融合,但是并没有提供统一的顶层治理模型(或者仅提供了一部分);而 polaris 是先基于下一代架构基金会所制定的服务治理标准,制定和扩展了服务治理的模型,然后基于该模型,分别构建了服务治理的控制面和数据面(各类语言的 sdk、开发框架、javaagent、kubernetes controller)。当然,基于该模型,也能很好的对接到 servicemesh 的治理方式, 这样就给未来的发展也留足了空间。
另一方面,polarismesh 也通过插件机制,为框架扩展预留了空间,如果当前的开源 polaris 不满足你的需求,可以较灵活的进行扩展。
polaris-go sdk 服务注册发现技术分析&源码阅读
本篇 blog 重点对 polaris-go sdk 的服务的注册和发现做下技术分析, 以及源码阅读。主要是服务注册和发现是各类服务治理框架最基础和核心的功能,因此先从它开始吧~
公共部分 sdkcontext
在客户端 sdk, 不论是服务注册的 api, 还是服务发现的 sdk,其内部都是封装了 sdkcontext 的上下文, sdkcontext 内部构成如下图所示:
configurationimpl: 主要是客户端 polaris.yaml 配置文件的映射, 分为4个部分,分别是 globalconfig, consumerconfig, providerconfig 和 configfileconfig 。
connectionmanager: grpc 连接的连接池管理接口。
plugin.manager: 插件管理接口,sdk 内部实现的各类功能- 熔断,限流,配置,健康检查,路由,负载均衡等都是按照插件的方式实现, 插件需要实现 plugin 接口,通过 pluginproxy 包装后交给 plugin.manager 管理。
engine:sdk 执行的各类动作,都交由 engine 处理, 例如服务的注册发现,限流,路由,熔断等,都是调用 engine 内的 api 实现。也就是 sdk 能执行的功能,都是由 engine api 统一实现。
服务注册流程
服务注册的粗略流程如下图所示 :
go 客户端 sdk 的整体服务注册流程比较线性, 没有涉及特别复杂的逻辑, 相关 grpc service 如下:
service polarisgrpc {
// 客户端上报
rpc reportclient(client) returns (response) {}
// 被调方注册服务实例
rpc registerinstance(instance) returns (response) {}
// 被调方反注册服务实例
rpc deregisterinstance(instance) returns (response) {}
// 统一发现接口
rpc discover(stream discoverrequest) returns (stream discoverresponse) {}
// 被调方上报心跳
rpc heartbeat(instance) returns (response) {}
// 上报服务契约
rpc reportservicecontract(servicecontract) returns (response) {}
}
服务发现流程
服务发现流程相对于服务注册流程要复杂很多, 主要原因是北极星的服务发现会涉及本地 cache 与 远程 server 端信息的懒加载同步,同时加载的服务信息也比较复杂,包括实例信息,服务信息,路由信息,限流信息等内容。
服务发现的粗略流程如下图所示 :
可以看到,服务发现中的关键点包括:
-
sdk 内部实现了 localcache 缓存机制, 同时 localcache 缓存具备以懒加载方式同步远程 server 中服务信息的能力。
-
sdk 与远程服务信息的同步,是由插件 serverconnector 实现, sdk客户端通过专门的 routine 和 channel 队列,在服务信息第一次远程懒加载完成后, 定时拉取远程 server 中的服务信息,并更新本地缓存和插件数据。
-
获取到服务信息后,通过路由和负载均衡机制,选取出可用实例,参考官网-流量管理。
-
其他细节包括: 与服务端通信后的异步回调更新机制,超时计算,重试 ,缓存实现,插件加载机制等 。
go sdk 服务发现的 grpc 接口如下:
// discoverclient 服务发现客户端接口
type discoverclient interface {
// send 发送服务发现请求
send(*apiservice.discoverrequest) error
// recv 接收服务发现应答
recv() (*apiservice.discoverresponse, error)
// closesend 发送eof
closesend() error
}
结语
上面的技术分析因为时间有限,难免有错误和遗漏,欢迎大家指正, 也特别感谢社区的帮助。北极星通过对服务治理标准的实现,提供了完善的服务发现和治理方案。同时, sdk客户端与 server 服务端的数据同步与交互,也有设计良好的服务治理模型和健壮的通信机制提供了可靠的保障。此外,通过插件机制,sdk框架 也提供了灵活扩展的能力 。
发表评论