目录
前言
Remote Procedure Call,RPC 是一种计算机通信协议,它允许程序在网络上请求服务而不需要了解底层网络细节。
RPC 的基本思想:本地计算机上的客户端程序调用远程服务器上的过程或子程序,就像调用本地过程一样,而不用关心底层网络通信的细节。
RPC 的工作原理/步骤
-
客户端调用:客户端通过本地调用远程服务的方式,就像调用本地方法一样
-
数据序列化:客户端将调用的参数序列化为可以在网络上传输的格式,如二进制流或 JSON
-
网络传输:序列化后的数据通过网络传输到远程服务器
-
数据反序列化:服务器接收到数据后,将其反序列化为原始参数
-
服务端执行:服务器执行相应的过程,并将结果返回
-
结果序列化:服务器将执行结果序列化为可以在网络上传输的格式
-
网络传输:序列化后的结果通过网络传输到客户端
-
结果反序列化:客户端接收到结果后,将其反序列化为最终的返回值
-
客户端接收结果:客户端获得最终的执行结果,完成整个过程
RPC 的优点
-
抽象性:提供了一种高层抽象,使开发者可以像调用本地方法一样调用远程服务,无需关心底层网络通信
-
封装性:隐藏了底层通信细节,提供了类似于本地调用的封装,使得分布式系统开发更为简单
-
效率:相对于其他通信方式,由于数据的二进制传输和更紧凑的协议,RPC 通常更加高效
-
可扩展性:提供了一种扩展服务的机制,可以在不修改客户端代码的情况下添加新的服务或更新服务版本
RPC 的适用场景
-
分布式系统场景:当系统的各个模块分布在不同的服务器上时,RPC 提供了方便的远程调用机制,使得模块间的通信更加简便
-
微服务架构场景:在微服务架构中,各个微服务可能运行在不同的进程或主机上,RPC 提供了一种有效的通信方式,支持微服务之间的远程调用
-
性能要求高场景:RPC 框架通常采用二进制协议和高效的序列化方式,因此在性能要求较高的场景中表现比较优越
-
多语言支持场景:RPC 框架通常支持多种编程语言,使得不同语言编写的模块可以方便地进行远程调用
-
服务治理场景:RPC 框架通常提供服务注册、负载均衡、服务发现等功能,有助于构建健壮的分布式系统
-
接口规范明确场景:RPC 框架通常使用 IDL 或者其他接口描述语言,接口规范明确,便于团队协作和版本管理
总之,RPC 在需要高效、可靠的远程调用和分布式系统通信的场景中具有较强的适用性。
常见 RPC 框架介绍
当前这个技术的“卷”时代,行业内有许多流行的 RPC 框架,每个框架都有其独特的特点和适用场景。
gRPC
gRPC 是 Google 开发的高性能远程服务调用框架,特别适用于构建跨语言、高性能、多服务的分布式系统,尤其在微服务架构中表现优异。
特点
-
跨语言支持:支持多种编程语言,使得不同语言的服务可以无缝协同工作
-
IDL:使用 Protobuf 作为接口定义语言,IDL 可以定义服务和消息格式,提供强大的代码生成工具,使得跨语言的通信变得更加简单
-
HTTP/2 协议:基于 HTTP/2 的传输协议,提供了双向流、头部压缩、多路复用等特性,显著提升了性能和效率
-
多种序列化支持:支持多种序列化格式,包括 Protobuf、JSON、XML 等,可以让开发根据需求选择适当的序列化方式
-
双向流和流控制:支持双向流式通信,可以在同一个连接上同时进行多个请求和响应,同时提供了流控制机制,确保通信的平滑进行
-
服务治理和负载均衡:集成了服务治理和负载均衡的功能,可以通过服务注册发现、负载均衡策略等方式优化服务通信
-
拦截器和中间件:提供了强大的拦截器和中间件机制,允许开发者在请求和响应的生命周期中添加自定义的逻辑,扩展框架功能
-
高度集成的监控和追踪:集成了常见的监控和跟踪工具,如 Prometheus、Zipkin 等,方便开发者对系统进行监测和调试
适用场景
-
跨语言通信:因支持多种编程语言,适用于构建跨语言的分布式系统,特别是在大规模多语言的项目中
-
高性能和效率要求:因基于 HTTP/2 的传输协议和 Protobuf 的序列化格式,使得在性能和效率方面表现出色,适用于对通信性能有高要求的场景
-
微服务架构:因提供了服务治理和负载均衡,使其成为构建可伸缩和可靠的微服务架构的理想选择
-
多语言团队协作:适用于多语言团队协作的场景,可以让不同语言的服务协同工作,提高团队的开发效率
-
流式通信需求:因支持双向流和流控制,适用于需要实时或大规模数据传输的场景,如实时通信、视频流等
Dubbo
Dubbo 是一个强大而灵活的分布式服务框架,适用于构建复杂的分布式系统,尤其在微服务和异构系统继承的场景中表现出色。Alibaba 是主要贡献者。
特点
-
分布式服务治理:提供了全面的分布式服务治理功能,包括服务注册发现、负载均衡、路由、容错、集群管理等,以支持大规模分布式系统
-
多协议支持:支持多种通信协议,包括 Dubbo 协议、HTTP、WebService 等,使得服务可以以不同的方式进行通信,方便集成到不同的系统中
-
多语言支持:Dubbo 用 Java 实现,但它支持多语言的客户端和服务端实现,允许不同语言的服务协同工作
-
高性能和低延迟:Dubbo 在设计上追求高性能和低延迟,采用了多种优化策略,包括基于 Netty 的通信、序列化协议等,以满足对性能要求较高的应用场景
-
可扩展性:框架提供了丰富的扩展点,开发者可以通过自定义扩展点实现特定的需求,使得 Dubbo 具有较强的可扩展性
-
智能负载均衡:支持多种负载均衡策略,包括随机、轮询、一致性哈希等,通过智能的负载均衡机制,优化服务的性能和稳定性
-
服务降级和容错:提供了多种容错机制,如服务降级、失败重试、容错策略等,以提高系统的可用性和鲁棒性
适用场景
-
分布式架构:适用于构建大规模分布式系统,提供完善的服务治理功能,使得服务的注册、发现和管理更加方便
-
微服务架构:Dubbo 被广泛应用于微服务架构中,支持微服务之间的通信协作,通过治理功能优化微服务架构的整体性能
-
异构系统集成:Dubbo 支持多语言,可以用语整合不同语言编写的系统,实现异构系统的集成和协同工作
-
高性能和低延迟要求场景:适用于对性能要求较高、对延迟有严格要求的应用场景,如金融、电商等
-
服务治理场景:对服务治理功能有较高需求的场景,如需求灵活的负载均衡、容错机制等
Finagle
Finagle 是 Twitter 开发的高性能 RPC 框架,特别适用于构建高性能、可伸缩、可靠的分布式系统,尤其是在微服务架构中。
特点
-
异步:基于异步模型设计,支持使用 Future 进行异步编程,能够有效地处理大量并发请求并充分利用系统资源
-
可组合性:可组合性是指可以将多个异步操作组合成更复杂的操作,从而简化了异步编程的复杂性
-
多协议支持:支持多种协议,包括 HTTP、Thrift、Protobuf 等,多协议的支持使其适用于不同领域和服务之间的通信
-
服务治理和负载均衡:内建的服务治理功能,包括服务注册、服务发现、负载均衡等,可以用于构建可靠和可伸缩的微服务架构
-
可插拔的中间件:允许用户添加自定义的中间件来扩展其功能,这种可插拔的机制使得用户能够根据特定需求对框架进行定制
-
统一的监控和追踪:集成了统一的监控和追踪系统,使得用户可以方便地监测和调试分布式系统
-
灵活的连接池管理:提供了灵活的连接池管理机制,可以根据实际需求进行配置和调整,这对于高并发和低延迟的系统至关重要
适用场景
-
分布式系统通信:因异步和可组合,适用于构建大规模的分布式系统,特别是需要高性能和低延迟的通信场景
-
微服务架构:因服务治理和负载均衡功能,适用于构建可靠和可伸缩的微服务架构的理想选择
-
多协议通信:因支持多种协议,适用于不同服务之间的通信,无论是 HTTP RESTful API 还有 Thrift 的服务调用
-
高并发场景:因异步模型和灵活的连接池管理,适用于高并发场景下处理大量请求的系统
-
统一的监控和追踪需求:对于需要集成监控和追踪的系统,提供了统一的解决方案,有助于用户更好地理解和调试系统的运行情况
Thrift
Thrift 是由 Apache 开发的一种跨语言的远程服务调用框架,具有高性能、多语言支持、动态扩展性的特点,适用于构建复杂、异构、性能要求较高的分布式系统。
特点
-
多语言支持:支持多种编程语言,包括但不限于 Java、C++、Python、Go、Ruby 等,使得可以用不同的语言编写的服务相互通信
-
高性能:使用二进制协议进行数据传输,相比于文本协议,提供了更高的性能和更小的数据传输体积。这使得 Thrift 在对性能有要求的场景下表现出色
-
多协议支持:支持多种网络传输协议,包括 TSocket、THttp、TFile 等,以适应不同的网络环境和需求
-
动态扩展性:数据模型支持动态扩展,可以在不修改旧版本代码的情况下向数据模型中添加新的字段,这使得服务的演化更加灵活
-
数据类型丰富:提供了丰富的数据类型,包括基本数据类型、容器类型、自定义结构等,以满足不同数据传输需求
-
代码生成:使用 IDL(接口定义语言)来描述服务接口,通过编译器生成相应语言的代码,简化了服务接口定义和实现的工作
-
支持异步通信:支持异步通信,通过非阻塞的方式进行调用,提高了系统的并发性能
适用场景
-
跨语言服务调用:适用于构建跨语言的分布式系统,支持多语言间的服务调用和协同工作
-
高性能要求:在高性能的数据传输场景下表现出色,适用于对性能要求较高的应用,如大规模分布式系统、实时数据处理等
-
异构系统集成:支持多语言,可用于整合不同语言编写的系统,实现异构系统的集成和协同工作
-
大规模分布式系统:适用于构建大规模分布式系统,支持高性能的服务调用和动态的服务演化
-
数据传输量较大场景:在需要优化数据传输体积、提高传输效率的场景下,Thrift 的二进制协议有一定优势
Motan 1/2
Motan1/2 是由 Sina 微博开发的一款高性能、易扩展的分布式远程服务调用框架。
特点
-
分布式服务治理:提供了完备的分布式服务治理能力,包括服务注册与发现、负载均衡、故障熔断、降级、容错等,帮助构建健壮的分布式系统
-
多协议支持:支持多种网络协议,包括 Motan 自有的 Motan 协议、Thrift 协议、Hessian 协议等,满足不同的需求和环境
-
动态扩展:支持在运行时动态添加和删除服务节点,具有良好的扩展性,适应业务的变化和扩展
-
高性能:在设计上注重性能,通过优化网络传输、序列化和反序列化等环节,提供了较高的性能表现
-
易集成:提供了丰富的集成方式,可以与 Spring、Dubbo 等框架无缝集成,便于现有系统的迁移和升级
-
灵活的配置:支持丰富的配置方式,包括 XML 配置、注解配置等,使得配置更加灵活和可管理
-
可插拔的设计:注重可插拔性,支持自定义的扩展,包括负载均衡、容错策略等,使得用户可以根据需求定制特定的行为
适用场景
-
微服务架构:适用于构建微服务架构,支持服务注册与发现、负载均衡等微服务治理特性
-
分布式系统:适用于构建大规模分布式系统,提供了完善的分布式服务治理和动态扩展机制
-
异构系统集成:多协议支持使其适用于整合不同语言、不同框架编写的系统,实现异构系统的协同工作
-
高性能要求:适用于对性能有较高要求的场景,如需要快速响应和高吞吐量的业务系统
-
易扩展的业务:对于需要频繁变更和扩展的业务,Motan 提供了良好的支持,可以根据业务需求灵活扩展和调整
bRPC
bRPC 是由 Baidu 开发的高性能、通用的 RPC 框架,注重性能、灵活性和可扩展性,适用于 Baidu 内部大规模服务的场景。
特点
-
高性能:采用了一系列性能优化手段,如支持零拷贝、基于 Epoll 的高并发处理、采用 Protobuf 进行高效的序列化等,以提供卓越的性能
-
灵活的负载均衡:支持多种负载均衡策略,包括轮询、随机、一致性哈希等,以适应不同的业务需求
-
多语言支持:提供了 C++ 和 Java 的版本,并且支持跨语言的 RPC 调用,使得不同语言的服务可以无缝通信
-
可扩展性:提供了可插拔的插件机制,可以根据业务需求扩展功能
-
故障转移和容错:具备自动故障转移和容错机制,能够保障系统的稳定性
适用场景
-
百度内部服务:最初是百度内部用于支持大规模分布式服务的,因此在百度的内部服务中得到了广泛应用
-
高性能要求场景:注重性能和低延迟,特别适用于对 RPC 调用性能要求较高的场景,如在线实时计算、广告投放等
-
多语言异构系统:提供了多语言支持,适用于构建多语言异构系统,使得不同语言的服务可以进行高效通信
JSON-RPC 2.0
JSON-RPC 2.0 是一种轻量级的 RPC 协议框架,设计目标是使用简单、易于理解的 JSON 格式进行数据交换,适用于对通信协议要求较为简单、数据交换格式使用 JSON 的场景,特别适合与小型简单的 Web 开发和移动应用开发。
特点
-
基于 JSON 格式:使用 JSON 作为数据交换的格式,JSON 是一种轻量级的数据交换格式,易于阅读、编写和解析
-
简洁和轻量级:相对于其他 RPC 协议,JSON-RPC 2.0 的协议设计相对简单,保持了轻量级的特性
-
支持批处理:支持批处理请求,客户端可以将多个请求发送到服务器,并一次性接收多个响应,减少通信开销
-
协议无关性:与具体的传输协议无关,可以在多种网络协议上使用,例如 HTTP、WebSocket 等
-
错误处理:提供了统一的错误处理机制,通过错误对象可以清晰地了解错误的原因
适用场景
-
Web 应用开发:使用 JSON 格式,很适合在 Web 开发中进行前后端之间的远程调用
-
移动应用开发:对于移动应用,轻量级的 JSON-RPC 2.0 协议有助于减小数据传输的开销
-
微服务架构:在微服务体系结构中,不同服务之间的通信可以使用 JSON-RPC 2.0 进行简便的远程调用
-
跨语言通信:协议设计简单,易于实现,可以在不同编程语言之间进行跨语言的远程调用
Tips
如何选择合适的 RPC 框架
在实际应用研发的具体场景中,面对这么多的 RPC 框架,我们应该如何选择呢?从个人多年的经验来看,在选择一个 RPC 框架的时候,主要考虑以下几个方面因素:
项目需求和规模
不同的 RPC 框架适用于不同规模和需求的项目。对于小型项目,可以选择简单易用的框架,而对于大型分布式系统,则需要考虑更加强大和灵活的框架
语言支持
确保选择的框架支持项目中所使用的编程语言。一些框架可能对某些语言提供更好的支持,而另一些框架可能具有更广泛的语言覆盖范围
性能和扩展性
考虑框架的性能和扩展性是否满足项目的需求。一些框架可能在性能上表现更好,而另一些可能更适合需要大量扩展性的场景
社区和生态
查看框架的社区活跃程度和生态系统是否完善。有一个强大的社区通常意味着更好的支持和更新,同时丰富的生态系统可以提供更多的工具和插件
学习成本
考虑团队成员对于框架的学习成本。选择一个团队熟悉或者容易学习的框架能够提高开发效率
公司技术栈
如果公司或团队已经在使用某个 RPC 框架,并且取得了良好的经验,那么继续沿用该框架可能是更为明智的选择
可维护性和调试便捷性
考虑框架是否提供良好的调试工具和可维护性。这在项目的长期演进和维护过程中尤为重要
安全性
对于一些安全性要求较高的项目,需要考虑框架是否提供了足够的安全机制和特性