1. 什么是RPC?
RPC(Remote Procedure Call):远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。在OSI网络通信模型中,RPC跨越了传输层和应用层,用以满足分布式系统架构中不同的系统之间的远程通信和相互调用。简单来说,计算机 A 上的进程,远程调用计算机 B 上的进程,此时 A 上的调用进程被挂起,而 B 上的被调用进程开始执行,当值返回给 A 时,A 进程继续执行。调用方可以通过使用参数将信息传送给被调用方,通过传回的结果得到信息。这一过程,对于开发人员来说是透明的。
由于各服务部署在不同机器上,要想在服务间进行远程调用免不了网络通信过程,服务消费方每调用一个服务都要写一堆网络通信相关的代码,不仅复杂而且极易出错。如果有一种方式能让我们像调用本地服务一样调用远程服务,而让调用者对网络通信这些细节透明,那么将大大提高生产力,比如服务消费方在执行orderService.buy(“HHKB键盘”)时,实质上调用的是远端的服务。这种方式其实就是RPC。而提供了这种功能的工具我们称之为RPC框架。
在RPC框架中主要有三个角色:Provider、Consumer和Registry。
服务提供方 Provider 启动后主动向注册中心 Registry 注册机器IP、port以及提供的服务列表;
服务消费方 Consumer 启动时向注册中心 Registry 获取服务提供方地址列表,可实现软负载均衡和Failover。
2. 实现RPC需要用到的技术
一个成熟的RPC框架需要考虑的问题有很多,这里只介绍实现一个远程调用需要用到的基本技术,感兴趣的朋友可以找一些开源的RPC框架代码来看下。
动态代理
生成 client stub 和 server stub 需要用到Java 动态代理技术,我们可以使用JDK原生的动态代理机制,可以使用一些开源字节码工具框架 如:CgLib、Javassist等。
序列化
为了能在网络上传输和接收 Java对象,我们需要对它进行序列化和反序列化操作。
可以使用Java原生的序列化机制,但是效率非常低,推荐使用一些开源的、成熟的序列化技术,例如:protobuf、Thrift、hessian、Kryo、Msgpack
NIO
当前很多RPC框架都直接基于netty这一IO通信框架,比如阿里巴巴的HSF、dubbo,Hadoop Avro,推荐使用 Netty 作为底层通信框架。
服务注册中心
可选技术: Redis、Zookeeper、Consul、Etcd。
3. RPC和Web Service的区别
- Client stub:存放服务端的地址消息,再将客户端的请求参数打包成网络消息,然后通过网络远程发送给服务方。
- Server stub:接收客户端发送过来的消息,将消息解包,并调用本地的方法。
Web Service接口就是RPC中的stub组件,规定了server能够提供的服务(web service),这在server和client上是一致的,但是也是跨语言跨平台的。同时,由于web service规范中的WSDL文件的存在,现在各平台的web service框架,都可以基于WSDL文件,自动生成web service接口 。
在接口不多、系统与系统交互较少的情况下,利用HTTP协议进行传输。接口可能返回一个JSON字符串或者是XML文档,然后客户端再去处理这个返回的信息。但是对于大型企业来说,内部子系统较多、接口非常多的情况下,RPC框架的好处就显示出来了,首先就是长链接,不必每次通信都要使用三次握手建立连接,减少了网络开销;其次就是RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。