zoukankan      html  css  js  c++  java
  • hadoop17---RPC和Socket的区别

    RPC是在Socket的基础上实现的,它比socket需要更多的网络和系统资源。RPC(Remote Procedure Call,远程过程调用)是建立在Socket之上的,出于一种类比的愿望,在一台机器上运行的主程序,可以调用另一台机器上准备好的子程序,就像LPC(本地过程调用).

    简单RPC之Socket实现

    最近看到Dubbo大神写得使用Socket实现的简单的RPC调用,对RPC的理解更简单了,然后根据大神的代码自己也重构了一下。

    RPC Server端代码,主要是使用ServerSocket获得rpc调用客户端发送过来的类信息,方法信息及方法参数信息,通过反射在RPCServer端进行代码执行,最后将执行结果发送给Socket,第一步需要首先执行RPCServer。

    [java] view plain copy
     
    1. import java.io.IOException;  
    2. import java.io.ObjectInputStream;  
    3. import java.io.ObjectOutputStream;  
    4. import java.lang.reflect.InvocationTargetException;  
    5. import java.lang.reflect.Method;  
    6. import java.net.ServerSocket;  
    7. import java.net.Socket;  
    8. import java.util.concurrent.ConcurrentHashMap;  
    9. /** 
    10.  * 服务端 
    11.  * @author tianjunwei 
    12.  */  
    13. public class RPCServer {  
    14.   
    15.     public static ConcurrentHashMap<String, Object> classMap = new ConcurrentHashMap<String,Object>();  
    16.       
    17.     public static void main(String [] args) throws Exception{  
    18.         System.err.println("server start");  
    19.         RPCServer.invoker(8080);  
    20.     }  
    21.     public static void invoker(int port) throws Exception{  
    22.           
    23.         ServerSocket server = new ServerSocket(port);  
    24.         for(;;){  
    25.                 try{  
    26.                     final Socket socket = server.accept();  
    27.                     new Thread(new Runnable() {  
    28.                         ObjectOutputStream output =  null;  
    29.                         @Override  
    30.                         public void run() {  
    31.                             try{  
    32.                                 try {  
    33.                                     output = new ObjectOutputStream(socket.getOutputStream());   
    34.                                     ObjectInputStream input = new ObjectInputStream(socket.getInputStream());  
    35.                                     String className = input.readUTF();  
    36.                                     String methodName = input.readUTF();  
    37.                                     Class<?>[] parameterTypes = (Class<?>[])input.readObject();    
    38.                                     Object[] arguments = (Object[])input.readObject();    
    39.                                     Object claszz = null;  
    40.                                     if(!classMap.containsKey(className)){  
    41.                                         try {  
    42.                                             claszz = Class.forName(className).newInstance();  
    43.                                             classMap.put(className, claszz);  
    44.                                         } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {  
    45.                                             e.printStackTrace();  
    46.                                         }  
    47.                                     }else {  
    48.                                         claszz = classMap.get(className);  
    49.                                     }  
    50.                                     Method method = claszz.getClass().getMethod(methodName, parameterTypes);    
    51.                                     Object result = method.invoke(claszz, arguments);    
    52.                                     output.writeObject(result);    
    53.                                 } catch (IOException | ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {  
    54.                                     output.writeObject(e);  
    55.                                 }finally {  
    56.                                     output.close();  
    57.                                 }  
    58.                             }catch(Exception e){  
    59.                                 e.printStackTrace();  
    60.                             }finally {  
    61.                                 try {  
    62.                                     socket.close();  
    63.                                 } catch (IOException e) {  
    64.                                     e.printStackTrace();  
    65.                                 }  
    66.                             }  
    67.                         }  
    68.                     }).start();  
    69.             }catch (Exception e) {  
    70.                 e.printStackTrace();  
    71.             }  
    72.         }  
    73.     }  
    74. }  

    RPC 客户端代码,这里利用了代理机制的特性,在执行具体的方法时执行远程调用,执行方法时会调用invoke方法,这样就可以通过Socket向RPCServer发送需要执行的方法的信息,并且获取执行后的结果并返回。
    [java] view plain copy
     
    1. public class RPCProxy {  
    2.       
    3.      @SuppressWarnings("unchecked")  
    4.     public static <T> T create(Object target){  
    5.            
    6.          return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler(){  
    7.   
    8.             @SuppressWarnings("resource")  
    9.             @Override  
    10.             public Object invoke(Object proxy, Method method, Object[] args)  
    11.                     throws Throwable {  
    12.                  Socket socket = new Socket("localhost", 8080);  
    13.                  ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());    
    14.                  try {    
    15.                      output.writeUTF(target.getClass().getName());  
    16.                      output.writeUTF(method.getName());    
    17.                      output.writeObject(method.getParameterTypes());    
    18.                      output.writeObject(args);    
    19.                      ObjectInputStream input = new ObjectInputStream(socket.getInputStream());    
    20.                      try {    
    21.                          Object result = input.readObject();    
    22.                          if (result instanceof Throwable) {    
    23.                              throw (Throwable) result;    
    24.                          }    
    25.                          return result;    
    26.                      } finally {    
    27.                          input.close();    
    28.                      }    
    29.                  } finally {    
    30.                      output.close();    
    31.                      socket.close();  
    32.                  }    
    33.             }  
    34.                
    35.          });  
    36.      }  
    37. }  

    HelloRpc接口:

    [java] view plain copy
     
    1. public interface HelloRpc {  
    2.     String hello(String name);  
    3. }  
    HelloRpcImpl实现类:
    [java] view plain copy
     
    1. public class HelloRpcImpl implements HelloRpc {  
    2.   
    3.     @Override  
    4.     public String hello(String name) {  
    5.         return "hello "+name;  
    6.     }  
    7.   
    8. }  

    Main函数操作:
    [java] view plain copy
     
    1. public class Main {  
    2.   
    3.     public static void main(String [] args){  
    4.         HelloRpc helloRpc = new HelloRpcImpl();  
    5.         helloRpc = RPCProxy.create(helloRpc);  
    6.         System.err.println(helloRpc.hello("rpc"));  
    7.     }  
    8. }  
    执行结果:

    hello rpc

    通过以上这个示例我们可能会对一些RPC框架的实现原理有一定的了解,比如和我之前发表的Hessian源码分析有一些相似的地方。示例源码地址github,当然这个实现只是作为一些简单的原理说明,还有很多不足的地方。

  • 相关阅读:
    应用Druid监控SQL语句的执行情况
    J2EE应用监控后台执行SQL
    maven环境搭建
    【机器学习】Sklearn库主成分分析PCA降维的运用实战
    PCA降维算法
    80行Python实现-HOG梯度特征提取(转载)
    HOG特征提取算法原理(转载)
    数据预处理方法 总结
    【AI换脸】Faceswap源代码换脸软件安装指南(转)
    人工智能领域的会议和期刊(转载)
  • 原文地址:https://www.cnblogs.com/yaowen/p/9025475.html
Copyright © 2011-2022 走看看