RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP/IP或UDP,为通信程序之间携带信息数据。RPC将原来的本地调用转变为调用远端的服务器上的方法,给系统的处理能力和吞吐量带来了近似于无限制提升的可能。在OSI网络通信模型中,RPC跨域了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
大白话一点,rpc对程序员朋友是透明的。你可以像调用本地方法一样调用远端方法,是两个JVM程序之间的信息交互。无论是本地方法还是远端方法,你直接用就可以了, 如果是远端方法剩下的交给RPC。
-
RPC作用:
- 进程间通讯
- 提供和本地调用一样的调用机制
- 屏蔽掉远程调用的细节实现
-
在spring中接口的调用是通过动态代理实现的,RPC自然也是。对JAVA来说调用方式有两种:
- JDK动态代理
- cglib代理
尽管cglib代理的实现更为强大和高效,cglib可以不需要接口类,jdk动态代理必须要有接口类,但是在使用时还是首选jdk动态代理,因为接口类肯定会提供的。cglib的代码不易维护。
-
调用流程
调用流程.png -
调用步骤:
- 服务方暴露服务,并提供调用地址
- 服务消费方以调用本地方法的方式调用服务
- 接收到请求后,将方法,参数组装成能够进行消息传输的消息体
- 找到服务地址,并将消息发送到服务端
- server收到消息后进行解码
- 根据解码结果调用本地服务
- 本地服务执行,并将服务执行结果发送给消费方
- 消费方收到消息后子进行解码,得到执行的结果
-
常用的分布式rpc:
- dubbo , motan ,rpcx , grpc , thrift等
下面手撕代码
- 既然是调用远端服务,那么就必须在远端暴露一个服务,并提供调用地址,使用ServerSocker 来实现。
- 服务端暴露后,来写本地的动态代理方法,在本地调用时是通过动态代理来将请求转发到远端服务。
- 接口
public interface HelloRpc {
public String helloRpc(String args);
String hellRpc(String arg1, String arg2);
}
- 实现类
public class HelloRpcImpl implements HelloRpc {
@Override
public String helloRpc(String args) {
return "HelloRPC : ---- " + args;
}
@Override
public String hellRpc(String arg1, String arg2) {
return "arg1 : " + arg1 + "args2:" + arg2;
}
}
- 服务发布:
public static void main(String[] args) throws IOException {
HelloRpcImpl helloRpc = new HelloRpcImpl();
RpcFrame.server(helloRpc , 80);
}
- 消费调用:
public static void main(String[] args) {
HelloRpc o = (HelloRpc) RpcFrame.helloRpc(HelloRpc.class, "127.0.0.1", 80);
String hello = o.hellRpc("client !" , "verygood!");
System.out.println(hello);
}
上面只是模拟rpc的实现方式,写的一段代码,市面上的rpc也不是这样搭建的。不过核心思想还是相同的。 但就dubbo而言,暴露的服务是要注册到zk上的,消费方如果需要某个服务,回去zk上查找,并在本地缓存。
- rpc与队列对比
- 既然是两个服务之间的交互,为什么不用队列?
- 队列是异步化的,对于同步返回的需求是没法满足的
- rpc既可以做同步,也可以做异步
网友评论