RPC原理与分析

来源:互联网 发布:java 守护进程 编辑:程序博客网 时间:2024/05/17 01:46

RPC原理与分析

  RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。
       RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

RPC主要应用在分布式系统。如Hadoop生态中hadooop/hbase等中的IPC组件。RPC框架原理是什么呢?

所涉及的模块包括 1、RPC服务器   2、接口    3、实现类   4、服务器提供者模块    5、客户端消费者模块

从下面几个方面思考,仅供参考:

1.通信模型:客户端与服务端通信在Java中一般基于BIO或NIO,HTTP;。

2.过程(服务)定位:使用给定的通信方式,确定具体的目标服务;

3.远程代理对象:本地调用的方法(服务)其实是远程方法的本地代理,因此可能需要一个远程代理对象,对于Java而言,远程代理对象可以使用Java的动态对象实现,封装了调用远程方法调用;

4.序列化,将对象名称、方法名称、参数等对象信息进行网络传输需要转换成二进制传输,这里可能需要不同的序列化技术方案。如:protobuf,avro等。

即:

RPC架构分为三部分:

1)服务提供者,运行在服务器端,提供服务接口定义与服务实现类。

2)服务中心(RPC服务器),运行在服务器端,负责将本地服务发布成远程服务,管理远程服务,提供给服务消费者使用。

3)服务消费者,运行在客户端,通过远程代理对象调用远程服务。



简易实现:

接口定义:Calc.java

package com.rpc;public interface Calc {public int add(int a,int b);public int sub(int a, int b);public int mulitp(int a, int b);public int did(int a, int b);}

接口实现CalcImpl.java

package com.rpc;public class CalcImpl implements Calc { public CalcImpl() {};@Overridepublic int add(int a, int b) {return a+b;}@Overridepublic int sub(int a, int b) {return a-b;}@Overridepublic int mulitp(int a, int b) {return a *b;}@Overridepublic int did(int a, int b) {return a/b;}}
服务接口Server.java

package com.rpc;public interface Server {public void start();public void stop();public void register(Class<?> clz, Class<?> impl); //注册服务public boolean isRunning();}

服务接口实现ServerCenter.java

package com.rpc;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Method;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** * 服务接口实现(服务提供者和服务注册) * @author Administrator * */public class ServerCenter implements Server {private  ExecutorService ExecutorService =null;private Map<String, Class> maps = null;private ServerSocket serverSocket = null;private String ip;private int port;private  boolean isRunnable = false; public ServerCenter(String ip, int port) {ExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*5);maps = new HashMap<String,Class>();try {serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(ip, port));} catch (IOException e) {e.printStackTrace();}this.ip = ip;this.port = port;}@Overridepublic void start() {isRunnable = true;new Thread(new Runnable() {@Overridepublic void run() {while(isRunnable){try {System.out.println("is started ...");Socket socket = serverSocket.accept();ExecutorService.execute(new SocketTask(socket));} catch (IOException e) {e.printStackTrace();}}}}).start();}public class SocketTask implements Runnable{Socket socket = null;ObjectInputStream dis  = null;ObjectOutputStream dos = null;public SocketTask(Socket socket) {System.out.println("socket。。。");this.socket = socket;try {socket.setKeepAlive(true);dis = new ObjectInputStream(socket.getInputStream());dos = new ObjectOutputStream(socket.getOutputStream());System.out.println("dfdf。。");} catch (IOException e) {e.printStackTrace();}}@Overridepublic void run() {try {String serviceName = dis.readUTF();String methodName = dis.readUTF();Class<?>[] paramTypes = (Class[]) dis.readObject();System.out.println(paramTypes[0].getName());Object[] params = (Object[])dis.readObject();System.out.println("serviceName"+serviceName);Class<?> clz = maps.get(serviceName);System.out.println("clz"+clz.getName());System.out.println();System.out.println(serviceName + methodName);Method method = clz.getDeclaredMethod(methodName, paramTypes);Object object = method.invoke(clz.newInstance(), params);dos.writeObject(object);dos.flush();}catch (Exception e) {e.printStackTrace();}}public void stopSocket(){if(socket.isClosed()){try {if(dis != null)dis.close();if(dos != null)dos.close();if(socket != null)dos.close();} catch (IOException e) {e.printStackTrace();}}}}@Overridepublic void stop() {isRunnable = false;try {if(serverSocket != null){serverSocket.close();}} catch (IOException e) {e.printStackTrace();}}@Overridepublic void register(Class<?> clz, Class<?> impl) {if(maps != null)maps.put(clz.getName(), impl);}@Overridepublic boolean isRunning() {return isRunnable;}}



服务请求Client.java

package com.rpc;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.InetSocketAddress;import java.net.Socket;public class Client<T> {@SuppressWarnings("unchecked")public static <T> T getRPCProxy(Class<?> clzz, String ip, int port){ //获得远程动态代理对象return (T)Proxy.newProxyInstance(clzz.getClassLoader(), new Class[]{clzz}, new InvocationHandler() {ObjectInputStream input = null;ObjectOutputStream output = null;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;Socket socket = new Socket();socket.connect(new InetSocketAddress(ip, port));System.out.println("is conn..");if(socket.isConnected())socket.setKeepAlive(true);output = new ObjectOutputStream(socket.getOutputStream());output.writeUTF(clzz.getName());output.writeUTF(method.getName());output.writeObject(method.getParameterTypes());output.writeObject(args);input = new ObjectInputStream(socket.getInputStream());result = input.readObject();return result;}});}}



0 0