精华内容
下载资源
问答
  • DUBBO应用

    2017-01-17 18:14:34
    1.现状———解决方案在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。 (1) 当服务越来越多时,服务URL配置管理变...

    1.现状———解决方案

    在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。
    (1) 当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
    此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。
    并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。

    (2) 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述?

    (3) 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
    为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。
    其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。

    简介

    Dubbo是什么
    一个分布式高性能RPC服务框架,SOA治理方案.

    核心功能
    A.远程通讯
    –多协议集成,提供对多种基于长连接的NIO框架抽象封装
    B.集群容错
    –失败自动切换,当出现失败,重试其它服务器。(缺省)
    C.自动发现
    –基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
    D.软负载均衡
    –可在内网替代F5等硬件负载均衡器,降低成本,减少单点

    DUBBO架构展示

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

    调用关系说明
    • 0. 服务容器负责启动,加载,运行服务提供者。
    • 1. 服务提供者在启动时,向注册中心注册自己提供的服务。
    • 2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
    • 3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
    • 4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
    • 5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
    这里写图片描述

    Dubbo模块详解:

    服务定义服务是围绕服务提供方和服务消费方的,服务提供方实现服务,而服务消费方调用服务。

    服务注册对于服务提供方,它需要发布服务,而且由于应用系统的复杂性,服务的数量、类型也不断膨胀;对于服务消费方,它最关心如何获取到它所需要的服务,而面对复 杂的应用系统,需要管理大量的服务调用。而且,对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,即既需要提供服务,有需要消费服务。通过将服务统一管理起来,可以有效地优化内部应用对服务发布/使用的流程和管理。服务注册中心可以通过特定协议来完成服务对外的统一。Dubbo提供的注册中心有如下几种类型可供选择:
    Multicast注册中心
    Zookeeper注册中心
    Redis注册中心
    Simple注册中心

    服务监控无论是服务提供方,还是服务消费方,他们都需要对服务调用的实际状态进行有效的监控,从而改进服务质量

    协议支持Dubbo支持多种协议,如下所示:
    Dubbo协议
    Hessian协议
    HTTP协议
    RMI协议
    WebService协议
    Thrift协议
    Memcached协议
    Redis协议
    在通信过程中,不同的服务等级一般对应着不同的服务质量,那么选择合适的协议便是一件非常重要的事情。你可以根据你应用的创建来选择。例如,使用 RMI协议,一般会受到防火墙的限制,所以对于外部与内部进行通信的场景,就不要使用RMI协议,而是基于HTTP协议或者Hessian协议。

    DUBBO配置

    1.服务提供者暴露服务配置
    Ref: 服务对象实现引用 interface: 服务接口名

    2.服务消费者引用服务配置
    Interface: 服务接口名 id: 服务引用BeanId

    3.服务提供者协议配置
    Name:协议名称(默认是dubbo协议)hession,http.,webService,rmi

    4.注册中心配置
    Port:dubbo协议缺省端口为20880,rmi协议缺省端口为1099,http和hessian协议缺省端口为80
    Host: 自动查找本机IP

    5.监控中心配置
    监控中心协议,如果为protocol=”registry”,表示从注册中心发现监控中心地址,否则直连监控中心否则直连监控中心服务器地址,address=”10.20.130.230:12080“

    6.模块信息配置
    Name: 当前模块名称,用于注册中心计算模块间依赖关系

    7.应用信息配置
    Name:当前应用名称,用于注册中心计算应用间依赖关系,注意:消费者和提供者应用名不要一样,此参数不是匹配条件, 你当前项目叫什么名字就填什么,和提供者消费者角色无关,比如:kylin应用调用了morgan应用的服务,则kylin项目配成 kylin,morgan项目配成morgan,可能kylin也提供其它服务给别人使用,但kylin项目永远配成kylin,这样注册中心将显示 kylin依赖于morgan

    8.服务提供者默认值配置,说明:该标签为和标签的默认设置。
    Id: 协议BeanId,可以在中引用此ID
    Protocol:协议名称

    9.服务消费者默认值配置, 该标签为标签的缺省值设置

    1. 方法级配置, 该标签为或的子标签,用于控制到方法级
      Name:方法名

    2. 方法参数配置, 该标签为的子标签,用于方法参数的特征描述



      Index: int值方法名
      Callback:布尔值参数是否为callback接口,如果为callback,服务提供方将生成反向代理,可以从服务提供方反向调用消费方,通常用于事件推送.

    DUBBO依赖

    <project>
      <dependencies>
          <dependency>
              <groupId>com.alibaba</groupId>
              <artifactId>dubbo</artifactId>
              <version> 2.4.9/version>
          </dependency>
       </dependencies>
    </project>
        在阿里巴巴内部广泛使用的GA版本为:2.4.9
    
    

    DUBBO简单实例

    服务接口:

    
    import java.util.List;
    
    import com.deppon.gis.common.pojo.User;
    
    public interface UserService {
    
        public List<User> queryAll();
    }
    

    dubbo传输对象实体类(必须实现序列化接口)

    
    import java.io.Serializable;
    
    // 使用dubbo要求传输的对象必须实现序列化接口
    public class User implements Serializable {
    
        private static final long serialVersionUID = -7341603933521593227L;
    
        private Long id;
    
        private String username;
    
        private String password;
    
        private Integer age;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User [id=" + id + ", username=" + username + ", password="
                    + password + ", age=" + age + "]";
        }
    
    
    }
    

    服务提供方Spring核心配置文件以及代码实现

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    
        <!-- 提供方应用信息,用于计算依赖关系 -->
        <dubbo:application name="dubbo-provider" />
    
        <!-- 这里使用的注册中心是zookeeper -->
        <dubbo:registry address="zookeeper://10.230.13.74:2181"
            client="zkclient" />
    
        <!-- 用dubbo协议在20880端口暴露服务   port="20880"-->
        <dubbo:protocol name="dubbo"   port="20880"/>
    
        <!-- 将该接口暴露到dubbo中 -->
        <dubbo:service interface="com.deppon.gis.common.service.UserService"
            ref="userServiceImpl" />
         <!-- 服务提供方    interface:服务接口名  version:版本号(注意只有在版本号一致的情况下,才可以完成消费端到提供端的调用)
         cluster:集群容错模式   retries:远程服务调用重试次数,不包括第一次调用   timeout:服务方法调用超时时间 
         protocol:只调用指定协议的服务提供方     dubbo:method会继承dubbo:service中配置的属性   loadbalance:负载均衡策略-->
        <dubbo:service interface="com.deppon.gis.common.service.UserService"
             cluster="failover"  ref="userServiceImpl"  loadbalance="random">
             <!-- <dubbo:method name="queryAll" timeout="80" retries="2" loadbalance="leastactive" /> -->
        </dubbo:service>
        <!-- 将具体的实现类加入到Spring容器中 -->
        <bean id="userServiceImpl" class="com.deppon.gis.provider.service.impl.UserServiceImpl" />
        <!-- 监控中心配置 -->
        <dubbo:monitor protocol="registry"/>
    
    
    </beans>
    
    import java.net.InetAddress;
    import java.net.UnknownHostException;
    import java.util.ArrayList;
    import java.util.List;
    
    import com.deppon.gis.common.pojo.User;
    import com.deppon.gis.common.service.UserService;
    
    
    public class UserServiceImpl implements UserService{
    
        public List<User> queryAll() {
            long x=0;
            List<User> users=new ArrayList<User>();
            try {
                 InetAddress addr = null;
                   try {
                      addr = InetAddress.getLocalHost();
                   } catch (UnknownHostException e) {
                      e.printStackTrace();
                   }
                   String IP=addr.getHostAddress().toString();
                for (int i = 0; i < 20; i++) {
                    x++;
                    User user= new User();
                    user.setAge(i);
                    user.setId(x);
                    user.setPassword("MIMA"+i);
                    user.setUsername("用户名"+IP+"--------线程名称"+Thread.currentThread().getName());
                    users.add(user);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return users;
        }
    
    }

    服务消费方spring核心配置文件以及代码实现

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    
        <!-- 提供方应用信息,用于计算依赖关系 -->
        <dubbo:application name="dubbo-consumer" />
    
        <!-- 这里使用的注册中心是zookeeper -->
        <dubbo:registry address="zookeeper://10.230.13.74:2181"
            client="zkclient" />
    
        <!-- 从注册中心中查找服务 -->
        <dubbo:reference id="userService"
            interface="com.deppon.gis.common.service.UserService" >
             <!-- <dubbo:method name="queryAll" retries="2" /> -->
        </dubbo:reference>
    
        <!-- 监控中心配置 -->
    
        <dubbo:monitor protocol="registry"/>
    
        <bean id="conSumer" class="com.deppon.gis.consumer.ConSumer">
           <property name="userService" ref="userService"></property>
        </bean>
    </beans>
    
    
    import java.util.List;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogConfigurationException;
    import org.apache.commons.logging.LogFactory;
    
    import com.alibaba.fastjson.JSON;
    import com.deppon.gis.common.pojo.User;
    import com.deppon.gis.common.service.UserService;
    
    public class ConSumer {
        private static  Log log=LogFactory.getLog(ConSumer.class);
        private UserService userService;
    
        public void setUserService(UserService userService) {
            this.userService = userService;
        }
    
        public void queryAll(){
            List<User> queryAll = userService.queryAll();
            if(queryAll==null &&queryAll.size()==0){
                log.info("info级别 获取的数据为0");
                System.out.println("获取数据为0----------------------------");
            }
            for (User user : queryAll) {
                if(user==null){
                    log.error("error级别 获取的数据为空");
                    System.out.println("获取数据空----------------------------");
                }else{
                Object json = JSON.toJSON(user);
                System.out.println("阿里的fastjson,单独解析json对象"+json);
                }
            }
        }
    
    
    }

    DUBBO实例运行
    这里写图片描述

    Dubbo复杂配置

    A.Dubbo服务集群容错配置
    假设我们使用的是单机模式的Dubbo服务,如果在服务提供方(Provider)发布服务以后,服务消费方(Consumer)发出一次调用请求,恰好 这次由于网络问题调用失败,那么我们可以配置服务消费方重试策略,可能消费方第二次重试调用是成功的(重试策略只需要配置即可,重试过程是透明的);但 是,如果服务提供方发布服务所在的节点发生故障,那么消费方再怎么重试调用都是失败的,所以我们需要采用集群容错模式,这样如果单个服务节点因故障无法提 供服务,还可以根据配置的集群容错模式,调用其他可用的服务节点,这就提高了服务的可用性。
    Dubbo内置支持如下6种集群模式:
    Failover Cluster模式:
    配置值为failover。这种模式是Dubbo集群容错默认的模式选择,调用失败时,会自动切换,重新尝试调用其他节点上可用的服务
    **这里写图片描述**
    如果调用失败一次,可以再次重试2次调用,服务级别调用超时时间为100ms,调用方法queryRoomUserCount的超时时间为80ms,允许重试2次,最坏情况调用花费时间160ms。
    Failfast Cluster模式
    配置值为failfast。这种模式称为快速失败模式,调用只执行一次,失败则立即报错。
    Failsafe Cluster模式:
    配置值为failsafe。失败安全模式,如果调用失败, 则直接忽略失败的调用,而是要记录下失败的调用到日志文件,以便后续审计

    Failback Cluster模式
    配置值为failback。失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作

    Forking Cluster模式
    配置值为forking。并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。

    Broadcast Cluster模式
    配置值为broadcast。广播调用所有提供者,逐个调用,任意一台报错则报错(2.1.0开始支持)。通常用于通知所有提供者更新缓存或日志等本地资源信息。

    B.Dubbo服务负载均衡
    Dubbo框架内置提供了4种负载均衡策略:
    Random LoadBalance:随机策略,配置值为random。可以设置权重,有利于充分利用服务器的资源,高配的可以设置权重大一些,低配的可以稍微小一些(默认)
    RoundRobin LoadBalance:轮询策略,配置值为roundrobin
    LeastActive LoadBalance:配置值为leastactive。根据请求调用的次数计数,处理请求更慢的节点会受到更少的请求
    ConsistentHash LoadBalance: ” 一致性Hash,相同参数的请求总是发到同一提供者。
    ” 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

    这里写图片描述

    此配置负载策略为:随机策略,dubbo:method配置负载策略为轮训策略,service默认策略为随机策略 methos如不定义随机策略,默认继承service负载策略

    Dubbo管理控制台,简易控制中心的安装

    1. Dubbo管理控制平台安装
    作用:Dubbo的管理控制台,在实际的项目中非常的有用,尤其是在dubbo服务提供数量逐渐加大的情况下,通过Dubbo管理控制台能够很好的被我们所用,从而让我们更好的使用Dubbo提供的服务.
    操作步骤:
    A.Dubbo.properties配置文件管理注册中心连接以及管理控制平台用户名和密码
    dubbo.registry.address=zookeeper://10.230.13.74:2181配置Zookeeper注册中心的地址和端口,这个属性支持多个注册中心的配置
    dubbo.admin.root.password=root
    dubbo.admin.guest.password=guest以上两个属性是管理控制台的用户名密码.
    这里写图片描述

    B.启动服务
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    2.Dubbo 简易监控中心
    dubbo-monitor作用:
    Simple Monitor挂掉不会影响到Consumer和Provider之间的调用,所以用于生产环境不会有风险。

    配置好了之后可以结合admin管理后台使用,可以清晰的看到服务的访问记录、成功次数、失败次数等…..

    Simple Monitor采用磁盘存储统计信息,请注意安装机器的磁盘限制,如果要集群,建议用mount共享磁盘。
    charts目录必须放在jetty.directory下,否则页面上访问不了

    操作步骤
    需要在服务端以及消费端dubbo核心配置文件中配置监控中心

    服务端客户端监控中心配置:
    这里写图片描述

    启动Dubbo-monitor监控中心
    这里写图片描述
    因为dubbo监控中心内嵌jetty服务器,启动服务器,访问ip+8080路径
    这里写图片描述
    这里写图片描述

    Dubbo管理SOA服务方案:

    1.WebService
    A.maven依赖

    <dependencies>
            <!-- dubbo推荐版本2.4.9 阿里巴巴内部广泛使用的GA版本-->
           <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>2.4.9</version>
                <exclusions>
                    <exclusion>
                        <!-- 排除传递spring依赖 -->
                        <artifactId>spring</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                </exclusions>
           </dependency>
          <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>4.1.3.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.6.4</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>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.1.39</version>
            </dependency>
            <dependency>
               <groupId>gis.deppon.com</groupId>
               <artifactId>dubbo-api</artifactId>
               <version>0.0.1-SNAPSHOT</version>
            </dependency>
             <dependency>
               <groupId>org.codehaus.jackson</groupId>
               <artifactId>jackson-mapper-asl</artifactId>
               <version>1.9.4</version>
         </dependency>
       <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-simple</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>2.6.1</version>
    </dependency>
      </dependencies>

    B.服务端Web.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="WebApp_ID" version="2.5">
    
        <display-name>dubbo</display-name>
    
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dubbo/dubbo-*.xml</param-value>
        </context-param>
    
        <!--Spring的ApplicationContext 载入 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    
         <!--dubbo 服务根路径-->
        <servlet>
            <servlet-name>dubbo</servlet-name>
            <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dubbo</servlet-name>
            <url-pattern>/services/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

    C.服务端spring核心文件配置以及代码实现:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://code.alibabatech.com/schema/dubbo
            http://code.alibabatech.com/schema/dubbo/dubbo.xsd
            ">
    
        <!-- 提供方应用信息,用于计算依赖关系 -->
        <dubbo:application name="dubbo-webservice-app" />
    
        <!-- 使用zookeeper注册中心暴露服务地址 -->
        <dubbo:registry address="zookeeper://10.230.13.74:2181" />
    
        <!-- 用webservice协议在8080端口暴露服务,如server属性定义servlet,则暴露端口号必须与所在服务的端口号保持一致 -->
        <dubbo:protocol name="webservice" port="8080" server="servlet" />
        <!-- 声明需要暴露的服务接口 -->
        <dubbo:service interface="com.gis.webservice.service.DubboService"
            ref="dubboService" />
    
        <!-- 和本地bean一样实现服务 -->
        <bean id="dubboService" class="com.gis.webservice.service.impl.DubboServiceImpl" />
    
    </beans>
    
    //接口
    public interface DubboService {
    
        public String printWord(String word);
    }
    //实现类
    import com.gis.webservice.service.DubboService;
    
    public class DubboServiceImpl implements DubboService {
    
        public String printWord(String word) {
    
            return "DUBBO 集成webService  返回字符串";
        }
    
    }

    D.客户端spring核心配置文件配置以及代码实现

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://code.alibabatech.com/schema/dubbo
            http://code.alibabatech.com/schema/dubbo/dubbo.xsd
            ">
    
        <!-- 提供方应用信息,用于计算依赖关系 -->
        <dubbo:application name="dubbo-webservice-consumer" />
    
        <!-- 使用zookeeper注册中心暴露服务地址 -->
        <dubbo:registry address="zookeeper://10.230.13.74:2181" />
    
    <!--URL属性:服务端服务的访问路径,最后路径则为接口的全路径 -->
       <dubbo:reference id="dubboService" interface="com.gis.webservice.service.DubboService"
        url="webservice://localhost:8080/services/com.gis.webservice.service.DubboService" />
    
        <bean id="consumerService" class="com.gis.consumer.service.impl.ConsumerServiceImpl">
            <property name="dubboService" ref="dubboService"></property>
        </bean>
    </beans>
    
    //代码实现
    import com.gis.consumer.service.ConsumerService;
    import com.gis.webservice.service.DubboService;
    
    public class ConsumerServiceImpl implements ConsumerService {
    
        private DubboService dubboService;
    
        public void setDubboService(DubboService dubboService) {
            this.dubboService = dubboService;
        }
    
        public void say() {
            String printWord = dubboService.printWord("123");
            System.out.println("WebService客户端展示"+printWord);
    
        }
    
    
    }

    操作步骤:启动服务端以及客户端服务,输入服务访问路径判断webService服务是否搭建成功。如图展示如出现以下内容即表示webService服务搭建成功
    测试结果展示:
    这里写图片描述
    这里写图片描述

    2.restfulWebService
    简介:Dubbox是Dubbo的一个扩展,功能展示:支持REST风格远程调用(HTTP + JSON/XML); 支持基于Kryo和FST的Java高效序列化实现; 支持基于嵌入式Tomcat的HTTP remoting体系。
    dubbo添加REST调用,其最主要到目的也是面向服务的提供端,即开发REST服务来提供给非dubbo的(异构)消费端。
    A.服务端pom配置:
    要引用2.8.4版本dubbo框架并且排除spring的依赖

     <dependencies>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>dubbo</artifactId>
                <version>2.8.4</version>
                 <exclusions>
                    <exclusion>
                    <!--    排除传递spring依赖 -->
                        <artifactId>spring</artifactId>
                        <groupId>org.springframework</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
             <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>4.1.3.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.javassist</groupId>
                <artifactId>javassist</artifactId>
                <version>3.15.0-GA</version>
            </dependency>
            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty</artifactId>
                <version>3.7.0.Final</version>
            </dependency>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.2.1</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.1.39</version>
            </dependency>
            <dependency>
                <groupId>org.apache.bsf</groupId>
                <artifactId>bsf-api</artifactId>
                <version>3.1</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.apache.cxf</groupId>
                <artifactId>cxf-rt-frontend-simple</artifactId>
                <version>2.6.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-rt-transports-http</artifactId>
                <version>2.6.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.thrift</groupId>
                <artifactId>libthrift</artifactId>
                <version>0.8.0</version>
            </dependency>
            <dependency>
                <groupId>com.caucho</groupId>
                <artifactId>hessian</artifactId>
                <version>4.0.7</version>
            </dependency>
             <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
                <scope>provided</scope>
            </dependency> 
            <!-- 要将 org.mortbay.jettyJAR包中的servlet-->
            <dependency>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.mortbay.jetty</groupId>
                        <artifactId>servlet-api</artifactId>
                    </exclusion>
                </exclusions>
                <version>6.1.26</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                 <version>1.2.16</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.6.2</version>
            </dependency>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
               <version>2.1.0</version>
            </dependency>
            <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>1.0.0.GA</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>4.2.0.Final</version>
            </dependency>
            <dependency>
                <groupId>javax.cache</groupId>
                <artifactId>cache-api</artifactId>
                <version>0.4</version>
            </dependency>
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jaxrs</artifactId>
                <version>3.0.7.Final</version>
            </dependency>
    
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-client</artifactId>
                <version>3.0.7.Final</version>
            </dependency>
    
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-netty</artifactId>
                <version>3.0.7.Final</version>
            </dependency>
    
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jdk-http</artifactId>
                <version>3.0.7.Final</version>
            </dependency>
    
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jackson-provider</artifactId>
                <version>3.0.7.Final</version>
            </dependency>
    
            <dependency>
                <groupId>org.jboss.resteasy</groupId>
                <artifactId>resteasy-jaxb-provider</artifactId>
                <version>3.0.7.Final</version>
            </dependency>
    
            <!-- <dependency>   注意:此JAR包中也包含servlet类,如果使用要注意排除其中的servlet
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-core</artifactId>
                <version>8.0.11</version>
            </dependency>
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-logging-juli</artifactId>
                <version>8.0.11</version>
            </dependency> -->
            <!-- KRYO 高性能序列化库 -->
            <dependency>
                <groupId>com.esotericsoftware.kryo</groupId>
                <artifactId>kryo</artifactId>
                <version>2.24.0</version>
            </dependency>
            <dependency>
                <groupId>de.javakaffee</groupId>
                <artifactId>kryo-serializers</artifactId>
                <version>0.26</version>
            </dependency>
            <dependency>
                <groupId>de.ruedigermoeller</groupId>
                <artifactId>fst</artifactId>
                 <version>1.55</version>
          </dependency>
    
            <dependency>
                <groupId>com.deppon.gis</groupId>
                <artifactId>restapi</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
            <!-- RESTFUL JAR包 -->
            <dependency>  
                    <groupId>javax.ws.rs</groupId>  
                    <artifactId>javax.ws.rs-api</artifactId>  
                    <version>2.0</version>  
                </dependency>
             <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
       </dependencies>

    B.服务端web.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="WebApp_ID" version="2.5">
    <!-- dubbox 远程调用的配置 -->
    <!-- 如果你是用spring的ContextLoaderListener来加载spring,则必须保证BootstrapListener配置在ContextLoaderListener之前,否则dubbo初始化会出错。 -->
       <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:dubbo/dubbo-*.xml</param-value>
        </context-param>
        <listener>
            <listener-class>com.alibaba.dubbo.remoting.http.servlet.BootstrapListener</listener-class>
        </listener>
    
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <servlet>
            <servlet-name>dispatcher</servlet-name>
            <servlet-class>com.alibaba.dubbo.remoting.http.servlet.DispatcherServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcher</servlet-name>
            <url-pattern>/services/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

    C.服务端spring核心配置以及代码实现

    
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
        <!-- 开放dubbo协议,serialization表示序列化的方案  optimizer表示执行序列化的类-->
        <dubbo:protocol name="dubbo" serialization="kryo" optimizer="com.alibaba.dubbo.demo.SerializationOptimizerImpl"/>
        <dubbo:protocol name="dubbo" serialization="fst" optimizer="com.alibaba.dubbo.demo.SerializationOptimizerImpl"/>
        <dubbo:protocol name="dubbo" serialization="nativejava"/>
        <dubbo:protocol name="dubbo" serialization="hessian2"/>
        <dubbo:protocol name="dubbo" serialization="fastjson"/>
        <dubbo:protocol name="dubbo" serialization="dubbo"/>
        <!-- name:使用的协议  port:端口号   
         contextpath:所有rest服务对应的基础路径  
         server:如果为servlet,那么在web.xml中DispatcherServlet访问路径必须是 contextpath配置的访问路径
         extension:配置拦截器,多个拦截器类似于逗号分开
        -->
         <!-- 提供方应用信息,用于计算依赖关系   owner:该应用的负责人 -->
        <dubbo:application name="demo-provider" />
         <!-- 注册中心地址 -->
        <dubbo:registry address="zookeeper://10.230.13.74:2181"/>
        <!-- 开启dubbo注解扫描 -->
        <dubbo:annotation package="com.deppon.gis.service" />  
        <!--  name:使用的协议  
            port:端口号   
         contextpath:所有rest服务对应的基础路径  
         server:如果为servlet,那么在web.xml中DispatcherServlet访问路径必须是 contextpath配置的访问路径 
         extension:配置拦截器的实现类-->
         <!-- contextpath="services"  --><!-- server="servlet"  -->
        <dubbo:protocol name="rest"  port="9090"  contextpath="services" server="servlet" />
        <!-- extension="com.deppon.gis.filter.DubboxProviderFilter,
          com.deppon.gis.filter.DubboProvideCustomException,com.deppon.gis.filter.DubboConsumerFilter"extension 此属性值为自定义的dubbo拦截类需要实现ClientResponseFilter或者ContainerResponseFilter接口,可自行百度,此处不做演示 -->
       <!-- 声明需要暴露的服务接口 -->
        <dubbo:service interface="com.deppon.gis.service.DubboProviderService" ref="dubboProviderServiceImpl"
          protocol="rest" validation="true"  timeout="2000" connections="100" />
    
        <bean id="dubboProviderServiceImpl" class="com.deppon.gis.provider.impl.DubboProviderServiceImpl" />
    
    </beans>
    
    
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    
    import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;
    //接口上面不添加注解,保持接口的广泛适用性,使用dubbo客户端调用必须添加在接口上面
    @Path("/restdemo")  //访问路径
    public interface DubboProviderService {
          @GET  //请求方式
          @Path("/{param}")  //访问路径,并且请求参数加如正则校验必须是数组
          @Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})  
          public String queryService(@PathParam("param") int name);
    }
    
    import com.deppon.gis.service.DubboProviderService;
    
    public class DubboProviderServiceImpl implements DubboProviderService{
    
           //指定输出JSON格式的数据。框架会自动将对象序列化为JSON数据。application/json; charset=UTF-8,text/xml;charset=UTF-8
            public String queryService(int name) {
                    return "客户端使用restful风格调用服务端不使用servlet,返回字符串 name="+name ;
            }
    }

    A.非dubbo客户端调用duboo-rest服务端
    这里写图片描述
    B.dubbo客户端调用dubbo服务端
    服务端配置文件:
    这里写图片描述
    客户端配置文件:
    这里写图片描述
    运行结果:
    这里写图片描述
    C.dubbo客户端调用非dubbo服务端
    服务端配置文件:
    这里写图片描述
    这里写图片描述
    接口:
    这里写图片描述
    客户端配置文件:
    这里写图片描述
    实现:
    这里写图片描述

    展开全文
  • 本篇侧重用代码说明Dubbo应用程序的开发及使用,通过一个简单的示例演示Dubbo应用。读者要是对Dubbo框架的基本概念还有模糊,可以先阅读 【Dubbo】深入理解Apache Dubbo(一):带你走近高性能RPC通信框架 另外本篇...

    1. 引言

    本篇侧重用代码说明Dubbo应用程序的开发及使用,通过一个简单的示例演示Dubbo应用。读者要是对Dubbo框架的基本概念还有模糊,可以先阅读
    【Dubbo】深入理解Apache Dubbo(一):带你走近高性能RPC通信框架
    另外本篇涉及的所有源码都已经上传到GitHub,欢迎交流学习:
    Dubbo应用程序实战

    2. 环境配置

    无论你使用的是Windows、Linux还是Mac OS操作系统,请保证已经配置如下的环境:JDK(必须,推荐1.8)、IDE(推荐IDEA)、Maven(推荐版本3.x.x)以及ZooKeeper(不是必须,但生产环境已经大量使用ZooKeeper作为注册中心,为了深入理解Dubbo,建议配置)
    另外,为了更好的学习Dubbo,强烈建议clone源码学习,附GitHub地址:
    https://github.com/apache/dubbo
    通过git clone https://github.com/apache/dubbo命令将Dubbo源码clone到本地之后,用IDEA打开。所有模块的测试都在对应的test文件夹下,可以在对应的源码中打好断点,然后利用测试类进行单元调试,有利于更加深入的理解Dubbo。

    3. 开发Dubbo应用程序

    在本节中,笔者将动手快速构建一个完整的服务器和客户端程序。程序功能很简单:服务器接收客户端的请求,然后将消息不做任何处理返回给客户端。但是麻雀虽小五脏俱全,这个示例将很有助于我们理解Dubbo的运行过程。应用程序编写有三种方式:XML、注解和API。

    3.1 基于XML配置的方式

    1.编写服务端
    先定义服务暴露的接口EchoService
    程序清单3-1

    /**
     * @author Carson Chu
     * @email 1965704869@qq.com
     * @date 2020/1/31 13:53
     * @description
     */
    public interface EchoService {
    
        /**
         * @description 发送给客户端的信息
         * @params [msg]
         * @returns java.lang.String
         */
        String productMsg(String msg);
    }
    

    然后实现该接口。
    程序清单3-2

    /**
     * @author Carson Chu
     * @email 1965704869@qq.com
     * @date 2020/1/31 13:53
     * @description
     */
    public class EchoServiceImpl implements EchoService {
        @Override
        public String productMsg(String msg) {
            String curTime = new SimpleDateFormat("HH:mm:ss").format(new Date());
            System.out.println("[" + curTime + "] Hello " + msg
                    + ", request from client: " + RpcContext.getContext().getRemoteAddress());
            return msg;
        }
    }
    

    接下来,就是基于XML配置的核心了,将配置文件echo-provider.xml放到项目资源目录resources/spring下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- 服务提供方应用名称, 方便用于依赖跟踪 -->
        <dubbo:application name="echo-provider"/>
    
        <!-- 使用本地zookeeper作为注册中心 -->
        <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    
        <!-- 只用Dubbo协议并且指定监听端口 20880 -->
        <dubbo:protocol name="dubbo" port="20880"/>
    
        <!-- 通过xml方式配置为bean, 让spring托管和实例化 -->
        <bean id="echoService" class="com.pers.server.impl.AnnotationServiceImpl"/>
    
        <!-- 声明服务暴露的接口,并暴露服务 -->
        <dubbo:service interface="com.pers.server.AnnotationService" ref="echoService"/>
    
    </beans>
    

    之后,我们还需要编写一个类用于加载该配置文件并启动Dubbo服务:
    程序清单3-3

    /**
     * @author Carson Chu
     * @description
     */
    public class EchoProvider {
    
        public static void main(String[] args) throws Exception {
            // #1 指定服务暴露配置文件
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/echo-provider.xml"});
            // #2 启动spring容器并暴露服务
            context.start();
    
            System.in.read();
        }
    }
    

    2.编写客户端
    客户端也是通过加载XML配置文件的:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
           xmlns="http://www.springframework.org/schema/beans"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- 服务消费方应用名称, 方便用于依赖跟踪 -->
        <dubbo:application name="echo-consumer"/>
    
        <!-- 使用本地zookeeper作为注册中心 -->
        <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    
        <!-- 指定要消费的服务 -->
        <dubbo:reference id="echoService" check="false" interface="com.pers.server.EchoService"/>
    
    </beans>
    

    但此步需要保证client依赖server端的服务(因为EchoService属于server模块),在IDEA中的配置步骤是:

    1. 打开Project Structure,
      在这里插入图片描述
    2. 在弹出的窗口按照下图依次勾选:
      在这里插入图片描述
    3. 最后在弹出的窗口选择你要依赖的模块,这里选择dubbo-server:

    在这里插入图片描述
    配置完成之后,开始编写客户端消费程序:
    程序清单3-4

    /**
     * @author Carson Chu
     * @description
     */
    public class EchoConsumer {
    
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"spring/echo-consumer.xml"});
            context.start();
            EchoService echoService = (EchoService) context.getBean("echoService"); // get remote service proxy
    
            String status = echoService.productMsg("Hello Dubbo!");
            System.out.println("echo result: " + status);
        }
    }
    

    编写完成之后运行main方法,可以在控制台看到运行结果:
    在这里插入图片描述
    到这里,基于XML的方式编写Dubbo应用程序就完成了。
    3. 可能遇到的问题
    如果启动报错:

    java.lang.NoClassDefFoundError: io/netty/channel/nio/NioEventLoopGroup

    则需要引入该jar包:

                <dependency>
                    <groupId>io.netty</groupId>
                    <artifactId>netty-all</artifactId>
                    <version>4.1.42.Final</version>
                </dependency>
    

    3.2 基于注解的方式

    通过XML方式配置启动Dubbo服务比较常见,另外Dubbo也支持通过注解的方式启动。通过注解的方式更加友好一点,虽然会耦合一些Dubbo框架自身的注解,但是代码重构的时候比较便利。
    1. 编写服务端
    该方式在定义了接口之后,只需要在接口实现类上加上注解@Service。需要注意的是,**这个@Service不是Spring框架的注解,而是Dubbo的注解。**使用注解之后,由Dubbo框架bazhege 实现类升级为Spring容器的Bean。
    程序清单3-5

    import com.alibaba.dubbo.config.annotation.Service;
    
    /**
     * @author Carson Chu
     * @description
     */
    @Service
    public class AnnotationServiceImpl implements AnnotationService {
        @Override
        public String productMsg(String msg) {
            String curTime = new SimpleDateFormat("HH:mm:ss").format(new Date());
            System.out.println("[" + curTime + "] Hello " + msg
                    + ", request from client: " + RpcContext.getContext().getRemoteAddress());
            return msg;
        }
    }
    

    不同于基于XML的方式,基于注解的方式生成Dubbo的配置信息是通过程序以及注解来实现的。
    程序清单3-6

    /**
     * @author Carson Chu
     * @email 1965704869@qq.com
     * @date 2020/1/31 15:30
     * @description
     */
    public class AnnotationProvider {
        public static void main(String[] args) throws Exception {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
            context.start();
            System.in.read();
        }
    
        @Configuration
        // #1 指定扫描服务的位置
        @EnableDubbo(scanBasePackages = "com.pers.server")
        static class ProviderConfiguration {
            @Bean
            public ProviderConfig providerConfig() {
                return new ProviderConfig();
            }
    
            @Bean
            public ApplicationConfig applicationConfig() {
                ApplicationConfig applicationConfig = new ApplicationConfig();
                applicationConfig.setName("echo-annotation-provider");
                return applicationConfig;
            }
    
            @Bean
            public RegistryConfig registryConfig() {
                RegistryConfig registryConfig = new RegistryConfig();
                // #2 使用zookeeper作为注册中心,同时给出注册中心ip和端口
                registryConfig.setProtocol("zookeeper");
                registryConfig.setAddress("localhost");
                registryConfig.setPort(2181);
                return registryConfig;
            }
    
            @Bean
            public ProtocolConfig protocolConfig() {
                ProtocolConfig protocolConfig = new ProtocolConfig();
                // #3 默认服务使用dubbo协议,在20880端口监听服务
                protocolConfig.setName("dubbo");
                protocolConfig.setPort(20880);
                return protocolConfig;
            }
        }
    }
    

    2. 编写客户端
    通过注解消费服务的时候,只需要@Reference注解标注,该注解适用于对象字段和方法。
    程序清单3-7 基于注解包装消费

    @Component
    public class EchoConsumer {
        @Reference
        private AnnotationService annotationService;
    
        public String produceMsg(String msg) {
            return annotationService.productMsg(msg);
        }
    }
    

    在完成上述的消费定义之后,还需要完成基于注解的启动代码。
    程序清单3-7 基于注解消费服务

    /**
     * @author Carson Chu
     * @email 1965704869@qq.com
     * @date 2020/1/31 17:40
     * @description
     */
    public class AnnotationConsumer {
        public static void main(String[] args) {
            // #1 基于注解配置初始化spring上下文
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
            context.start();
            // #2 发起服务调用
            EchoConsumer echoService = context.getBean(EchoConsumer.class);
            String hello = echoService.produceMsg("Hello Dubbo!");
            System.out.println("result: " + hello);
        }
    
        @Configuration
        // #3 指定要扫描的消费注解,会触发注入
        @EnableDubbo(scanBasePackages = "com.pers.client")
        @ComponentScan(value = {"com.pers.client"})
        static class ConsumerConfiguration {
            @Bean
            public ApplicationConfig applicationConfig() {
                ApplicationConfig applicationConfig = new ApplicationConfig();
                applicationConfig.setName("echo-annotation-consumer");
                return applicationConfig;
            }
    
            @Bean
            public ConsumerConfig consumerConfig() {
                return new ConsumerConfig();
            }
    
            @Bean
            public RegistryConfig registryConfig() {
                RegistryConfig registryConfig = new RegistryConfig();
                // #4 使用zookeeper作为注册中心,同时给出注册中心ip和端口
                registryConfig.setProtocol("zookeeper");
                registryConfig.setAddress("localhost");
                registryConfig.setPort(2181);
                return registryConfig;
            }
        }
    }
    

    然后启动该服务,依然会看出控制台输出:result:Hello Dubbo!
    3. 可能遇到的问题
    如果运行的时候报错:

    NoClassDefFoundError: com/alibaba/spring/util/PropertySourcesUtils

    则需要引入该jar包:

            <dependency>
                <groupId>com.alibaba.spring</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>1.0.5</version>
            </dependency>
    

    3.3 基于API的方式

    该方式在大部分场景下不会直接使用,但在开发网关类的应用时,该方式则非常有用。本篇对该方式不做赘述。感兴趣的同学可以私聊我学习交流。

    小结

    通过以上的代码,我们已经实现了利用Dubbo服务实现客户端和服务端交互的功能。在客户端启动时发生了哪些事情呢?这里做个小结:

    • 客户端启动时会创建和Zookeeper注册中心的连接并拉取服务列表
    • 拉取服务列表完成之后,会与远程服务建立TCP长连接
    • 客户端发起服务调用,发送“Hello Dubbo!”给服务方,服务方不做任何处理返回给客户端。
    • 客户端收到回显消息并输出。

    在实现了第一个Dubbo应用程序之后,从下一篇开始,笔者将会开始Dubbo底层架构的学习。

    展开全文
  • dubbo应用实例

    2019-05-23 10:13:21
    这是一个参考了网上其他人的代码后,自己平平凑凑整合起来的一套dubbo应用实例。用到了spring、spring mvc、mybatis、dubbo等技术。 工具和技术 操作系统:centOS 7.5 数据库服务器:mysql 5.7 zookeeper...

    这是一个参考了网上其他人的代码后,自己拼拼凑凑整合起来的一套dubbo应用实例。用到了spring、springMVC、mybatis、dubbo等技术。

    工具和技术

    • 操作系统:centOS 7.5
    • 数据库服务器:mysql 5.7
    • zookeeper服务器:zookeeper-3.4.6、dubbo-monitor-simple-2.5.3、dubboadmin、jdk1.7、apache-tomcat-7.0.88
    • 生产者服务器:apache-tomcat-9.0.16、jdk-11.0.2
    • 消费者服务器:apache-tomcat-9.0.16、jdk-11.0.2
    • 开发工具:IntelliJ IDEA 、apache-maven-3.6.0

    系统部署

    你要准备4台服务器,可以用vmware虚拟出4台centOS操作系统的服务器出来。不过把它们全部署在同一台服务器也可以。所有服务装好后,记得要打开防火墙的开放端口。

    开放防火墙端口可用以下命令:
    firewall-cmd --zone=public --add-port=8080/tcp --permanent
    firewall-cmd --reload
    firewall-cmd --list-all

    数据库服务器

    安装好MySQL,防火墙放开3306端口。用root登录MySQL建库、用户、表,程序需要用到。

    --创建数据库
    CREATE DATABASE vigardb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
    --创建用户
    CREATE USER 'vigar'@'%' IDENTIFIED BY 's32sk2334jk2';
    --授权用户权限
    GRANT ALL ON vigardb.* TO 'vigar'@'%';
    --用新用户登录后建表
    CREATE TABLE `user` (
      `id` int(11) DEFAULT NULL,
      `username` varchar(30) DEFAULT NULL,
      `password` varchar(30) DEFAULT NULL,
      `age` int(11) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    zookeeper服务器

    可以参考dubbo admin 和monitor的安装进行部署。部署成功后可以看到如下:登录的用户名和密码都是root
    dubboadmin
    这个monitor就是那个dubbo monitor部署成功提供的服务。

    dubbo monitor也有个网页,不过好像没啥用。
    dubbomonitor
    防火墙要放开端口:7070、8080、9090、2181

    生产者服务器

    把tomcat和jdk解压到/usr/local下,然后在/etc/profile.d下添加两个文件java.sh和tomcat.sh,用于设置环境变量。
    java.sh:

    JAVA_HOME=/usr/local/jdk-11.0.2
    PATH=$JAVA_HOME/bin:$PATH
    

    tomcat.sh:

    CATALINA_BASE=/usr/local/apache-tomcat-9.0.16
    PATH=$CATALINA_BASE/bin:$PATH
    

    然后把程序编译出来的vigar-dubbo-provider.war放到tomcat的webapps下,然后启动tomcat。
    顺利的话,将可以在dubboadmin看到新增了两个服务。
    服务
    防火墙要放开端口:20880

    消费者服务器

    跟生产者服务器一样的部署,只是放的是vigar-dubbo-consumer.war。顺利的话,将可以访问到网页,然后就可以开始试用功能了。
    前端
    防火墙要放开端口:8080

    代码

    代码用一个父pom.xml把几个子项目集合在一起,以便统一依赖包的版本号。包含以下三个子项目:

    vigar-dubbo-api

    这个用来放消费者和生产者都会用到的对象和服务接口,以免相同的代码出现在多处地方。

    vigar-dubbo-provider

    这是生产者代码,用mybatis连数据库,UserMapper.xml、UserMapper.java、UserExample.java和User.java几个文件是用mybatis-generator生成的,不需要手工编写。注意要修改jdbc.properties和applicationContext-dubbo-provider.xml里面的IP,改成你自己服务器的。

    vigar-dubbo-consumer

    这是消费者代码,它并不连数据库,所有请求都通过请求dubbo服务获得。程序用spring mvc架构。注意要改dubbo文件里的IP。

    代码下载

    dubbo应用实例.zip

    存在问题

    这套代码引用了太多jar包,有一些应该是多余的,谁能告诉我哪些jar去掉了,也能正常运行。

    展开全文
  • dubbo应用场景示例二

    2018-05-21 18:55:27
    dubbo应用场景示例一》中我们介绍了3种dubbo应用场景,今天我们接着聊聊dubbo几种应用场景。 1、线程模型 如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直接在 IO ...

    个人博客请访问 http://www.x0100.top  

    《dubbo应用场景示例一》中我们介绍了3种dubbo应用场景,今天我们接着聊聊dubbo几种应用场景。

    1、线程模型

    如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直接在 IO 线程上处理更快,因为减少了线程池调度。

    但如果事件处理逻辑较慢,或者需要发起新的 IO 请求,比如需要查询数据库,则必须派发到线程池,否则 IO 线程阻塞,将导致不能接收其它请求。

    如果用 IO 线程处理事件,又在事件处理过程中发起新的 IO 请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。

    因此,需要通过不同的派发策略和不同的线程池配置的组合来应对不同的场景:

    <dubbo:protocolname="dubbo" dispatcher="all" threadpool="fixed"threads="100" />

    Dispatcher

    all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。

    direct 所有消息都不派发到线程池,全部在 IO 线程上直接执行。

    message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在 IO 线程上执行。

    execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在 IO 线程上执行。

    connection 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。

    ThreadPool

    l  fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)

    l  cached 缓存线程池,空闲一分钟自动删除,需要时重建。

    l  limited 可伸缩线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。

    2、直连提供者

    在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表。

    通过 XML 配置

    如果是线上需求需要点对点,可在中配置 url 指向提供者,将绕过注册中心,多个地址用分号隔开,配置如下(1.0.6 及以上版本支持):

    <dubbo:referenceid="xxxService" interface="com.alibaba.xxx.XxxService"url="dubbo://l  ocalhost:20890"/>

    通过 -D 参数指定

    在 JVM 启动参数中加入-D参数映射服务地址(key 为服务名,value 为服务提供者 url,此配置优先级最高, 1.0.15 及以上版本支持) ,如:

    java-Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890

    通过文件映射

    如果服务比较多,也可以用文件映射,用 -Ddubbo.resolve.file 指定映射文件路径,此配置优先级高于 中的配置(1.0.15 及以上版本支持, 2.0 以上版本自动加载${user.home}/dubboresolve.properties文件,不需要配置) ,如:

    java-Ddubbo.resolve.file=xxx.properties

    然后在映射文件 xxx.properties 中加入配置,其中 key 为服务名,value 为服务提供者 URL:

    com.alibaba.xxx.XxxService=dubbo://localhost:20890

    注意为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。

    3、只订阅

    为方便开发测试,经常会在线下共用一个所有服务可用的注册中心,这时,如果一个正在开发中的服务提供者注册,可能会影响消费者不能正常运行。

    可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其它服务),而不注册正在开发的服务,通过直连测试正在开发的服务。

    禁用注册配置

    <dubbo:registryaddress="10.20.153.10:9090" register="false" />

    或者

    <dubbo:registryaddress="10.20.153.10:9090?register=false" />

    关注微信公众号和今日头条,精彩文章持续更新中。。。。。

     

    展开全文
  • 背景本文将以 Dubbo 为例,介绍如何快速开发一个 Dubbo 应用。为了便于读者理解:首先会介绍一下传统的 RMI 的基本概念然后比较下现代的 RPC 框架与 RMI 的区别再基于 Dubbo 提供的 API 展示最基本的 Dubbo 应用如何...
  • 本周刚好研究了一下dubbo的启动脚本,所以在官网的启动脚本和公司内部的启动脚本做了一个整理,弄了一份比较通过的Dubbo应用启动和停止脚本。  下面的脚本只应用于配置分离的应用,什么叫做配置分离呢?就是使用...
  • 使用IDEA 创建Dubbo应用 - Quick Start

    千次阅读 2018-06-08 17:40:25
    Dubbo是由阿里巴巴研发的一个高性能的,基于java的RPC开源的框架 。在停止维护了数年之后,直到去年...接下来将以Dubbo官网的Quick Start例子来体验构建一个简单的Dubbo应用(使用ZooKeeper作为注册中心)。 1.创建...
  • 简介:本文分为三部分来介绍,分别介绍微服务应用迁移到 SAE 的优势,如何迁移 SpringCloud/Dubbo 应用到 SAE 上,以及针对 SpringCloud 应用迁移的实践演示。作者 | 行松 阿里巴巴云原生团队本文整理自《Serverless...
  • 在Docker中运行Dubbo应用

    万次阅读 2017-03-30 11:18:36
    摘要: 本文通过Spring Boot构建了一个最小的Dubbo应用,容器化后成功部署到阿里云容器服务上。 Dubbo是阿里开源的一个分布式服务框架,在国内粉丝很多。官网上的介绍是: DUBBO是一个分布式服务框架...
  • 使用Docker容器化SpringBoot+Dubbo应用的实践 Docker在日常开发中越来越火,工作中后端很多项目都需要使用Docker进行容器化,SpringBoot+Docker被称为“原生云应用”,SpringBoot应用和Docker结合非常容易。但是...
  • while(true)引发的Dubbo应用假死

    千次阅读 2016-06-08 17:12:13
    while(true)引发的Dubbo应用假死现象:当客户端向服务器发起调用的时候,Dubbo出现无法响应,客户端报超时异常,而且当客户端继续调用任何服务时,出现No provider available 异常。而此时服务器不见异常,偶尔报出...
  • springboot项目中dubbo应用启动报错

    万次阅读 2020-06-15 15:53:26
    主要报错信息: Error starting ApplicationContext....com.alibaba.dubbo.remoting.RemotingException: Failed to bind NettyServer on /192.168.65.1:20880, cause: Failed to bind to: /0.0.0.0:20
  • dubbo应用场景示例一

    千次阅读 2018-05-21 18:53:11
    公司使用Dubbo做为服务治理工具搭建了微服务架构。幸运的是,Dubbo官方文档对于开发过程遇到的一些通用问题提供了解决办法。我们一起来看一下。 1、启动时检查 Dubbo缺省会在启动时检查依赖的服务是否可用,不可用...
  • dubbo应用场景示例三

    千次阅读 2018-05-22 07:40:55
    如果有两个镜像环境,两个注册中心,有一个服务只在其中一个注册中心有部署,另一个注册中心还没来得及部署,而两个注册中心的其它应用都...dubbo:registryid="hzRegistry" address="10.20.153.10:9090" /> ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 77,448
精华内容 30,979
关键字:

dubbo应用