RPC是指远程过程调用,直观说法就是A通过网络调用B的过程方法。

也就是说两台serverA。B,一个应用部署在Aserver上,想要调用Bserver上应用提供的函数/方法,因为不在一个内存空间,不能直接调用。须要通过网络来表达调用的语义和传达调用的数据。

为什么RPC呢?就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完毕的需求,比方比方不同的系统间的通讯,甚至不同的组织间的通讯。因为计算能力须要横向扩展。须要在多台机器组成的集群上部署应用


  1. 首先要解决寻址的问题,也就是说,Aserver上的应用怎么告诉底层的RPC框架。Bserver的IP。以及应用绑定的端口,还有方法的名称,这样才干完毕调用
  2. 方法的參数须要通过底层的网络协议如TCP传递到Bserver,因为网络协议是基于二进制的,内存中的參数的值要序列化成二进制的形式
  3. 在Bserver上完毕寻址后。须要对參数进行反序列化。恢复为内存中的表达方式。然后找到相应的方法进行本地调用,然后得到返回值。
  4. 返回值还要发送回serverA上的应用,也要经过序列化的方式发送,serverA接到后。再反序列化,恢复为内存中的表达方式,交给应用

RpcFramework

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
/**
* RpcFramework
*/
public class RpcFramework { /**
* 暴露服务
*
* @param service
* 服务实现
* @param port
* 服务端口
* @throws Exception
*/
public static void export(final Object service, int port) throws Exception {
if (service == null)
throw new IllegalArgumentException("service instance == null");
if (port <= 0 || port > 65535)
throw new IllegalArgumentException("Invalid port " + port);
System.out.println("Export service " + service.getClass().getName() + " on port " + port);
ServerSocket server = new ServerSocket(port);//前面都是验证调用是否符合规则,这里在被调用端开一个服务。以下就是死循环执行。
for (;;) {
try {
final Socket socket = server.accept();
new Thread(new Runnable() {//对每个请求new一个线程,匿名类
@Override
public void run() {
try {
try {
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
try {
String methodName = input.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
Object[] arguments = (Object[]) input.readObject();
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());//接收client传来的方法名、參数类型、參数
try {
Method method = service.getClass().getMethod(methodName, parameterTypes);//在本地生成相应的方法,
Object result = method.invoke(service, arguments);//调用
output.writeObject(result);//返回结果
} catch (Throwable t) {
output.writeObject(t);
} finally {
output.close();
}
} finally {
input.close();
}
} finally {
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 引用服务
*
* @param <T>
* 接口泛型
* @param interfaceClass
* 接口类型
* @param host
* server主机名
* @param port
* server端口
* @return 远程服务
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {
if (interfaceClass == null)
throw new IllegalArgumentException("Interface class == null");
if (!interfaceClass.isInterface())
throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!");
if (host == null || host.length() == 0)
throw new IllegalArgumentException("Host == null!");
if (port <= 0 || port > 65535)
throw new IllegalArgumentException("Invalid port " + port);
System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);
return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<? >[] { interfaceClass },
new InvocationHandler() {//用动态代理的方法进行包装,看起来是在调用一个方法,事实上在内部通过socket通信传到server。并接收执行结果
public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {
Socket socket = new Socket(host, port);
try {
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
try {
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(arguments);
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
try {
Object result = input.readObject();
if (result instanceof Throwable) {
throw (Throwable) result;
}
return result;//返回结果
} finally {
input.close();
}
} finally {
output.close();
}
} finally {
socket.close();
}
}
});
} }

RpcProvider


public class RpcProvider {
public static void main(String[] args) throws Exception {
HelloService service = new HelloServiceImpl();
RpcFramework.export(service, 1234);
}
}

RpcConsumer


public class RpcConsumer {
public static void main(String[] args) throws Exception {
HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 1234);
for (int i = 0; i < Integer.MAX_VALUE; i++) {
String hello = service.hello("World" + i);
System.out.println(hello);
Thread.sleep(1000);
}
}
}

RPC远程调用概念 &amp;&amp; demo实例的更多相关文章

  1. 从0到1:全面理解RPC远程调用

    上一篇关于 WSGI 的硬核长文,不知道有多少同学,能够从头看到尾的,不管你们有没有看得很过瘾,反正我是写得很爽,总有一种将一样知识吃透了的错觉. 今天我又给自己挖坑了,打算将 rpc 远程调用的知识 ...

  2. Openstack Nova 源码分析 — RPC 远程调用过程

    目录 目录 Nova Project Services Project 的程序入口 setuppy Nova中RPC远程过程调用 nova-compute RPC API的实现 novacompute ...

  3. 測试JSON RPC远程调用(JSONclient)

    #include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSonclient Auth ...

  4. 使用Socket&反射&Java流操作进行方法的远程调用(模拟RPC远程调用)

    写在前面 阅读本文首先得具备基本的Socket.反射.Java流操作的基本API使用知识:否则本文你可能看不懂... 服务端的端口监听 进行远程调用,那就必须得有客户端和服务端.服务端负责提供服务,客 ...

  5. rpc远程调用开发

    RPC即远程过程调用,适用于集群管理,集群节点就是RPCServer,而我们发起远程调用的web服务器就是RPCClient.所以是少数rpcClient(可能一个)对多个RPCServer(集群节点 ...

  6. dubbo集成zookeeper rpc远程调用

    注:下面使用dubbo依赖的是zookeeper注册中心,这里没有详细的介绍.在配置之前,请自行准备好zookeeper环境. 后续如果写zookeeper的配置会补放链接 添加Gradle依赖 co ...

  7. RabbitMQ学习之基于spring-rabbitmq的RPC远程调用

    http://blog.csdn.net/zhu_tianwei/article/details/40920985 spring-rabbitmq中实现远程接口调用,主要在com.rabbitmq.s ...

  8. netcore 基于 DispatchProxy 实现一个简单Rpc远程调用

    前言 netcore 发布以来,一直很关注netcore的进程.目前在公司负责的网站也历经波折的全部有.net framework 4.0 全部切换到netcore 2.2 版本中.虽然过程遇到的坑不 ...

  9. 详解RPC远程调用和消息队列MQ的区别

    PC(Remote Procedure Call)远程过程调用,主要解决远程通信间的问题,不需要了解底层网络的通信机制. RPC框架 知名度较高的有Thrift(FB的).dubbo(阿里的). RP ...

随机推荐

  1. 显卡、显卡驱动、CUDA、cuDNN之间的关系

    作者:冬瓜哥链接:https://www.zhihu.com/question/59184480/answer/166167659来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  2. 用Eclipse开发Androd应用程序时,自带虚机模拟器太慢了,怎么办

    问:用Eclipse开发Androd应用程序时,系统自带模拟器太慢了,怎么办? 答:用Genymotin

  3. tensorflow报错屏蔽的方法

    之前是报这样的错: OpKernel ('op: "BestSplits" device_type: "CPU"') for unknown op: BestS ...

  4. solr高亮设置以及摘要

    高亮显示 public SolrDocumentList query(String str) { SolrQuery query = new SolrQuery(str); //设置高亮,以下两种方式 ...

  5. Spring Boot Maven Plugin打包异常及三种解决方法:Unable to find main class

    [背景]spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringBootApplication注解(或者另一种情形:你有两个main方法并且所在类都没 ...

  6. ztree默认自动打开第一级

    var treeObj = $.fn.zTree.getZTreeObj("tree"); var nodes = treeObj.getNodes(); if (nodes.le ...

  7. 由易信界面——谈谈fragment 状态的保存

    看看我要实现的效果: 其实,这种左右界面切换保存布局方式,不只是易信界面这么用罢了.这更是大多数app布局的主流,而在android平台上面,随着谷歌大力推荐fragment的使用,用fragment ...

  8. 平均值(Mean)、方差(Variance)、标准差(Standard Deviation) (转)

    http://blog.csdn.net/xidiancoder/article/details/71341345 平均值 平均值的概念很简单:所有数据之和除以数据点的个数,以此表示数据集的平均大小: ...

  9. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(二)安装hadoop2.9.0

    如何搭建配置centos虚拟机请参考<Kafka:ZK+Kafka+Spark Streaming集群环境搭建(一)VMW安装四台CentOS,并实现本机与它们能交互,虚拟机内部实现可以上网.& ...

  10. guns使用注意问题

    guns使用注意问题 1,创建的表必须有注释,这样自动生成代码有标题: 2,必须先构建好结构,后期修改主菜单会产生异常的结构影响: 3,修改菜单编号容易产生异常问题: 4,如果没有id,不会自动生成增 ...