RPC调用是现在中大型公司在分布式系统架构、服务治理不可避免需要面对的问题。RPC框架也是各个大厂的必争之地,例如Facebook开源框架Thrift、Google开源框架gRPC、Alibaba开源框架Dubbo。做一个PRC框架并不难,可是构建一个高可用、高性能、可扩展的PRC框架可就是不那么容易了。万丈高楼平地起,我们需要首先了解最基本的概念,才可以更容易理解这些开源框架。所以今天我们开始讨论一下什么是RPC框架。
故事现在正式开始:
今天新来的师弟问我:”师兄,什么是RPC?“
”Remote Procedure Calls,远程过程调用“,我随口一答。
师弟一脸茫然,好像在说“英文我比你好,还用你说?”。我突然意识到这个不是他要的答案,我应该用更容易理解的话来给一个大学刚毕业,还没有任何实战经验的实习生讲述一下什么是RPC。
“远程调用对应的就是本地调用,例如你在超市买苹果,你这个买苹果的动作你自己在执行,可以看作本地调用。”
“突然你的女朋友打电话过来,让你再买几个香蕉。你女朋友没有来执行这个动作,他只是调用你来做,所以你女朋友这个动作就是远程调用。”
“哦,我明白了。就是程序通过网络中某种协议向另外一个计算机请求程序服务,这就是RPC调用。”
“差不多吧。但是PRC也远没有这么简单,你可以...”
故事结束,下面我们就RPC做一下讨论吧。
远程过程调用
如果把事必躬亲定义为本地调用,假手于人定义为远程调用,那我们很容易想到就是B/S架构的http调用,前些年比较热的Web Service,当然还有国内RPC开源框架Dubbo,还有最近比较热的微服务框架Spring Cloud. 我们可以对这些技术分别进行分析:
Http调用
HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议。HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。HTTP协议是应用层协议:
HTTP 协议用于B/S结构(客户端-服务器端)。限制每次连接只能处理一个请求,服务器处理完请求后,响应处理后断开连接。同时HTTP协议是无状态协议,那就是说后续处理依赖前面的信息时,需要重新发起请求。
当然也很容用使用后端代码来执行HTTP调用:
// 指定URL
URL url = new URL(path);
// 获取连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置连接相关的参数
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
conn.setDoOutput(true);
conn.setDoInput(true);
//获取URLConnection对象对应的输出流
PrintWriter out = new PrintWriter(conn.getOutputStream());
当用原生的Http作为远程调用时,调用双方需要线下沟通好协议,这样才可以保证正常的数据解析。如果服务端的数据格式发生变化,调用无法同步感知。后来 Web Servic 出现,制订了标准,从而缓解了这一矛盾。
Web Service
Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。
Web Service 的构建思想是尽量把非核心功能交给其他人去做,自己专注核心功能。自己网站只要能通过网络调用网站的资源就好了。
Web Service是基于HTTP协议进行网络传输的,只是作为一个标准(WSDL),他定义了服务是什么(方法、参数、返回值),在那里(服务的网络地址URL),怎么调(通过什么方式来调用)的标准。WSDL(Web Services Description Language)是一个基于XML的语言,用于描述Web Service及其函数、参数和返回值。
Web Service 除了定义了WSDL标准在规范调用接口外,同时使用了 SOAP 规范(定义消息的XML 格式)、UDDI 规范(介绍所提供的业务和服务的XML文件)。
Web Service 的特点:
- 平台无关;
- 编程语言无关;
- 服务端运维不需要考虑客户端兼容问题;
Web Serive 是基于Http协议的,同时定义了使用XML方式来做信息的交互,所以也有自己的局限性:
- 基于HTTP,每次调用都需要重复建立连接,在高可用、高并发的场景下,效率很难保障;
- 使用SOAP规范的XML传输,传输内容多且复杂,这样传输的效率不高,现在逐渐趋向JSON、字节码方式等简单方式进行传输;
- 在运维层面,服务负载平衡已经水平扩容都能复杂
PRC 框架 Dubbo
当项目较小,域划分简单时,我们重点在建设数据库,远程调用只是辅助,所以无论使用原生Http调用还是使用Web Service 都可以方便快捷的解决问题。当面对大规模、分布式系统来说,我们需要更多的强调高可用、高并发。Dubbo RPC 框架就是在这一背景下产生。
百度百科:
Dubbo 是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。
Dubbo 底层是基于TPC/IP(网络层)来构建的,使用长连接来保证调用的稳定性和性能,同时 Dubbo 主要解决了下面的问题:
- 负载平衡:当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大。 此时需要一个服务注册中心,动态地注册和发现服务,使服务的位置透明。并通过在消费方获取服务提供方地址列表,实现软负载均衡和 Failover,降低对 F5 硬件负载均衡器的依赖,也能减少部分成本
- 服务治理:服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。 这时,需要自动画出应用间的依赖关系图,以帮助架构师理清关系
- 水平扩容:服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
整体 Dubbo 的架构:
节点 | 角色说明 |
---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | Container |
Spring Cloud
随着微服务的理念不断深入Java开发者,对微服务对管控、治理,负载均衡、异步消息等基础设施变得更加迫切。 Spring Boot 框架作为微服务的倡导者,对 Java 周边的成熟的一系列框架进行整合集成,帮助Java开发者便利的使用相关框架。
百度百科:
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
总起来来说,Spring Cloud 整合的项目分两类:成熟框架封装、自主实现了部分基础设施:
项目 | 作用 |
---|---|
Spring Cloud Netflix | 是对Netflix开发的一套分布式服务框架的封装,包括服务的发现和注册,负载均衡、断路器、REST客户端、请求路由等。 |
Spring Cloud Config | 将配置信息中央化保存, 配置Spring Cloud Bus可以实现动态修改配置文件 |
Spring Cloud Bus | 分布式消息队列,是对Kafka, MQ的封装 |
Spring Cloud Security | 对Spring Security的封装,并能配合Netflix使用 |
Spring Cloud Zookeeper | 对Zookeeper的封装,使之能配置其它Spring Cloud的子项目使用 |
Spring Cloud Eureka | Spring Cloud Eureka 是 Spring Cloud Netflix 微服务套件中的一部分,它基于Netflix Eureka 做了二次封装,主要负责完成微服务架构中的服务治理功能 |
Spring Cloud 提供的一整套的应用建设方案,真正和PRC相关的是其封装的 Spring Cloud Netflix。Spring Cloud Netflix 调用也是基于HTTP的,序列化反序列化一般采用的是jackson。
Spring Cloud 对中小企业来说是一种不错的选择。这些企业往往没有精力和资金投入此类基础设施的开发,并且业务并不是特别的复杂,Spring Cloud 这种一站式的解决方案会节省很大的成本。
Http调用和PRC调用区别
广义上我们认为无论是Http调用,Web Service 的调用,Dubbo框架的服务调用,Spring Cloud 下的服务调用都是RPC调用。在狭义上讲,我愿意把RPC调用定义在TPC传输协议上的为RPC调用。
Http调用、Web Service 的调用、Spring Cloud 下的服务调用都是基于HTTP协议的,接口一盘是XML或者是JSON,比较容易理解,开发起来也比较便利。但是对于更为复杂的系统,成千上万级别的系统需要交互时,我们可能更关注稳定性和性能,这是基于网络传输层(TCP)的框架往往会占有优势,因为他可以减少连接握手次数(长链接),从而减少网络开销。
无论哪种方式,为了系统可维护、可运维,都需要一整套的周边设施来帮助,以便可以长期稳定的发展。无论Web Service 提供的 WSDL 标准,Spring Cloud 一整套的微服务治理系统,还是 Dubbo 的服务管理端,都是为了这一目的。
在选择RPC框架时,需要根据自己的项目特点,进行适当的选择,不要为了某项技术而违背了自己的初衷。