Dubbo


Dubbo : 简单来说,Dubbo 是一个服务治理的框架,集中管理RPC调用,并提供多种访问策略和负载来满足应用系统之间的相互调用。

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

  • Provider: 暴露服务的服务提供方。
  • Consumer: 调用远程服务的服务消费方。
  • Registry: 服务注册与发现的注册中心。
  • Monitor: 统计服务的调用次调和调用时间的监控中心。
  • Container: 服务运行容器。

注意:Registry 是一个很轻的东西,实际上Dubbo只是在注册中心共享了服务的相关信息,Dubbo的主体是Provider和Consumer,这两者都是属于应用范 围内的。Monitor也是很轻的模块,需要有监控服务在Registry进行了注册应用才能正常使用监控,监控宕掉不影响服务。

 

Dubbo 本身提供了多种协议的支持,hession协议也是其中之一。

dubbo://  dubbo缺省协议采用单一长连接和NIO异步通讯(非组撒),适合于小数据量大并发的服务调用,以及服务消费者机器数大于服务提者机器数的情况。

 

  • Dubbo缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。

 

    • rmi://
      RMI协议采用JDK标准的java.rmi.*实现,采用阻塞式短连接和JDK标准序列化方式。
    • hessian://
      Hessian协议用于集成Hessian的服务,Hessian底层采用Http通讯,采用Servlet暴露服务,Dubbo缺省内嵌Jetty作为服务器实现。
    • http://
       基于http的短连接协议,基本不会去使用了。
    • webservice://
       webservice
    • redis://
      Redis是一个高效的KV存储服务器
    • memcached://
      Memcached是一个高效的KV缓存服务器
    • Thrift://
      Thrift是Facebook捐给Apache的一个RPC框架    

 

注册中心介绍

Dubbo也支持多种类型的注册中心,分别有:

    • Multicast
      基于组 播实现的注册中心,互相发现
    • Zookeeper
      Zookeeper是Apacahe Hadoop的子项目,是一个树型的目录服务,支持变更推送,适合作为Dubbo服务的注册中心,工业强度较高,可用于生产环境,并推荐使用。
    • Redis
      Redis是一个高效的KV存储服务器
    • Simple
      注册中心本身就是一个普通的Dubbo服务,可以减少第三方依赖,使整体通讯方式一致。

         <a href="http://alibaba.github.io/dubbo-doc-static/User+Guide-zh.htm" class="external-link" rel="nofollow">User+Guide-zh</a>

 

 

接口定义

  1. 定义Maven接口项目

    pom.xml
       < modelVersion >4.0.0</ modelVersion >
       < groupId >com.z</ groupId >
       < artifactId >Iexample</ artifactId >
       < version >1.0</ version >
    </ project >
  2. 定义接口
     

    ISayHello.java
    1
    2
    3
    4
    package  com.z.iexample;
    public  interface  ISayHello {
         public  String sayHelloWaitAnswer(String s);
    }

服务提供方(Provider)

 

  1. 定义Maven服务端项目,并提供相应依赖(Iexample,dubbo,zookeeper)。

    pom.xml
       < modelVersion >4.0.0</ modelVersion >
       < groupId >com.z</ groupId >
       < artifactId >example-server</ artifactId >
       < version >1.0</ version >
       < dependencies >
         < dependency >
             < groupId >com.z</ groupId >
             < artifactId >Iexample</ artifactId >
             < version >1.0</ version >
         </ dependency >
         < dependency >
             < groupId >com.alibaba</ groupId >
             < artifactId >dubbo</ artifactId >
             < version >2.5.3</ version >
         </ dependency >
         < dependency >
             < groupId >org.springframework</ groupId >
             < artifactId >spring-context</ artifactId >
             < version >3.2.1.RELEASE</ version >
         </ dependency >
         < dependency >
             < groupId >com.github.sgroschupf</ groupId >
             < artifactId >zkclient</ artifactId >
             < version >0.1</ version >
         </ dependency >
         < dependency >
             < groupId >org.slf4j</ groupId >
             < artifactId >slf4j-api</ artifactId >
             < version >1.6.4</ version >
         </ dependency >
         < dependency >
             < groupId >org.slf4j</ groupId >
             < artifactId >slf4j-log4j12</ artifactId >
             < version >1.6.4</ version >
         </ dependency >
         < dependency >
             < groupId >log4j</ groupId >
             < artifactId >log4j</ artifactId >
             < version >1.2.16</ version >
         </ dependency >
       </ dependencies >
    </ project >

    Dubbo对外的依赖是需要什么就增加什么的jar依赖,我们需要到的依赖一个是dubbo自身的依赖,另外一个是注册中心zookeeper的依赖,需要提供zookeeper的连接客户端,再者就是需要实现的接口jar了。

  2. 实现接口的服务类

    SayHelloImpl.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package  com.z.example.server.rpc;
    import  java.text.DateFormat;
    import  java.text.SimpleDateFormat;
    import  java.util.Date;
    import  java.util.concurrent.atomic.AtomicInteger;
    import  org.slf4j.Logger;
    import  org.slf4j.LoggerFactory;
    import  com.z.iexample.ISayHello;
    public  class  SayHelloImpl  implements  ISayHello {
         private  final  Logger log = LoggerFactory.getLogger(getClass());
         private  DateFormat dateFormat =  new  SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
         private  String template =  "[%s] - %d." ;
         private  AtomicInteger count =  new  AtomicInteger();
     
         public  String sayHelloWaitAnswer(String s) {
             log.info( "Receive message {} from client" , s);
             Date now =  new  Date();
             String answerTime = dateFormat.format(now);
             return  String.format(template, answerTime, count.getAndIncrement());
         }
    }
  3. 准备Spring的配置文件,因为这个示例是基于Spring Context实现的。

    applicationContext.xml
    <? xml  version = "1.0"  encoding = "UTF-8" ?>
     
         <!-- 提供方应用信息,用于计算依赖关系 -->
         < dubbo:application  name = "say-hello-server"   />
         <!-- Group属性指定dubbo在zookeeper中以什么路径开始,group之间相对隔离,如果不写,则所有服务都从根/开始 -->
         < dubbo:registry  address = "zookeeper://10.10.110.58:2181"  group = "dubbo"  client = "zkclient" />
         <!-- 如果注册中心里有监控服务进行注册,则可以开启下面的配置,监控会从注册中心寻找监控服务端,通过protocol="registry"指定 -->
    <!--     <dubbo:monitor protocol="registry"/> -->
         <!-- 服务提供方对外提供的连接数控制,connections代表与每一个消费者建立多少连接,accepts代表本服务提供方总共对外提供多少连接 -->
         < dubbo:provider  connections = "5"  accepts = "8" />
     
         <!-- 用dubbo协议在20880端口暴露服务 -->
         < dubbo:protocol  name = "dubbo"  port = "20880" />
     
         <!-- 声明需要暴露的服务接口 -->
         < dubbo:service  interface = "com.z.iexample.ISayHello"  ref = "simpleServer" />
     
         <!-- 和本地bean一样实现服务 -->
         < bean  id = "simpleServer"  class = "com.z.example.server.rpc.SayHelloImpl"  />
     
    </ beans >
  4. 提供主程序入口

    Main.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package  com.z.example.server;
    import  java.io.IOException;
    import  org.springframework.context.support.ClassPathXmlApplicationContext;
    public  class  Main {
         /**
          * @param args
          */
         public  static  void  main(String[] args) {
             ClassPathXmlApplicationContext context =  new  ClassPathXmlApplicationContext( "applicationContext.xml" );
             context.start();
             try  {
                 System.in.read();
             catch  (IOException e) {
                 e.printStackTrace();
             }
         }
    }

服务消费方(Consumer)

  1. 定义Maven项目,提供消费者的依赖

    pom.xml
       < modelVersion >4.0.0</ modelVersion >
       < groupId >com.z</ groupId >
       < artifactId >example-client</ artifactId >
       < version >1.0</ version >
       < dependencies >
         < dependency >
             < groupId >com.z</ groupId >
             < artifactId >Iexample</ artifactId >
             < version >1.0</ version >
         </ dependency >
         < dependency >
           < groupId >com.alibaba</ groupId >
           < artifactId >dubbo</ artifactId >
           < version >2.5.3</ version >
         </ dependency >
         < dependency >
             < groupId >org.springframework</ groupId >
             < artifactId >spring-context</ artifactId >
             < version >3.2.1.RELEASE</ version >
         </ dependency >
         < dependency >
             < groupId >org.apache.zookeeper</ groupId >
             < artifactId >zookeeper</ artifactId >
             < version >3.4.6</ version >
         </ dependency >
         < dependency >
             < groupId >com.github.sgroschupf</ groupId >
             < artifactId >zkclient</ artifactId >
             < version >0.1</ version >
         </ dependency >
         < dependency >
             < groupId >org.slf4j</ groupId >
             < artifactId >slf4j-api</ artifactId >
             < version >1.6.4</ version >
         </ dependency >
         < dependency >
             < groupId >org.slf4j</ groupId >
             < artifactId >slf4j-log4j12</ artifactId >
             < version >1.6.4</ version >
         </ dependency >
         < dependency >
             < groupId >log4j</ groupId >
             < artifactId >log4j</ artifactId >
             < version >1.2.16</ version >
         </ dependency >
       </ dependencies >
    </ project >

    消费者的依赖也是根据服务而定,基本上与服务提供者相同,只是不需要实现接口,只需要调用即可。

  2. 提供Spring配置文件

    applicationContext.xml
    <? xml  version = "1.0"  encoding = "UTF-8" ?>
     
         <!-- 提供方应用信息,用于计算依赖关系 -->
         < dubbo:application  name = "say-hello-client"   />
     
         < dubbo:registry  address = "zookeeper://10.10.110.58:2181"  group = "dubbo"  client = "zkclient" />
         <!-- 与服务端相同,有监控服务注册就可以开启 -->
         <!-- <dubbo:monitor protocol="registry"/> -->
         <!-- 定义引用的服务 -->
         < dubbo:reference  id = "simpleClient"  interface = "com.z.iexample.ISayHello" />
     
    </ beans >
  3. 提供Main入口调用服务

    Main.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    package  com.z.example.client;
    import  java.io.IOException;
    import  org.slf4j.Logger;
    import  org.slf4j.LoggerFactory;
    import  org.springframework.context.support.ClassPathXmlApplicationContext;
    import  com.z.iexample.ISayHello;
    public  class  Main {
         private  final  Logger log = LoggerFactory.getLogger(getClass());
         private  ClassPathXmlApplicationContext context;
     
         public  Main() {
             context =  new  ClassPathXmlApplicationContext( "applicationContext.xml" );
             context.start();
         }
     
         public  void  start() {
             ISayHello simpleClient  = (ISayHello) context.getBean( "simpleClient" );
             for ( int  i =  0 ; i <  100 ; i++){
                 String answer = simpleClient.sayHelloWaitAnswer( "HOHO "  + i);
                 log.info( "Answer from server {}" , answer);
             }
         }
     
         /**
          * @param args
          */
         public  static  void  main(String[] args) {
             new  Main().start();
             try  {
                 System.in.read();
             catch  (IOException e) {
                 e.printStackTrace();
             }
         }
    }

    这样启动后就能正常访问服务了。

F&Q

    1. Dubbo里很多标签在应用环境内都是唯一的,只有<dubbo:service>和<dubbo:reference>是多份的,但是需要注意,这两个标签的底层实现都是非常重的,所以尽量保证使用单例模式。
    2. 有时候在应用启动时可能使用的服务还没有注册,这个时候默认启动会报错,可以在reference标签添加check="false"来关闭启动的检测,只在真正发起调用时去检查。
    3. Dubbo中存在很多的配置,从上往下有很多继承关系,所以默认需要的配置很少,但是越小范围的配置越高,在小范围内没有时默认采用上一级的配置,application,registry,provider,consumer都是教高层的配置,具体的配置在Dubbo官方文档中有详细的说明,大家可以去自己研究一下。
    4. 出现java.io.IOException: Can not lock the registry cache file /home/deployer/.dubbo/dubbo-registry-xxxxx.cache, ignore and retry later的问题解决方法
      这个问题的出现是因为dubbo在用户目录下使用一个文件来缓存注册中心的服务提供者的信息,那么在使用前会加上文件锁,所以再一次使用这个文件是获取锁就会失败,解决的方式是:
      1:确认应用内只有一个<registry>标签,不同文件的情况下,也只能有一个
      2:在<registry>标签内指定一个文件,使用file属性 <registry address="xxx" file="xxx"/>


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM