RPC入门(一):RPC java代码简单实现
来源:互联网 发布:易语言qq空间秒赞源码 编辑:程序博客网 时间:2024/05/19 02:25
1.RPC概念
全程 Remote Procedure Call Protocol 即远程调用协议。它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。(来自百度百科)
(图片来源:互联网)
- 服务消费方(client)调用以本地调用方式调用服务;
- client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
- client stub找到服务地址,并将消息发送到服务端;
- server stub收到消息后进行解码;
- server stub根据解码结果调用本地的服务;
- 本地服务执行并将结果返回给server stub;
- server stub将返回结果打包成消息并发送至消费方;
- client stub接收到消息,并进行解码;
- 服务消费方得到最终结果。
如上图:如果client调用sayHello()方法,给人的感觉就像在调用本地方法一样,执行方法---返回数据。RPC屏蔽了底层通信、协议处理,让调用者不用关心具体实现的细节。
2.RPC框架组成
从上图中我们知道RPC框架需要从下面几方面考虑:
- 通信模型:服务消费方消费服务提供方提供的服务时,需要进行通信?通信一般采用TCP/UDP 或者 HTTP。
- 服务定位:客户端该怎么找到服务提供方的服务?一般通过:IP、端口、具体方法名。
- 远程对象代理:消费方如何调用RPC服务?实际上是通过远程方法的本地代理实现调用的。
- 序列化:调用时如何传递数据?我们知道底层通信都是传输的字节流,因此我们需要将传递的对象序列化进行传输。
3.RPC框架的JAVA的简单实现
- 通信模型:我们可以采用java的BIO或者NIO实现tcp连接。
- 服务定位:我们只是简单实现直接写死 端口 和 ip,不去实现发现服务。
- 远程对象代理:java中可以实现字节码或者动态代理实现。
- 序列化:java原生序列化实现。
rpc-interface:服务接口定义。
rpc-provider:服务提供者,实现服务接口,依赖interface。
rpc-client: 服务消费方,依赖interface。
3.1 接口定义
package cc.hu.test.rpc.facade;public interface HelloRPCService {String sayHello(String name);}
3.2:服务提供
服务接口实现:
package cc.hu.test.rpc.provider.impl;import cc.hu.test.rpc.facade.HelloRPCService;public class HelloRPCServiceImpl implements HelloRPCService {@Overridepublic String sayHello(String name) {return "Hi, RPC I want " + name;}}
package cc.hu.test.rpc.provider;public interface RPCProvider {/**停止服务*/void stop();/**启动RPC服务*/void start();/**获得服务端口*/int getPort();/**注册服务*/void regist(Class<?> serviceInterface, Class<?> serviceImpl);boolean isRunning();}
package cc.hu.test.rpc.provider;import java.io.IOException;import java.net.ServerSocket;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class RPCProviderImpl implements RPCProvider {//private static ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());//使用线程池private static Map<String, Class<?>> SERVICE_MAP = new HashMap<String, Class<?>>();private boolean isStop = false;private static int port = 28080;public static Class<?> getServiceClass(String serviceName) {return SERVICE_MAP.get(serviceName);}@Overridepublic void stop() {this.isStop = true;}@Overridepublic void start() {ServerSocket serverSocket = null;try {serverSocket = new ServerSocket(port);System.out.println("开启RPC测试服务@" + String.valueOf(port));while (!isStop) {Thread t = new Thread(new RPCProviderHandler(serverSocket.accept()));//每一次调用新建一个线程t.start();//exec.execute(new RPCProviderHandler(serverSocket.accept()) );//使用线程池}} catch (IOException e) {e.printStackTrace();} finally {if (null != serverSocket)try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}@Overridepublic int getPort() {return port;}@Overridepublic void regist(Class<?> serviceInterface, Class<?> serviceImpl) {SERVICE_MAP.put(serviceInterface.getName(), serviceImpl);}@Overridepublic boolean isRunning() {return !isStop;}}
package cc.hu.test.rpc.provider;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.Socket;public class RPCProviderHandler implements Runnable {Socket socket;public RPCProviderHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {ObjectInputStream input = null;ObjectOutputStream output = null;try {input = new ObjectInputStream(socket.getInputStream());String serviceName = input.readUTF();String methodName = input.readUTF();Class<?>[] parameterTypes = (Class<?>[]) input.readObject();Object[] parameters = (Object[]) input.readObject(); Class<?> serviceImpl = RPCProviderImpl.getServiceClass(serviceName);//获取实现类if (null == serviceImpl)throw new ClassNotFoundException(serviceName);Method method = serviceImpl.getMethod(methodName, parameterTypes);//获取调用方法String result = (String) method.invoke(serviceImpl.newInstance(), parameters);//将执行调用后的结果输出output = new ObjectOutputStream(socket.getOutputStream());output.writeObject(result);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} finally {try {if (output != null) {output.flush();output.close();}if (input != null)input.close();if (socket != null)socket.close();} catch (IOException e) {e.printStackTrace();}}}}服务Main:
package cc.hu.test.rpc.provider;import cc.hu.test.rpc.facade.HelloRPCService;import cc.hu.test.rpc.provider.impl.HelloRPCServiceImpl;/** * RPC * */public class App { public static void main( String[] args ) { RPCProvider provider = new RPCProviderImpl(); provider.regist(HelloRPCService.class, HelloRPCServiceImpl.class);//注册rpc服务 provider.start();//启动服务端 }}
3.3 消费方:
消费方代理实现:
package cc.hu.test.rpc.client;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.Socket;public class RPCClient<T> {@SuppressWarnings("unchecked")public static <T> T getRemoteProxyObj(final Class<?> serviceInterface, final int port, final String address) {return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class<?>[]{serviceInterface}, new InvocationHandler() {@SuppressWarnings("resource")@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Socket socket = null;ObjectInputStream input = null;ObjectOutputStream output = null;socket = new Socket(address, port);output = new ObjectOutputStream(socket.getOutputStream());output.writeUTF(serviceInterface.getName());output.writeUTF(method.getName());output.writeObject(method.getParameterTypes());output.writeObject(args);input = new ObjectInputStream(socket.getInputStream());String callRet = (String) input.readObject();return callRet;}});}}
消费方main
package cc.hu.test.rpc.client;import java.io.IOException;import cc.hu.test.rpc.facade.HelloRPCService;/** * Hello world! * */public class App { public static void main( String[] args ) { HelloRPCService service = RPCClient.getRemoteProxyObj(HelloRPCService.class, 28080, "192.168.2.62"); byte[] buffer = new byte[512]; try { System.out.print("请输入任意字符:");System.in.read(buffer);String name = new String(buffer);System.out.println(service.sayHello(name));} catch (IOException e) {e.printStackTrace();} }}
只是简单模拟RPC调用,没有考虑重连、性能、服务发现、注册中心等机制。
阅读全文
0 0
- RPC入门(一):RPC java代码简单实现
- 简单的RPC java实现
- 简单的RPC java实现
- 简单的RPC java实现
- 简单的RPC java实现
- 一个简单RPC,java实现
- Java实现一个简单的RPC框架(一) 本地调用
- 基于Netty的RPC简单框架实现(一):RPC客户端
- foolscap实现rpc(一)
- RPC入门总结(一)RPC定义和原理
- 一个简单的rpc框架实现(一)
- 使用Akka实现一个简单的RPC框架(一)
- RPC服务框架(二) 简单RPC实现
- Java实现简单的RPC调用(基于TCP协议)
- 简单层RPC应用的Java实现
- 非常有用:简单的RPC java实现
- RPC(远程过程调用) JAVA简单实现
- Java实现简单的RPC框架
- 羊皮卷之十
- [LeetCode] 47. Permutations II
- FusionCompute (虚拟化引擎)-简单概述
- 图像滤波----高斯滤波/中值滤波/均值滤波
- wireshark学习
- RPC入门(一):RPC java代码简单实现
- anaconda安装opencv
- 《剑指offer》笔记-第4章(3)
- 结构体排序
- JavaScript基础第二章
- 杭电acm 2539点球大战(简单字符串)
- 由重建二叉树算法题到临时对象不能绑定到非 const 的左值引用
- JDBC连接超级标准模板
- 10305