Dubbo原理简介------自己动手实现简单的RPC调用

最近开始学习Dubbo框架. 

      Dubbo是阿里推出的一个开源的分布式服务框架,致力于提供高性能和透明化的RPC(Remote Procedure Call)远程服务调用方案,以及SOA治理方案. 简单的说,就是个远程服务调用的分布式框架.

      RPC即远程过程调用,也就是一台机器上的应用调用另一台机器上的方法.由于两个应用不在同一个内存上,因此不能直接调用,需要借助于网络通信,将方法相关的信息如接类型,方法名,参数类型,参数列表等通过网络通信发送给服务提供者,由服务提供者调用方法,并将方法执行的结果发送给服务调用者.

下图是Dubbo的架构图:


主要分为几个部分:

1.Provider 服务提供者

2.Consumer 调用服务的服务消费者

3.Registry 服务注册与发现的注册中心

4.统计服务的调用次调和调用时间的监控中心

服务调用的过程:

1).服务提供者向注册中心注册自己的服务

2).服务消费者向注册中心订阅自己所需的服务

3).注册中心将服务提供者的地址发送给服务消费者

4).服务消费者和服务提供者建立连接,调用服务提供者的服务


为了更好的理解RPC,下面参考网上的信息,简单实现了一个RPC过程. 主要分为以下几个部分:

1.ServiceProvider:服务提供者,对外提供服务

2.ServiceConsumer:服务消费者,调用服务提供者的服务

3.Registry:注册中心,负责服务的注册和发现

      这里主要利用了动态代理和socket通信的方法. 客户端通过动态代理获得代理对象;服务器创建真实对象;当客户端通过代理对象调用方法时, 在服务器和客户端之间建立socket连接, 将接口类型, 方法名, 参数类型, 参数对象发送给服务端. 服务端接收到相关信息后, 调用方法,并将方法返回的结果对象发送给客户端.

注册中心

[java]  view plain  copy
  1. /** 
  2.  * 服务注册中心 
  3.  * @author Administrator 
  4.  * */  
  5. public class Registory {  
  6.     private Map<String, ProviderConnection>map=new ConcurrentHashMap<>();  
  7.     private static final int PORT_PROVIDER=12003;  
  8.     private static final int PORT_CONSUMER=12206;  
  9.     /**监听服务提供者的注册请求*/  
  10.     public void register(){  
  11.         ServerSocket server=null;  
  12.         try {  
  13.             server=new ServerSocket(PORT_PROVIDER);  
  14.             System.out.println("开启provider监听");  
  15.             while(true){  
  16.                 Socket socket=server.accept();  
  17.                 System.out.println("provider建立连接");  
  18.                 registService(socket);  
  19.             }  
  20.         } catch (IOException e) {  
  21.             e.printStackTrace();  
  22.         } finally {  
  23.             if(server!=null){  
  24.                 try {server.close();} catch (IOException e) {e.printStackTrace();}  
  25.             }  
  26.         }  
  27.     }  
  28.     /**provider连接,将接口名\主机名\端口号发送过来;Registry接收到后将信息保存在map中*/  
  29.     private void registService(Socket socket) {  
  30.         ObjectInputStream reader=null;  
  31.         try{  
  32.             reader=new ObjectInputStream(socket.getInputStream());  
  33.             String interfaceName=reader.readUTF();  
  34.             ProviderConnection provConn=(ProviderConnection) reader.readObject();  
  35.             map.put(interfaceName, provConn);  
  36.         }catch(IOException e){  
  37.             e.printStackTrace();  
  38.         } catch (ClassNotFoundException e) {  
  39.             e.printStackTrace();  
  40.         }finally {  
  41.             if(reader!=null&&!socket.isClosed()){  
  42.                 try{reader.close();}catch(IOException e){e.printStackTrace();}  
  43.             }  
  44.             if(socket!=null&&!socket.isClosed()){  
  45.                 try{socket.close();}catch(IOException e){e.printStackTrace();}  
  46.             }  
  47.         }  
  48.         System.out.println("服务注册成功");  
  49.     }  
  50.     /**监听服务消费者的请求*/  
  51.     public void subscribe(){  
  52.         ServerSocket server=null;  
  53.         try {  
  54.             server=new ServerSocket(PORT_CONSUMER);  
  55.             System.out.println("开启consumer监听");  
  56.             while(true){    //  
  57.                 Socket socket=server.accept();  
  58.                 System.out.println("消费者建立连接...");  
  59.                 subscribeService(socket);  
  60.             }  
  61.         } catch (IOException e) {  
  62.             e.printStackTrace();  
  63.         } finally {  
  64.             if(server!=null){  
  65.                 try {server.close();} catch (IOException e) {e.printStackTrace();}  
  66.             }  
  67.         }  
  68.     }  
  69.     /**接收消费者的信息,并将服务提供者对应的信息返回给消费者*/  
  70.     private void subscribeService(Socket socket) {  
  71.         ObjectInputStream reader=null;  
  72.         ObjectOutputStream oos=null;  
  73.         try{  
  74.             reader=new ObjectInputStream(socket.getInputStream());  
  75.             oos=new ObjectOutputStream(socket.getOutputStream());  
  76.             String interfaceName=reader.readUTF();  
  77.             System.out.println("interfaceName="+interfaceName);  
  78.             ProviderConnection provConn=map.get(interfaceName);  
  79.               
  80.             System.out.println("provConn="+provConn);  
  81.             oos.writeUTF(provConn.getHost());  
  82.             System.out.println("host="+provConn.getHost());  
  83.               
  84.             Integer port=provConn.getPort();/  
  85.             System.out.println("port="+port);  
  86.             oos.writeInt(port); /  
  87.             oos.flush();    /  
  88.         }catch(IOException e){  
  89.             e.printStackTrace();  
  90.         }  
  91.     }  
  92.     public static void main(String[] args) {  
  93.         Registory registory=new Registory();  
  94.         Thread thread1=new Thread(new Runnable() {  
  95.             @Override  
  96.             public void run() {  
  97.                 registory.register();  
  98.             }  
  99.         });  
  100.         Thread thread2=new Thread(new Runnable() {  
  101.             @Override  
  102.             public void run() {  
  103.                 registory.subscribe();  
  104.             }  
  105.         });  
  106.         thread1.start();thread2.start();  
  107.     }  
  108. }  

服务提供者

[java]  view plain  copy
  1. <span style="font-size:14px;">/** 
  2.  * 服务提供者,负责对外提供服务 
  3.  * @author Administrator 
  4.  * */  
  5. public class ServiceProvider {  
  6.     private ExecutorService executor=Executors.newFixedThreadPool(10);  
  7.     private boolean flag=false;  
  8.       
  9.     private Map<String,Object> map=new ConcurrentHashMap<>();  
  10.     private static final String REGISTORY_HOST="localhost";  
  11.     private static final String PROVIDER_HOST="localhost";  
  12.     /**注册中心的端口号*/  
  13.     private static final int REGISTOR_PORT=12003;  
  14.     /**本机监听的端口号,用于和客户端建立连接*/  
  15.     private static final int PROVIDER_PORT=12004;  
  16.     public ServiceProvider() {}  
  17.       
  18.     /**将服务保存在本地*/  
  19.     public void regist(Object object){  
  20.         Class<?>[] cls=object.getClass().getInterfaces();  
  21.         String interfaceName=cls[0].getName();  
  22.         map.put(interfaceName, object);  
  23.         System.out.println(interfaceName+"保存...");  
  24.         registService(REGISTORY_HOST,REGISTOR_PORT,interfaceName);  
  25.     }  
  26.     /**将服务的接口名和服务提供者的信息注册到远程的注册中心*/  
  27.     private void registService(String registoryHost, int registoryPort, String interfaceName) {  
  28.         Socket socket=null;  
  29.         ObjectOutputStream writer=null;  
  30.         try {  
  31.             socket=new Socket(registoryHost,registoryPort);  
  32.             writer =new ObjectOutputStream(socket.getOutputStream());  
  33.               
  34.             writer.writeUTF(interfaceName);  
  35.             writer.writeObject(new ProviderConnection(PROVIDER_HOST,PROVIDER_PORT));  
  36.             writer.flush();  
  37.             System.out.println(interfaceName+"注册...");  
  38.         } catch (UnknownHostException e) {  
  39.             e.printStackTrace();  
  40.         } catch (IOException e) {  
  41.             e.printStackTrace();  
  42.         }finally {  
  43.             if(writer!=null){  
  44.                 try {writer.close();} catch (IOException e) {e.printStackTrace();}  
  45.             }  
  46.             if(socket!=null){  
  47.                 try {socket.close();} catch (IOException e) {e.printStackTrace();}  
  48.             }  
  49.         }  
  50.     }  
  51.     /**启动服务器*/  
  52.     public void start(){  
  53.         ServerSocket server=null;  
  54.         System.out.println("服务器启动");  
  55.         while(!flag){  
  56.             try {  
  57.                 server=new ServerSocket(PROVIDER_PORT);  
  58.                 Socket socket=server.accept();  
  59.                 System.out.println("消费者建立连接");  
  60.                 Thread thread=new Thread(new ThreadA(socket));  
  61.                 executor.submit(thread);  
  62.             } catch (IOException e) {  
  63.                 e.printStackTrace();  
  64.             }finally {  
  65.                 if(server!=null){  
  66.                     try{server.close();}catch(IOException e){e.printStackTrace();}  
  67.                 }  
  68.             }  
  69.         }  
  70.         System.out.println("服务器关闭成功");  
  71.     }  
  72.     /**关闭服务器*/  
  73.     public void stop(){  
  74.         this.flag=true;  
  75.     }  
  76.     /** 
  77.      * 1.服务消费者连接成功之后,接收消费者发送来的信息: 
  78.      *      1).服务名称:接口名 
  79.      *      2).方法名 
  80.      *      3).参数类型(Class[]) 
  81.      *      4).参数对象(Object[]) 
  82.      * 2.调用方法 
  83.      *      method.invoke(...); 
  84.      * 3.返回: 
  85.      *      方法执行后的result对象. 
  86.      * */  
  87.     class ThreadA implements Runnable{  
  88.         private Socket socket;  
  89.         public ThreadA(Socket socket) {  
  90.             this.socket=socket;  
  91.         }  
  92.         @Override  
  93.         public void run() {  
  94.             ObjectOutputStream oos=null;  
  95.             ObjectInputStream ois=null;  
  96.             try {  
  97.                 oos=new ObjectOutputStream(socket.getOutputStream());  
  98.                 ois=new ObjectInputStream(socket.getInputStream());  
  99.                   
  100.                 String interfaceName=ois.readUTF();  
  101.                 String methodName=ois.readUTF();  
  102.                 Class<?> argsCls[]=(Class<?>[]) ois.readObject();  
  103.                 Object[] args=(Object[]) ois.readObject();  
  104.                   
  105.                 Object targetService =map.get(interfaceName);  
  106.                 Method method=targetService.getClass().getMethod(methodName, argsCls);  
  107.                 Object result=method.invoke(targetService, args);  
  108.                   
  109.                 oos.writeObject(result);  
  110.             }catch (Exception e) {  
  111.                 e.printStackTrace();  
  112.             } finally {  
  113.                 if(ois!=null&&!socket.isClosed()){  
  114.                     try{ois.close();}catch(IOException e){e.printStackTrace();}  
  115.                 }  
  116.                 if(oos!=null&&!socket.isClosed()){  
  117.                     try{oos.close();}catch(IOException e){e.printStackTrace();}  
  118.                 }  
  119.             }  
  120.         }  
  121.     }  
  122.     public static void main(String[] args) {  
  123.         HelloWorld helloWorld=new HelloWorld();  
  124.         ServiceProvider provider=new ServiceProvider();  
  125.         provider.regist(helloWorld);  
  126.         provider.start();  
  127.     }  
  128. }</span><span style="font-size:18px;">  
  129. </span>  

服务消费者

[java]  view plain  copy
  1. /** 
  2.  * 服务消费者 
  3.  * @author Administrator 
  4.  * */  
  5. public class ServiceConsumer {  
  6.     /*注册中心的端口号*/  
  7.     private static final int<span style="font-size:12px;"> REGISTER_PORT=12</span>206;  
  8.     /*注册中心的主机名*/  
  9.     private static final String REGISTER_HOST="localhost";  
  10.     /*服务提供者的主机名*/  
  11.     private String host;  
  12.     /*服务提供者的端口号*/  
  13.     private int port;  
  14.     /**从注册中心获取服务提供者的信息: 
  15.      * 1.host服务提供者的主机名 
  16.      * 2.port服务提供者的端口号 
  17.      * */  
  18.     public void getProvider(String interfaceName){  
  19.         ObjectOutputStream oos=null;  
  20.         ObjectInputStream ois=null;  
  21.         Socket socket=null;  
  22.         try {  
  23.             socket=new Socket(REGISTER_HOST,REGISTER_PORT);  
  24.             oos=new ObjectOutputStream(socket.getOutputStream());  
  25.             ois=new ObjectInputStream(socket.getInputStream());  
  26.             oos.writeUTF(interfaceName);  
  27.             oos.flush();  
  28.               
  29.             String host=ois.readUTF();  
  30.             this.host=host;  
  31.             int port=ois.readInt();  
  32.             this.port=port;  
  33.             System.out.println("host="+host+"\nport="+port);  
  34.         } catch (UnknownHostException e) {  
  35.             e.printStackTrace();  
  36.         } catch (IOException e) {  
  37.             e.printStackTrace();  
  38.         }  
  39.     }  
  40.     /** 
  41.      * 利用动态代理的方式获取服务 
  42.      *  1.服务消费者端持有代理类对象; 
  43.      *  2.当消费者执行代理对象的方法时,建立和服务提供者的连接, 
  44.      *  3.发送相关参数给服务提供者, 
  45.      *  4.获得方法执行后的结果 
  46.      * @param serviceInterface :服务的接口类型 
  47.      * @return 
  48.      */  
  49.     @SuppressWarnings("unchecked")  
  50.     public <T>T findService(Class<T> serviceInterface){  
  51.           
  52.         return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{serviceInterface}, new InvocationHandler(){  
  53.             @Override  
  54.             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  55.                 Socket socket=new Socket(host,port);  
  56.                 ObjectOutputStream oos=null;  
  57.                 ObjectInputStream ois=null;  
  58.                 try {  
  59.                     oos=new ObjectOutputStream(socket.getOutputStream());  
  60.                     ois=new ObjectInputStream(socket.getInputStream());  
  61.                       
  62.                     String methodName=method.getName();  
  63.                     System.out.println("serviceInterface="+serviceInterface.getName());  
  64.                     oos.writeUTF(serviceInterface.getName());  
  65.                     oos.writeUTF(methodName);  
  66.                     oos.writeObject(method.getParameterTypes());  
  67.                     oos.writeObject(args);  
  68.                     oos.flush();  
  69.                       
  70.                     Object result=ois.readObject();  
  71.                     return result;  
  72.                 } catch (UnknownHostException e) {  
  73.                     e.printStackTrace();  
  74.                 } catch (IOException e) {  
  75.                     e.printStackTrace();  
  76.                 } finally {  
  77.                     if(ois!=null&&!socket.isClosed()){  
  78.                         try{ois.close();}catch(IOException e){e.printStackTrace();}  
  79.                     }  
  80.                     if(oos!=null&&!socket.isClosed()){  
  81.                         try{oos.close();}catch(IOException e){e.printStackTrace();}  
  82.                     }  
  83.                     if(socket!=null){  
  84.                         try{socket.close();}catch(IOException e){e.printStackTrace();}  
  85.                     }  
  86.                 }  
  87.                 return null;  
  88.             }  
  89.         });  
  90.     }  
  91.     public static void main(String[] args) {  
  92.         ServiceConsumer consumer=new ServiceConsumer();  
  93.         consumer.getProvider("cn.dongchao.dubbo.day02.Hello");  
  94.         Hello hello=consumer.findService(Hello.class);  
  95.         String result=hello.sayHello("zhangsan");  
  96.         System.out.println("result="+result);  
  97.     }  
  98. }  

用于测试的接口:

[java]  view plain  copy
  1. public interface Hello {  
  2.     String sayHello(String message);  
  3.     void sayYes(String msg);  
  4. }  

实现类:

[java]  view plain  copy
  1. public class HelloWorld implements Hello{  
  2.   
  3.     @Override  
  4.     public String sayHello(String message) {  
  5.         System.out.println("hello..."+message+"!");  
  6.         return "hello..."+message+"!";  
  7.     }  
  8.     @Override  
  9.     public void sayYes(String msg) {  
  10.         System.out.println("yes: "+msg+"...");  
  11.           
  12.     }  
  13. }  

分别启动Registry\Provider\Consumer,  结果如下:

注册中心:


provider:


Consumer:


可以看到,provider的服务成功注册到注册Registry, 然后Consumer从Registry获得服务提供者的相关信息, Consumer和provider建立连接; Consumer端调用方法,provider端执行方法,并将结果返回给Consumer. Consumer端成功接收到方法执行后的结果.

本文章参考了以下博客的内容:

http://blog.csdn.net/is_zhoufeng/article/details/21133643

http://blog.csdn.net/ichsonx/article/details/39008519

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值