1. 背景
2. RPC原理详解
2.1 RPC调用流程
- RPC框架调用流程中主要有五个对象,客户端(Client)、客户端代理(Client Stub)、网络服务(Network Service)、服务端代理(Service Stub)、服务端(Service)。
- 客户端(Client)作为服务消费方以本地调用方式调用服务。
- 客户端代理(Client Stub)接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体。然后找到服务地址,并将消息发送服务器。
- 服务端代理(Service Stub)将接收到消息后进行解码,Service Stub根据解码结果调用本地服务。
- 反向链路可参考下图流程:
2.2 透明化远程服务调用
- 如何封装通信细节才能让用户像以本地调用方式远程调用服务呢?对java对象来说就是使用代理。
- 代理的方式包括jdk动态代理和字节码生成,大部分公司实现RPC框架时还是选择动态代理。
- RPCProxyClient代理类中invoke方法中封装与远程服务通信的细节。
public class RPCProxyClient implements java.lang.reflect.InvocationHandler{
private Object obj; 、
public RPCProxyClient(Object obj){
this.obj=obj;
}
// 得到被代理对象;
public static Object getProxy(Object obj){
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new RPCProxyClient(obj));
}
// 调用此方法执行
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//结果参数;
Object result = new Object();
// 执行通信相关逻辑
// ...
return result;
}
}
2.3 消息的编码和解码
- 请求消息结构:
- 接口名称:如果不传,服务端就不知道调用哪个接口了;
- 方法名:一个接口内可能有很多方法,如果不传方法服务端也就不知道调用哪个方法;
- 参数类型&参数值:参数类型有很多,比如bool、int、long、double、string、map、list,甚至如Struct(class);以及相应的参数值;
- 超时时间
- requestID, 标识唯一请求ID
- 消息的编解码涉及到序列化框架的选择,目前互联网公司广泛使用Protobuf、Thrift、Avro等成熟的序列化解决方案来搭建RPC框架,这些都是久经考验的解决方案。
- 消息通信方式可以采用java NIO,netty等。我们的自研RPC框架也采用netty框架。
- 消息编码和解码细节可以参考下图
2.4 发布自己的服务
-
如何让别人使用我们的服务,两种办法:
- 1.自动告知,通过zookpeer充当一个服务注册表,让多个服务形成一个集群,让服务消费者通过服务注册表获取具体的服务访问地址(ip+端口)去访问具体的服务提供者。
- 人肉告知,显然这种方式不是很合理。
-
zookpeer的原理参加下图介绍
2.5 Protobuf序列化框架
- 前面RPC框架中提到了选择合适的序列化框架,笔者曾经公司的C端产品使用Protobuf序列化框架,性能很强悍,支撑了公司百万QPS的业务。自研的RPC框架也可使用该序列化框架。
- 这里我们不做过多介绍,细节及使用可以参考下图
3.总结
- 以上我们搞清楚了RPC框架的原理和细节,以及涉及到序列化Protobuf、通信netty等其他框架。
- 后面我们将根据我们介绍的原理和知识点自研一个RPC框架,后面会有系列文章详细介绍。
扫码关注公众号
- 后台回复“Hadoop”、“Hbase”、“Spark”等免费获取更多Hadoop、Hbase、Spark等学习教材及实战资料
|