dubbo教程

Posted z街角的风铃y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo教程相关的知识,希望对你有一定的参考价值。

Dubbo教程

一. Dubbo简介

Dubbox 是一个分布式服务框架,底层采用netty通信,服务之间通过rpc调用

 

 

 

 

节点角色说明

节点

角色说明

Provider

暴露服务的服务提供方

Consumer

调用远程服务的服务消费方

Registry

服务注册与发现的注册中心

Monitor

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

Container

服务运行容器

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

 

  • 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外
  • 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
  • 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者

 

 

二. 整合dubbo,官网给出了四种整合方式,xml,属性配置,aip配置,注解配置,建议使用xml配置方式。

2.1spring整合dubbo

 

所需环境:zookeeper作为注册中心,dubbo服务和消费方都在其中注册,教程见我的zookeeper教程

1.项目结构,消费者提供者共同依赖的都写在dubbo-demo的pom.xml中

 

 

 

 

 

 

1.1   pom.xml的配置,导入的jar包都springwebmvc的,dubbo,zookeeper,aop,lomback等。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>dubbo-demo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <!-- 在阿里巴巴内部广泛使用的GA版本为:2.4.9,强烈推荐此版本 -->
       
<dubbo.version>2.5.3</dubbo.version>
        <spring.version>5.1.6.RELEASE</spring.version>
    </properties>
   
    <dependencies>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!--引入json,返回前端json数据-->
       
<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.6</version>
        </dependency>


        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--aop-->
       
<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
            <scope>provided</scope>
        </dependency>
        <!-- spring end -->
       
<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--日志-->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
       
<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.8.0-alpha0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
            <scope>compile</scope>
        </dependency>

        <!--j2ee相关包 servletjspjstl-->
       
<dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>
   
    <modules>
        <module>api</module>
        <module>provider</module>
        <module>consumer</module>
    </modules>


</project>

1.2 新建maven工程,api,中定义接口DemoService和实体类Student

public interface DemoService {
    public String sayHello(String name);
    public Student getStudent(int id);
}

 

@Data
public class Student implements Serializable {
    private int id;
    private String name;
    private int age;
}

1.2新建provider的maven项目,作为提供方。
#引入api的依赖
<dependencies>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>
#新建api接口的实现类DEmoServiceImpl
public class DemoServiceImpl implements DemoService{
    @Override
    public String sayHello(String name) {
        return "你好"+name;
    }

    @Override
    public Student getStudent(int id) {
        Student student = new Student();
        student.setId(1);
        student.setName("zhouyang");
        student.setAge(25);
        return student;
    }
}
#resources下新建applicationContext.xml配置提供方信息
<?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_provider"/>
    <!-- 使用zookeeper注册中心暴露服务地址 -->
   
<dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- dubbo协议在20880端口暴露服务,服务方提供,消费方被动接受,所以消费方不用配置-->
   
<dubbo:protocol name="dubbo" port="20880" />

    <!-- 声明需要暴露的服务接口 -->
   
<dubbo:service interface="com.zy.dao.DemoService" ref="demoService" />
<bean id="demoService" class="com.zy.dao.DemoServiceImpl"/>
</beans>
#启动spring项目
public class Test {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        DemoServiceImpl demoService = (DemoServiceImpl) applicationContext.getBean("demoService");
        System.out.println(demoService);
        applicationContext.start();
        try {
            System.in.read();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}


    整体构造

 

 


    1.3 新建consumer消费方的maven工程,consumer是一个webmvc项目,pom中引入api依赖
#引入api依赖
<dependency>
    <groupId>org.example</groupId>
    <artifactId>api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
#web,xml中配置mvc的信息
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!--post请求乱码处理-->
 
<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--springmvc的配置文件地址-->
   
<init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!--启动时间,跟服务器一起启动-->
   
<load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <!--拦截所有请求-->
   
<url-pattern>/*</url-pattern>
  </servlet-mapping>

</web-app>
#配置spring-mvc.xml
<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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://www.springframework.org/schema/mvc
         http://www.springframework.org/schema/mvc/spring-mvc.xsd
          http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
        http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--此文件负责整个mvc中的配置-->
    <!--
自动扫描装配,扫描controller包的注解,加入到容器中 -->
   
<context:component-scan base-package="com.zy.controller"/>
    <!-- 配置注解驱动可以将request参数与绑定到controller参数上 -->
   
<mvc:annotation-driven/>
    <mvc:default-servlet-handler/>
    <!--静态资源映射-->
    <!--
本项目把静态资源放在了webappstatics目录下,资源映射如下-->
    <!--<mvc:resources mapping="/css/**" location="/static/css/"/>-->
    <!--<mvc:resources mapping="/js/**" location="/static/js/"/>-->
    <!--<mvc:resources mapping="/image/**" location="/static/images/"/>-->
   
<mvc:default-servlet-handler />  <!--这句要加上,要不然可能会访问不到静态资源,具体作用自行百度-->

    <!--
对模型视图名称的解析,即在模型视图名称添加前后缀(如果最后一个还是表示文件夹,则最后的斜杠不要漏了) 使用JSP-->
    <!--
默认的视图解析器在上边的解析错误时使用 (默认使用html)- -->
   
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--配置dubbo-->
    <!--
提供方应用信息,用于计算依赖关系 -->
   
<dubbo:application name="dubbo_consumer"/>
    <!-- 使用zookeeper注册中心暴露服务地址 -->
   
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <!-- 声明需要暴露的服务接口 -->
   
<dubbo:reference id="demoService" interface="com.zy.dao.DemoService" timeout="3000" />

</beans>
#新建HelloControoler
@RestController
public class HelloController {
    @Autowired
    @Qualifier("demoService")
    private DemoService demoService;
    @RequestMapping(value = "/hello",produces = {"application/json;charset=UTF-8"})
    public String sayHello(){
        return demoService.sayHello("zhouyang");
    }
    @RequestMapping("/get_student")
    public Student getStudent(int id){
        Student student = demoService.getStudent(id);
        return student;
    }
}
整体结构如下

 

 

 

1.3   启动zookeeper,启动provider项目,再启动consumer项目测试。

 

 

 

 

 

2.2 springboot整合dubbo,采用xml方式。

2.2.1新建空工程,dubbo-springboot-xml

2.2.2 新建api的maven工程,消费方和提供方共同依赖再api定义,

#pom.xnl

<dependencies>
    <dependency>
        <groupId>com.alibaba.boot</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>0.2.0</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.12</version>
    </dependency>
</dependencies>

#定义接口和实体类

public interface DemoService {
    public String sayHello(String name);
    public Student getStudent(int id);
}
@Data
public class Student implements Serializable {
    private int id;
    private String name;
    private int age;
}

 

 

#新建provider的spirngboot项目,pom中引入api依赖

#新建api接口实现类

@Service("demoService")
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "service"+name;
    }

    @Override
    public Student getStudent(int id) {
        Student student = new Student();
        student.setId(2);
        student.setName("service");
        student.setAge(25);
        return student;
    }
}

 

#resources下新建provider.xml配置提供方

<?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_provider"/>
    <!-- 使用zookeeper注册中心暴露服务地址 -->
   
<dubbo:registry address="zookeeper://127.0.0.1:2181" check="false"/>

    <!-- dubbo协议在20880端口暴露服务,协议配置,用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受。 -->
    
<dubbo:protocol name="dubbo" port="20880" />

    <!-- 声明需要暴露的服务接口 -->
   
<dubbo:service interface="com.zy.dao.DemoService" ref="demoService"/>
   </beans>

#application.properties中只写了prot配置

server.port=8080

#朱启动类上引入provider.xml

@SpringBootApplication
@ImportResource("classpath:provider.xml")
public class ProviderApplication {

   public static void main(String[] args) {
      SpringApplication.run(ProviderApplication.class, args);
   }

}

2.2.3 新建consumer消费方springboot项目,新建的时候选上mvc,pom.xml中引入api依赖

#resources下配置consumer.xml

<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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://www.springframework.org/schema/mvc
         http://www.springframework.org/schema/mvc/spring-mvc.xsd
          http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
        http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">


    <!--配置dubbo-->
    <!--
提供方应用信息,用于计算依赖关系 -->
   
<dubbo:application name="dubbo_consumer"/>
    <!-- 使用zookeeper注册中心暴露服务地址 -->
   
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <!-- 声明需要暴露的服务接口 -->
   
<dubbo:reference id="demoService" interface="com.zy.dao.DemoService" timeout="3000"/>
</beans>

#application.properties中

server.port=8081

#新建TestController

@RestController
public class TestController {
    @Autowired
    @Qualifier("demoService")
    private DemoService demoService;
    @RequestMapping("hello")
    public String sayHello(){
      return  demoService.sayHello("zhouyang");
    }
    @RequestMapping("get_student")
    public Student getStudent(){
        return demoService.getStudent(1);
    }
   
}

#住启动类引入consumer.xml

 

2.3 采用属性配置,和xml差不多,只不过配置都写在application.properties中,

服务生产者配置

在application.propetries中声明生成者配置信息

 

#springboot应用

spring.application.name = dubbo-provider-demo

server.port = 8080

 

# 扫描带阿里注解的的类(e.g @Service , @Reference)

#如果没有在配置中写dubbo.scan.base-package,还需要使用@EnableDubbo注解

#如果写了dubbo.scan.basePackages就可以主启动类不用写@EnableDubbo注解

dubbo.scan.basePackages  =com.example.provider.dao

 

 

# Dubbo Config properties

##应用配置

dubbo.application.id = dubbo-provider

dubbo.application.name = dubbo-provider

##协议配置

dubbo.protocol.id = dubbo

dubbo.protocol.name = dubbo

dubbo.protocol.port = 20880

 

dubbo.service.*.timeout=1000

##注册配置

dubbo.registry.id = my-registry

dubbo.registry.address =zookeeper://localhost:2181

dubbo.registry.dynamic=false

dubbo.registry.check=false

#监控中心

#dubbo.monitor.protocol=registry

 

#Dubbo Config properties

   

#dubbo 2.6.2版本需要写注册中心配置

dubbo.registry.address =zookeeper://localhost:2181

   

服务接口实现

@org.springframework.stereotype.Service("demoService")
@Service
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "你好"+name;
    }

    @Override
    public Student getStudent(int id) {
        Student student = new Student();
        student.setId(2);
        student.setName("zhouyang");
        student.setAge(25);
        return student;
    }
}

这里注意@Service这个注解,是dubbo提供的注解相当于XML配置中的

 

<dubbo:service interface="com.gjy.service.DefaultApiService" ref="defaultService"  />

1

服务启动

这里就是普通的springboot启动

 

@SpringBootApplication
public class ProviderApplication {

   public static void main(String[] args) {
      SpringApplication.run(ProviderApplication.class, args);
   }

}

服务消费者配置

#springboot应用名

spring.application.name = dubbo-consumer

server.port = 8081

 

#Dubbo Config properties

##应用配置

dubbo.application.id = dubbo-consumer

dubbo.application.name = dubbo-consumer

#dubbo 2.6.2版本需要写注册中心配置

dubbo.registry.address =zookeeper://localhost:2181

 

#监控中心

#dubbo.monitor.protocol=registry

#关闭所有消费者启动时检查

#dubbo.consumer.check=false

服务生产者调用

@RestController
public class TestController {
    @Reference
    private DemoService demoService;
    @RequestMapping("hello")
    public String sayHello(){
      return  demoService.sayHello("zhouyang");
    }
    @RequestMapping("get_student")
    public Student getStudent(){
        return demoService.getStudent(1);
    }
   
}

注意这里的@Reference注解是dubbo提供的注解,相当于XML配置的:

 

<dubbo:reference id="defaultService" interface="com.gjy.service.DefaultApiService" />

1

消费者启动

@SpringBootApplication
public class ConsumerApplication {

   public static void main(String[] args) {
      SpringApplication.run(ConsumerApplication.class, args);
   }

}
#启动provider和consumer,测试

 

 

 

2.4 springboot整合dubbo采用api方式

2.4.1 提供方配置

#Application.propertis配置

server.port=8081

#新建配置类

@Configuration
public class ProviderConfig {
    @Bean
    public ApplicationConfig applicationConfig(){
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-provider-api");
        return applicationConfig;
    }
    @Bean
    public RegistryConfig registryConfig(){
        RegistryConfig registryConfig =  new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");
        return registryConfig;
    }
    @Bean
    public ProtocolConfig protocolConfig(){
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);
        return protocolConfig;
    }
}
#实现接口
@org.springframework.stereotype.Service("demoService")
@Service
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "你好"+name;
    }

    @Override
    public Student getStudent(int id) {
        Student student = new Student();
        student.setId(2);
        student.setName("api");
        student.setAge(25);
        return student;
    }
}
 

#主启动类指定扫描包

@SpringBootApplication
//扫面指定包下的Servicedubbo的注解
@DubboComponentScan("com.example.provider.dao")
public class ProviderApplication {

   public static void main(String[] args) {
      SpringApplication.run(ProviderApplication.class, args);
   }

}

 

2.4.2 消费方配置

#applicaiton.properties配置

server.port=8081

#新建配置类

@Configuration
public class ConsumerConfig {
    //配置提供方应用名
   
@Bean
    public ApplicationConfig applicationConfig(){
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-consumer-api");
        return applicationConfig;
    }
    @Bean
    public RegistryConfig registryConfig(){
        RegistryConfig registryConfig =  new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");
        return registryConfig;
    }
}

#写controller

@RestController
public class TestController {
    @Reference
    private DemoService demoService;
    @RequestMapping("hello")
    public String sayHello(){
      return  demoService.sayHello("zhouyang");
    }
    @RequestMapping("get_student")
    public Student getStudent(){
        return demoService.getStudent(1);
    }
   
}
#启动项目测试
 
三. 启动dubbo admin
3.1 下载admin包
https://codeload.github.com/apache/incubator-dubbo-ops/zip/master

3.2 进入dubbo-admin项目

 

 

 

3.3 修改application的配置,特别是注册中心的地址。

 

 

 

3.3 进入cmd,maven导包

mvn clean package

 

 

 

3.4 进入生成的target目录,运行jar包

java -jar dubbo-admin-0.0.1-SNAPSHOT.jar

 

 

 

3.5 访问

默认端口为7001,账号/密码 :root/root
访问地址为:http://localhost:7001/

四. Dubbo配置方式的加载顺序,优先级从上到下,即环境配置》xml配置》properties配置

 

 

 

 

五. 配置的覆盖关系

 

 

 

 

 

六. 启动时检查

 

 

 

启动时检查分为两个方面,一个是服务注册订阅检查另一个是判断是否有服务提供者,默认都为ture,意思就是服务启动的时候如果没有成功注册订阅,或者服务消费者启动的时候找不到对应的服务器提供者,就会报错阻止项目的启动。官网说了,可以设置为false,意思就是可以想让项目启动起来,发现服务未注册或者没有服务提供者时报错。

 

 

 

七. 多版本

多版本主要过渡的时候用,实现灰度发布的一个手段。这里官网给出的解释:

 

 

 

多版本测试。

服务提供者,新增一个接口的实现类

@Service("demoService2")
public class DemoServiceImpl2 implements DemoService {
    @Override
    public String sayHello(String name) {
        return "service2"+name;
    }

    @Override
    public Student getStudent(int id) {
        Student student = new Student();
        student.setId(2);
        student.setName("service2");
        student.setAge(25);
        return student;
    }
}

服务提供者配置

<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.zy.dao.DemoService" ref="demoService" version="1.0.0" />
<dubbo:service interface="com.zy.dao.DemoService" ref="demoService2" version="2.0.0" />

服务消费者配置

<!-- 声明需要暴露的服务接口 -->
<dubbo:reference id="demoService" interface="com.zy.dao.DemoService" timeout="3000" version="1.0.0"/>

测试:你会发现调用的是版本1的服务

八. 直连服务提供者

官网说的挺详细的,但是在开发中还是蛮重要的,所以我再提一下,官网给出了三种直连方案,通过 -D 参数指定,通过文件映射,通过 XML 配置,如图:

 

 

具体配置方法

通过 -D 参数指定(推荐)

就是项目启动时候设置直连的服务提供者,如图:

 

 

通过文件映射(推荐)

服务很多的情况下,可以用文件映射的形式,dubbo2.0 以上版本自动加载 ${user.home}/dubbo-resolve.properties文件,不需要配置。

${user.home}在电脑中位置如图所示:

 

dubbo-resolve.properties中的配置参数为:

 

 

通过 XML 配置(不推荐)

配置方式如图:

 

 

 

注解的配置方式:

 

 

 

九.负载均衡

dubbo提供了四种负载均衡策略:

random(随机), roundRobin(轮询), leastActive(最少活跃调用数), consistentHash (一致性 Hash)。默认为随机模式。

 

l  随机 Random

这是默认的,顾名思义,就是按权重随机访问。

轮询

l  按权重轮询访问 RoundRobin

l  最少活跃调用数 LeastActive

l   一致性 Hash ConsistentHash

这里按照请求的参数来计算hash,相同参数的请求总是发到同一提供者。

配置

服务端服务级别

<dubbo:service interface="..." loadbalance="roundrobin" />

客户端服务级别

<dubbo:reference interface="..." loadbalance="roundrobin" />

服务端方法级别

<dubbo:service interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:service>

客户端方法级别

<dubbo:reference interface="...">
    <dubbo:method name="..." loadbalance="roundrobin"/>
</dubbo:reference>

 

怎么设置权重值呢?很简单,在admin中设置:

 

 

 

 

点击倍权就是之前的权重增加一倍,半权就是权重削减一半。

九. 本地存根

远程调用后,有时候服务的提供方也想在服务的消费方执行一些比如,提前验证一些参数,不符合要求的情况下制造一些容错数据返回给用户,避免不必要的远程调用对系统资源的消耗。那么本地存根就是解决这个问题的。

#定义一个本地存根,最好在api接口下写

public class DemoServiceStub implements DemoService{
    private DemoService demoService;

    public DemoServiceStub(DemoService demoService) {
        this.demoService = demoService;
    }

    @Override
    public String sayHello(String name) {
        System.out.println(name);
        return demoService.sayHello(name);
    }

    @Override
    public Student getStudent(int id) {
        System.out.println(id);
        return demoService.getStudent(id);
    }
}

#消费端或者服务端配置本地存根

在消费端或者提供端配置存根

消费端的配置

<dubbo:reference id="demoService" stub="com.zy.dao.DemoServiceStub" interface="com.zy.dao.DemoService" timeout="3000" version="1.0.0"/>

1

服务端的配置

<dubbo:service interface="com.zy.dao.DemoService" ref="demoService" version="1.0.0" stub="com.zy.dao.DemoServiceStub"/>

 

建议在服务端做配置,感觉在消费端做配置意思不大,因为个人感觉完全可以在消费者调用服务者的时候可以在代码里进行逻辑判断,从而决定要不要调用服务的提供方。

十一. 服务降级

当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。这个时候可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。

降级策略

服务降级策略分为两种,一种是mock=force:return+null另一种是mock=fail:return+null,这里贴出官方给出的解释:

 

mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null

值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。

mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null

值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

mock=force:return+null的实现,直接在管理后台点击屏蔽,即屏蔽对远程的调用,直接返回空,如图:

 

 


mock=fail:return+null的实现,在管理后台点击容错,即服务出现报错的情况下返回空,不报异常,如图:

 

 

十二.集群容错

在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。

dubbo提供了以下几种集群容错模式:

 

l  Failover Cluster

官方解释:

失败自动切换,当出现失败,重试其它服务器 。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。

解释说明:

很好理解,当调用失败的时候自动重试其它服务器在有限次数之内,直到成功才停止调用。

配置方法:

<dubbo:service retries=“2” /> 或:

<dubbo:reference retries=“2” />

或:

< dubbo:reference />

<dubbo:method name=“findFoo” retries=“2” /> </dubbo:reference>

 

l  Failfast Cluster

官方解释:

快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

解释说明:

意思系统只发一次请求,无论成功失败仅一次调用。

配置方法:

<dubbo:service cluster=“failfast” /> 或:

<dubbo:reference cluster=“failfast” />

 

l  Failsafe Cluster

官方解释:

失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

配置方法:

<dubbo:service cluster=“failsafe” /> 或:

<dubbo:reference cluster=“failsafe” />

 

l  Failback Cluster

官方解释:

失败自动恢复,后台记录失败请求,会生成一个定时器每5秒扫描哟没有调用失败的实例,定时重发。通常用于消息通知操作。

配置方法:

<dubbo:service cluster=“failback” /> 或:

<dubbo:reference cluster=“failback” />

 

l  Forking Cluster

官方解释:

并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。

配置方法:

<dubbo:service cluster=“forking" />

或:

<dubbo:reference cluster=“forking" />

 

l  Broadcast Cluster

官方解释:

广播调用所有提供者,逐个调用,任意一台报错则报错 。通常用于通知所有提供者更新缓存或日志等本地资源信息。

配置方法:

<dubbo:service cluster=“broadcast " />

或:

<dubbo:reference cluster=“broadcast " />

十三.只订阅

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

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

禁用注册配置

<dubbo:registry address="10.20.153.10:9090" register="false" />

 

 

十四。只注册

只注册正好跟前面的只订阅相反,这个时候可以向注册中心注册,但是,消费端却不能够读到服务,如果有两个镜像环境,两个注册中心,有一个服务只在其中一个注册中心有部署,另一个注册中心还没来得及部署,而两个注册中心的其它应用都需要依赖此服务。这个时候,可以让服务提供者方只注册服务到另一注册中心,而不从另一注册中心订阅服务。

<dubbo:registry id="qdRegistry" address="10.20.141.150:9090" subscribe="false" />

十五.超时设置

由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。

Provider可以配置的Consumer端主要属性有timeout、retries、loadbalance、actives和cluster。应尽量多配置在Consumer端的属性,

Dubbo消费端

全局超时配置

<dubbo:consumer timeout="5000" />

 

指定接口以及特定方法超时配置

<dubbo:reference interface="com.foo.BarService" timeout="2000">

    <dubbo:method name="sayHello" timeout="3000" />

</dubbo:reference>

 

Dubbo服务端

全局超时配置

<dubbo:provider timeout="5000" />

 

指定接口以及特定方法超时配置

<dubbo:provider interface="com.foo.BarService" timeout="2000">

    <dubbo:method name="sayHello" timeout="3000" />

</dubbo:provider>

十六.dubbo的注册中心

Dubbo目前支持4种注册中心,(multicast,zookeeper,redis,simple) 推荐使用Zookeeper注册中心。

Multicast:不需要启动任何中心节点,只要广播地址一样,就可以互相发现。提供方启动时广播自己的地址。消费方启动时广播订阅请求。提供方收到订阅请求时,单播自己的地址给订阅者,如果设置了unicast=false,则广播给订阅者。消费方收到提供方地址时,连接该地址进行RPC调用。

Zookeeper:依靠目录树结构,发布提供者在节点下写url地址,消费者订阅url

Redis:key/value键值对提供服务地址

Simple:只适合简单实现,不支持集群。

十七.dubbo支持的几种序列化协议

序列化,就是把数据结构或者是一些对象,转换为二进制串的过程。

1、dubbo 协议

 

默认就是走 dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。

 

为了要支持高并发场景,一般是服务提供者就几台机器,但是服务消费者有上百台,可能每天调用量达到上亿次!此时用长连接是最合适的,就是跟每个服务消费者维持一个长连接就可以,可能总共就 100 个连接。然后后面直接基于长连接 NIO 异步通信,可以支撑高并发请求。消费者一般多于服务者,防止了压垮提供者服务。

 

长连接,通俗点说,就是建立连接过后可以持续发送请求,无须再建立连接。

 

 

 

2、rmi 协议

 

走 Java 二进制序列化,多个短连接,适合消费者和提供者数量差不多的情况,适用于文件的传输,一般较少用。

 

3、hessian 协议

 

走 hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多的情况,适用于文件的传输,一般较少用。

 

4、http 协议

 

走 json 序列化。

 

5、webservice

 

走 SOAP 文本

 

dubbo 支持的序列化协议?

 

dubbo 支持 hession、Java 二进制序列化、json、SOAP 文本序列化多种序列化协议。但是 hessian 是其默认的序列化协议。

 

说一下 Hessian 的数据结构?

 

Hessian 的对象序列化机制有 8 种原始类型:

原始二进制数据

boolean

64-bit date(64 位毫秒值的日期)

64-bit double

32-bit int

64-bit long

null

UTF-8 编码的 string

 

另外还包括 3 种递归类型:

list for lists and arrays

map for maps and dictionaries

  • object for objects

 

还有一种特殊的类型:

ref:用来表示对共享对象的引用。

 

为什么 PB 的效率是最高的?

 

可能有一些同学比较习惯于 JSON or XML 数据存储格式,对于 Protocol Buffer 还比较陌生。Protocol Buffer 其实是 Google 出品的一种轻量并且高效的结构化数据存储格式,性能比 JSON、XML 要高很多。

 

其实 PB 之所以性能如此好,主要得益于两个:第一,它使用 proto 编译器,自动进行序列化和反序列化,速度非常快,应该比 XML 和 JSON 快上了 20~100 倍;第二,它的数据压缩效果好,就是说它序列化后的数据量体积小。因为体积小,传输起来带宽和速度上会有优化。

 

 

以上是关于dubbo教程的主要内容,如果未能解决你的问题,请参考以下文章

markdown 打字稿...编码说明,提示,作弊,指南,代码片段和教程文章

Dubbo视频教程《基于Dubbo的分布式系统架构视频教程》----课程列表

dubbo视频教程解压版今日免费送!!!

分布式RPC系统框架-Dubbo(2.7)教程,分布式dubbo教程下载百度云

Dubbo限流源码分析

dubbo教程-09-dubbo分布式事务 ? 看看dubbo作者怎么说 !