高可扩展性、高性能、生产级的 SOFARPC 框架

阅读数:3769 2019 年 8 月 30 日 16:17

高可扩展性、高性能、生产级的 SOFARPC 框架

小蚂蚁说:

SOFA(Scalable Open Financial Architecture)是蚂蚁金服自主研发的金融级分布式中间件,包含了构建金融级云原生架构所需的各个组件,是在金融场景里锤炼出来的最佳实践。

SOFA(Scalable Open Financial Architecture)是蚂蚁金服自主研发的金融级分布式中间件,专注为金融用户提供安全、稳定、可靠、高效、敏捷的基础架构能力,帮助金融用户解决传统集中式架构转型的困难,打造大规模高可用的分布式系统架构,加快金融互联网 + 推进的速度。

RPC 框架作为分布式技术的基石,在分布式和微服务环境下,扮演着非常重要的角色。RPC 的概念术语在上世纪 80 年代由 Bruce Jay Nelson 提出,他在论文 “Implementing Remote Procedure Calls” 中提到 3 点:简单、高效和通用,并认为 RPC 框架应包含 User、User-stub、RPC-Runtime、Server-stub、Server 5 个部分。

SOFARPC 蚂蚁金服开源的一个高可扩展性、高性能、生产级的 Java RPC 框架,是蚂蚁金服服务化架构的基石。致力于简化应用之间的 RPC 调用,为应用提供方便透明、稳定高效的点对点远程服务调用方案。SOFARPC 提供了负载均衡,流量转发,链路追踪,链路数据透传,故障剔除等基础能力。

一、SOFARPC 总体设计与扩展机制

总体设计

从下图目前的 RPC 框架结构图来看,core 和 core-impl 是核心的功能,包含 API 和一些扩展机制,extension-impl 中,则包含了不同的实现和扩展,比如对 http、rest、对 metrics,以及其他注册中心的集成和扩展。

高可扩展性、高性能、生产级的 SOFARPC 框架

扩展机制

为了 RPC 各个环节都有充足的可扩展性,提供 SPI 的能力,所有内部的实现和第三方实现都是绝对平等的,我们实现了一套自己的 SPI 机制。基于这套扩展加载机制,我们可以实现自定义扩展点,实现 SOFARPC 内部及第三方的自由扩展。

二、SOFARPC 链路追踪

SOFARPC 的依靠集成 SOFATrace 来实现链路追踪技术,SOFARPC 作为公共组件在整个链路追踪技术系统中负责数据埋点工作。依赖 SOFARPC 自身强大的可扩展性设计,如微内核设计和事件总线设计,使得 SOFARPC 在不破坏开发封闭原则的基础上快速实现了链路追踪埋点工作。 SOFARPC 的链路追踪技术具有以下特点:

1、作为公共基础的通讯组件,SOFARPC 的链路追踪埋点对业务代码实现零侵入。

2、采用日志数据异步刷新机制,不影响正常业务性能。

3、采用了自适应采样设计,巧妙平衡了数据采集和性能的问题。

4、支持数据上报 zipkin, 通过与 zipkin 结合可以快速构建一个完整的连续追踪系统。

5、解决了异步线程链路调用数据问题。

6、采用了 OpenTracing 规范,因此可以和其他链路追踪手机和展示的技术框架快速整合。

三、SOFARPC 连接管理与心跳

在 RPC 调用过程中,我们经常会和多个服务端进行远程调用,如果在每次调用的时候,都进行 TCP 连接,会对 RPC 的性能造成比较大的影响。因此,实际的场景中,我们经常要对连接进行管理和保持。

SOFARPC 应用心跳包以及断线重连实现,结合系统 tcp-keepalive 机制,可以实现对 RPC 连接的管理和保持。

四、SOFARPC 同步异步实现

SOFARPC 以基于 Netty 实现的网络通信框架 SOFABolt 用作远程通信框架,使用者不用关心如何实现私有协议的细节,直接使用内置 RPC 通信协议,启动客户端与服务端,同时注册用户请求处理器即可完成远程调用。

SOFARPC 服务调用提供同步 Sync、异步 Future、回调 Callback 以及单向 Oneway 四种调用类型:

1、在 Sync 上,支持方法级别,接口级别,方法级别的超时设置。调用会阻塞请求线程,待响应返回后才能进行下一个请求。这是最常用的一种通信模型。

2、在 Callback 上,支持方法级别,接口级别,线程级别的回调设置。是真正的异步调用,永远不会阻塞线程,结果处理是在异步线程里执行。

3、在 Future 上,对用户提供了统一的 API 操作。支持原生 Future 和自定义 Future。用户 可以直接在当前线程上下文获取。在调用过程不会阻塞线程,但获取结果的过程会阻塞线程。

4、在 Oneway 上,设置简单。直接支持。为了防止应用出现类型转换异常,根据返回值设置不同的默认值。不关心响应,请求线程不会被阻塞,但使用时需要注意控制调用节奏,防止压垮接收方。

五、SOFARPC 线程模型

对于 SOFARPC 来说,和底层的 SOFABolt 一起,在使用 Netty 的 Reactor 主从模型的基础上,支持业务线程池的选择。

高可扩展性、高性能、生产级的 SOFARPC 框架

目前 SOFARPC 服务端的线程模型在综合考虑,和一些历史压测的数据支撑的情况下,我们选了主从线程模型,并对序列化和业务代码执行使用一个 BizThreadPool(允许对线程池的核心线程数,队列等进行调整),或者自定义的线程池。将序列化,反序列化等这些耗时的操作全部放在了 Biz 线程池中,这样可以有效地提高系统的整体吞吐量。

六、SOFARPC 单机故障剔除

SOFARPC 5.3.0 支持故障剔除功能,能够将存在长连接但因为处于亚健康状态的服务进行降级,使得客户端的请求更多地指向健康节点。当这些异常节点恢复正常后,故障剔除功能会对该节点进行恢复,使得客户端请求逐渐将流量分发到该节点。这种策略类似软负责,所有的逻辑都在客户端执行。

SOFARPC 的内核设计和事件总线设计,能够在不破坏开发封闭性的情况下轻松引入故障剔除功能。FaultToleranceModule 包含了两部分:

1、事件订阅,负责订阅同步和异步结果事件,作为入口统计手机 RPC 调用信息。

2、调节器。根据收集的信息,以及内置的一些策略完成服务的降级和恢复操作。其中包含了信息收集器、计算策略、度量策略、降级策略和恢复策略。

七、SOFARPC 泛化调用实现

在 RPC 调用中,客户端需要加载服务端提供的接口定义类衍生了泛化调用的需求,一个成熟的、功能完善的 RPC 框架一般都会支持泛化调用。

当客户端因为某种原因无法得到服务提供方的接口 jar 包时,或者是客户端是一个比较通用的系统,并不想依赖每个服务提供方提供的 facade 接口,但是又需要进行调用,那么此时就需要进行泛化调用。

SOFARPC 的泛化设计与实现

1、设计目标是:服务端无需感知是否泛化,一切都是由客户端进行处理。

带来的好处是:应用如果想要支持泛化,不需要改动服务端,只需要修改客户端即可。这是和其他 RPC 框架泛化调用最大的区别。

2、实现方式:通过 SOFA-Hessian 序列化支持泛化序列化,在进行泛化调用时,bolt 会根据上下文的序列化标记来使用对应的序列化器,SOFA-Hessian 特有的泛化序列化器可将 GenericObject 对象序列化成目标对象的字节流,服务端按正常反序列化即可。SOFA-Hessian 特有的泛化反序列化器也可将目标返回值反序列化成 GenericObject 等对象。

八、SOFARPC 数据透传

在 RPC 调用中,数据的传递是通过接口方法参数来传递的,需要接口方定义好一些参数允许传递才可以。数据透传功能,就是指数据不需要以作为方法参数的形式在调用链路中进行传递,而是直接存储到调用上下文中,之后通过 RPC 的内置对象,进行传递,调用双端可从上下文中获取数据而不需要去关注数据的传输过程。SOFARPC 提供的数据透传支持请求数据透传(客户端向服务端)和响应数据透传(服务端向客户端)。

九、SOFARPC 优雅关闭

在微服务架构中,假如应用没有支持优雅停机,则会带来譬如数据丢失,交易中断、文件损坏以及服务未下线等情况。微服务的优雅停机需要遵循 " 注销发布服务 → 通知注销服务 → 更新服务清单 → 开启请求屏蔽 → 调用销毁业务服务 → 检查所有请求是否完成 → 超时强制停机 " 应用服务停机流程。

SOFARPC 提供服务端 / 客户端优雅关闭功能特性,用来解决 kill PID,应用意外自动退出譬如 System.exit() 退出 JVM,使用脚本或命令方式停止应用等使用场景,避免服务版本迭代上线人工干预的工作量,提高微服务架构的服务高可靠性。

在设计优雅关闭的时候,可以考虑按照如下几个约定来进行实现。

(1) 应用能够支持优雅停机

(2) 优先注销注册中心注册的服务实例

(3) 待停机的服务应用的接入点标记拒绝服务

(4) 上游服务支持故障转移因优雅停机而拒绝的服务

(5) 根据实际业务场景提供适当的停机接口。

十、SOFARPC 路由实现

RPC 框架需要创造一种调用远程服务如同调用本地般的体验,因此在实现一个基于 RPC 框架的微服务架构的系统时,服务消费者(客户端)往往只需要知道服务端提供了哪些接口和方法,并不需要知道服务具体由哪些 IP 在提供。RPC 框架本身的服务发现和路由寻址功能解决了如何知道目标地址的问题,该过程对于 RPC 客户端调用方来说应该是完全透明的。整个路由寻址过程的阶段如下图所示。

高可扩展性、高性能、生产级的 SOFARPC 框架

在这个过程中,RPC 框架需要接入注册中心来完成服务发现和路由寻址的功能。同时,在应用大规模请求时,微服务系统还需要对请求服务集群化,同时通过负载均衡来达到降低访问压力的效果。

十一、SOFARPC 注解支持

通过 XML 的方式去配置 SOFA 的 JVM 服务和引用非常简洁,但是多了一定的编码工作量。

因此,除了通过 XML 方式发布 JVM 服务和引用之外,SOFA 还提供了 Annotation 的方式来发布和引用 JVM 服务。@SofaService 注解省去了 sofa:service 声明,但 bean 的定义还是必须要有的。

SOFA 实际上是注册了一个 BeanPostProcessor 来处理 @SofaService 和 @SofaReference 注解。需要发布引用的对象属于当前 bean 的实例变量,使用 xml 的方式进行服务发布和引用,可以直接通过 Bean 生命周期的 InitializingBean#afterPropertiesSet 方法进行扩展。在工程中注解扫描是一个对所有 bean 的操作,只能通过实现 spring 的 beanpostprocessor 这个接口,另外有些属性可能在发布时需要用到。

因此使用注解的方式进行服务发布和引用,分别基于 Bean 生命周期的 BeanPostProcessor#postProcessAfterInitialization、#postProcessBeforeInitialization 方法进行扩展。

本文转载自公众号蚂蚁金服科技(ID:Ant-Techfin)。

原文链接:

https://mp.weixin.qq.com/s/ugDwv_GAYlj0Idm8i9ObBA

评论

发布