RPC框架
总体思路


RPC核心原理
- 客户端client:调用远程方法
- 客户端Stub:一个代理类,将客户端调用的方法、类、方法参数等信息传递到服务端。
- 网络传输:将调用的方法的信息比如说参数等传输到服务端,然后服务端执行完之后再把返回结果通过网络传输会客户端。网络传输方法有很多种,比如socket、Netty等。
- 服务端Stub:接收到客户端执行方法的请求后,取指定的方法然后返回结果给客户端的类。
- 服务端:提供远程方法的一端。
常见RPC框架
Dubbo、Motan、gRPC、Thrift
如何设计一个RPC框架
一般情况下,RPC框架不仅要提供服务发现功能,还要提供负载均衡、容错等功能。
服务提供端Server向注册中心注册服务,服务消费者Client通过注册中心拿到服务相关信息,然后再通过网络请求服务提供端Server。
下面是一个完整的RPC框架示意图:
注册中心
可以使用Zookeeper、Nacos甚至是Redis。
注册中心负责服务地址的注册和查找,相当于目录服务。服务端启动的时候将服务名称以及对应的地址(ip+port
)注册到注册中心,服务消费端根据服务名称找到对应的服务地址。有了服务地址之后,服务消费端就可以通过网络请求服务端了。
网络传输
发送网络请求来传递目标类和方法的信息以及方法的参数等数据到服务提供端。
网络传输的具体实现可以使用Socket(阻塞IO、性能低并且功能单一)、Netty。
Netty是一个基于NIO的client-server框架,使用它可以快速开发网络应用程序。
序列化和反序列化
因为在网络传输数据必须是二进制的。Java对象没办法直接在网络中传输。
为了能让Java对象在网络中传输,需要将其序列化为二进制的数据。最终需要的还是Java对象,因此还需要把二进制的数据“解析”为目标Java对象,也就是对二进制数据进行一次反序列化。
不仅网络传输的时候需要序列化和反序列化,将对象存储到文件、数据库等场景都需要用到序列化和反序列化。
常用的序列化有hessian、kryo、protostuff。
动态代理
使用动态代理来屏蔽远程方法调用的底层细节。简单来说,在调用远程方法的时候,实际会通过代理对象来传输网络请求。
负载均衡
负载均衡为了避免单个服务器响应同一个请求,容易造成服务器宕机、崩溃等问题。
传输协议
设计一个私有的RPC协议,定义需要传输那些类型的数据,并且还会规定每一种类型的数据应该占多少字节。这样我们在接收到二进制数据之后,就可以正确的解析出我们需要的数据。
序列化协议对应与TCP/IP哪一层
在OSI七层协议中,序列化和反序列化是表示层的工作,相对在TCP/IP中,就是对用于应用层的一部分。
Socket网络通信
Socket网络通信过程如下:
Socket网络通信步骤如下:
- 建立服务端并且监听客户端请求
- 客户端请求,服务端和客户端建立连接
- 两端之间可以传递数据
- 关闭资源

