分布式RPC框架

为了解决系统间交互中的维护成本及故障迁移成本问题,本文介绍了一个基于Thrift的分布式RPC框架Polaris的设计与实现。该框架解决了服务地址和服务管理等问题,支持多种语言并实现了监控统计等功能。

分布式RPC框架:Polaris 
在长期的业务发展过程中,对于系统间的交互,我们使用了Socket、RMI、Hessian、JSON等技术,针对每种技术,都需要维护一套相应的故障转移、故障恢复、追踪框架,对于商业平台多条业务线的大量系统交互来说,经常面临着硬件故障问题,此种交互方式引起的维护成本及故障迁移成本都是巨大的。另外,多种不同的接口技术也面临着接口兼容性的问题,例如对于RMI来说,我们就遇到了Spring从2.5.6升级到3.1.0所带来的RMI接口不兼容导致的接口调用错误问题。最后,我们内部也有一些跨语言的调用需求,比如用C++查询广告物料信息、Python脚本做统计,这些都会涉及到接口调用,而使用不能跨语言的技术(例如RMI和Hessian)成本会非常高。因此,我们需要统一内部系统接口交互方式,并降低接口的管理和维护成本。 

在实践过程中,我们比较了WebService、ProtocolBuffer、HTTP/JSON、Dubbo以及Thrift等技术。其中,WebService基于XML,兼容性良好,但其序列化/反序列化性能较差;ProtocolBuffer和HTTP/JSON无服务接口/地址描述;Dubbo的框架过于庞大;Thrift在接口定义文档、数据类型支持、跨语言等方面存在优势,然而对服务地址和服务管理方面支持力度不够,并且存在类型侵入问题。在分析比较之后,我们选定了Thrift,并在此基础上开发了服务注册中心,解决服务地址和服务管理方面的问题。对于类型侵入问题,从描述语言来看,长远来看它生成的POJO代码应该可以像WebService一样,消除类型侵入(例如,Facebook提供了开源的Swift框架,已经朝这个方向迈进了一步)。我们目前是提供了一系列的方法和转换类,自主进行类型转换适配工作。 

我们基于Thrift构建的分布式RPC框架Polaris如图5所示。 


 

 

图 5 分布式RPC框架Polaris


我们对Polaris的服务端和客户端都进行了增强。在服务器端,我们提供了标准的HTTP服务器,能够很轻易地将一个Thrift服务发布到一个URL上。同时,也集成了标准的认证和授权框架,有效地保证了业务的安全性;另外,我们在运维监控方面做了很多增强,能够监控每个方法的执行时间以及执行参数,这样的话可以面向整个商业平台,建立标准的监控统计架构。因为我们提供的服务是基于HTTP的,因此部分统计是可以直接沿用线上已有的监控统计软件,也有效减少了重新构建监控框架的成本。 

在客户端,主要添加了失败重试、提供了类RPC的调用方式,并且提供了一种抽象的机制简化了测试成本。通过Spring的依赖注入,可以支持在仅调整配置,不改变客户端代码的情况下进行本地调用和远程HTTP调用的切换。使用本地调用时可以更快地进行单元测试,在完成单元测试之后,可以直接通过调整配置切换成远程HTTP调用,在此过程中无需任何代码的调整。此方案还对接口迁移,比如从RMI接口迁移至Thrift接口提供了很大的帮助。一般情况下,大型复杂依赖系统内部接口间的依赖关系都会特别复杂,在进行接口梳理和迁移时成本和风险都非常高,特别是在系统的服务化改造过程中需要将内部接口提升为API接口的时候。在这种情况下,可以通过引入一个Thrift模块,将此模块依赖于需要提升为API接口的模块,而其他模块则仅依赖于此Thrift模块。在此调整过程中,可以随着业务版本的开发同步进行,而且可以重用大部分单元测试稍作调整即可使用,这样的话能够将成本和风险都降至最低。 

事实上,Thrift有标准的定义语言,能够对服务接口、异常、接口参数和返回值进行描述,同时支持Set、Map之类的数据结构。然而,它没有描述服务地址以及服务依赖关系等。因此,我们也构建了服务中心Aura,它的概念架构图6所示。 


 

 

图6 服务中心Aura概念架构图


图6中的通信框架服务端和通信框架客户端已经在前面介绍了。服务中心的主要功能是对Thrift接口描述语言文件进行管理,管理其发布/订阅关系。实际上,它定义了一种团队间互相协作的方法,此协作遵循面向服务体系结构。在开发实践中,我们不鼓励依赖通过接口描述语言直接生成的代码,鼓励依赖于接口描述语言生成代码,这样能够保证耦合性,减少代码升级所带来的成本。另外,通过管理服务的所有者和服务的订阅者,能够迅速地了解到服务间的依赖关系以及服务演化时所带来的相关影响。 

在商业平台内部有多个业务系统使用分布式RPC框架Polaris,包括资金、计费、客户、财务、合同、物料、报告等,也覆盖了Java、C++、Python等语言,目前已经完成大部分接口的迁移,利用服务中心Aura,构建了完善的服务发布、发现和使用的流程,也针对其安全性、易用性和可维护性做了很多工作,因为有了一致的技术集,连怎么去使用都有了最佳实践,迁移后的服务接口显著减少了重复开发成本,有效地提升了沟通效率,降低了风险。 

常见的分布式 RPC 框架包括 Dubbo、gRPC、Hessian、Thrift 等,它们在不同的使用场景下各有优势和适用性。 ### Dubbo Dubbo 是阿里巴巴开源的一个高性能服务框架,支持多种协议(如 Dubbo 协议、HTTP、RMI 等),并且可以与 Spring 框架无缝集成。它适用于大规模分布式系统,在服务注册、发现、负载均衡等方面提供了完善的支持。Dubbo 适合用于需要高性能和高可用性的微服务架构中,尤其是在国内互联网公司中广泛应用[^4]。 ### gRPC gRPC 是 Google 开发的现代开源高性能 RPC 框架,支持跨平台、跨语言通信。它基于 HTTP/2 协议,具有良好的传输效率和流式通信能力。gRPC 适用于需要跨数据中心通信、服务网格、微服务架构的场景,尤其适合需要高性能和跨语言支持的场景[^4]。 ### Hessian Hessian 是一个轻量级的远程调用框架,基于二进制协议进行通信,相较于基于文本的协议(如 JSON、XML)更加高效。它适用于需要轻量级解决方案、且需要在不同语言之间进行简单通信的场景,特别适合在 HTTP 协议下进行远程调用[^4]。 ### Thrift Apache Thrift 是 Facebook 开源的跨语言 RPC 框架,支持多种编程语言,具有良好的可扩展性和高效的序列化机制。Thrift 适用于需要多语言支持、且对性能有较高要求的分布式系统场景,尤其适合构建企业级服务框架[^4]。 ### RMI(JDK 自带) RMI 是 Java 平台自带的远程调用机制,但其功能较为基础,扩展性较差,适合简单的 Java 服务间通信,但在实际生产环境中较少使用[^4]。 ### 使用场景与最佳实践 - **高性能需求场景**:如金融、电商等需要低延迟、高并发的系统,推荐使用 Dubbo 或 gRPC,它们在性能和稳定性方面表现优异。 - **跨语言通信场景**:如果系统中涉及多种编程语言的交互,gRPC 和 Thrift 是更合适的选择,它们支持多语言,且具有良好的接口定义语言(IDL)机制。 - **轻量级通信场景**:对于需要快速搭建、资源消耗较小的系统,Hessian 是一个不错的选择,尤其适合 HTTP 下的远程调用。 - **服务治理需求场景**:Dubbo 提供了完善的服务注册、发现、负载均衡、容错等机制,适合需要复杂服务治理能力的系统。 ### 示例:Dubbo 简单服务定义 Dubbo 通常结合 Spring 配置文件进行服务定义和注册: ```xml <!-- 提供者配置 --> <dubbo:service interface="com.example.DemoService" ref="demoService" protocol="dubbo" registry="zookeeper://192.168.1.100:2181" /> <!-- 消费者配置 --> <dubbo:reference id="demoService" interface="com.example.DemoService" registry="zookeeper://192.168.1.100:2181" /> ``` ### 示例:gRPC 接口定义(.proto 文件) gRPC 使用 `.proto` 文件定义接口,并通过代码生成器生成客户端和服务端代码: ```proto syntax = "proto3"; package example; service DemoService { rpc SayHello (HelloRequest) returns (HelloResponse); } message HelloRequest { string name = 1; } message HelloResponse { string message = 1; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值