Dubbo的使用,看这篇就够了

Dubbo

文章目录

  • Dubbo
    • 一、Dubbo概述
    • 二、Dubbo运行示例
    • 三、序列化
    • 四、地址缓存
    • 五、超时
    • 六、重试
    • 七、多版本
    • 八、负载均衡
    • 九、集群容错
    • 十、服务降级

一、Dubbo概述

  1. Dubbo是一个Java RPC框架,用于提供高性能的远程服务调用方案和SOA服务治理方案

简单来说,Dubbo用于给消费方提供调用接口 (将接口注册到注册中心中)

  1. Dubbo运行流程图

Dubbo的使用,看这篇就够了_第1张图片

节点角色说明:

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

  1. Dubbo运行流程文字解释

(1) 启动容器,加载运行服务提供方
(2) 提供方启动时,在注册中心注册自己提供的服务
(3) 消费方启动时,在注册中心订阅自己需要的服务
(4) 注册中心用于管理提供方提供的url;ZooKeeper是Dubbo推荐使用的注册中心
(5) 监控中心管理整个过程

  1. 考虑失败或变更的情况

(1) 注册中心返回提供方地址列表给消费方,如果有变更,注册中心推送变更数据给消费方
(2) 消费方从提供方地址列表中,选择一台提供者进行调用,如果调用失败,选择另一台
(3) 消费方和提供方在内存中记录调用次数和调用时间,每分钟发送一次统计数据给监控中心

二、Dubbo运行示例

创建两个模块,一个作为提供方,一个作为消费方,通过Dubbo来实现消费方远程调用服务方提供 的服务,分别启动双方,进行测试

注意:要求双方都是可独立运行的war项目,并不是通过maven依赖调用提供方的服务

Dubbo的使用,看这篇就够了_第2张图片

  1. 双方都需要使用的接口的开发

将接口作为独立模块的原因:

(1) 提供方需要实现此接口定义具体的方法(服务),因而需要定义此接口
(2) 消费方需要定义此接口从而调用接口中的方法(使用此接口提供的服务)

导致双方对此接口的定义重复,一旦接口改动,双方修改繁琐,故将公用接口作为独立模块

package com.itheima.service;

public interface UserService {
     

    public String sayHello();
}
//并且需要将此模块install成为jar包


Dubbo的使用,看这篇就够了_第3张图片

  1. 提供方开发

(1) pom.xml文件中的内容

<groupId>com.itheimagroupId>
<artifactId>dubbo-serviceartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>



<properties>
    <spring.version>5.1.9.RELEASEspring.version>
    <dubbo.version>2.7.4.1dubbo.version>
    <zookeeper.version>4.0.0zookeeper.version>
properties>

<dependencies>

    
    <dependency>
        <groupId>org.apache.dubbogroupId>
        <artifactId>dubboartifactId>
        <version>${dubbo.version}version>
    dependency>

    
    <dependency>
        <groupId>org.apache.curatorgroupId>
        <artifactId>curator-frameworkartifactId>
        <version>${zookeeper.version}version>
    dependency>
    <dependency>
        <groupId>org.apache.curatorgroupId>
        <artifactId>curator-recipesartifactId>
        <version>${zookeeper.version}version>
    dependency>

    
    <dependency>
        <groupId>com.itheimagroupId>
        <artifactId>dubbo-interfaceartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>

    
    
dependencies>

Dubbo的使用,看这篇就够了_第4张图片

(2) web.xml中的内容

<context-param>
    <param-name>contextConfigLocationparam-name>

    <param-value>classpath*:spring/applicationContext*.xmlparam-value>
context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>

(3) UserServiceImpl中的内容

//导入公共接口所在类的包
/**
 * 1. @Service注解是Dubbo包下的,并不是Spring包下的
 * 2. 使用了此注解的类提供的方法将会对外发布,并将访问地址,端口等注册到注册中心中
 */
@Service
public class UserServiceImpl implements UserService {
     
    @Override
    public String sayHello() {
     
        return "hello Dubbo !";
    }
}

(4) applicationContext.xml中的内容




<dubbo:application name="dubbo-service"/>


<dubbo:registry address="zookeeper://192.168.200.130:2181"/>


<dubbo:annotation package="com.itheima.service.impl" />

  1. 消费方开发

(1) pom.xml中的内容

<groupId>com.itheimagroupId>
<artifactId>dubbo-webartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>warpackaging>



<properties>
    <spring.version>5.1.9.RELEASEspring.version>
    <dubbo.version>2.7.4.1dubbo.version>
    <zookeeper.version>4.0.0zookeeper.version>
properties>

<dependencies>

    
    <dependency>
        <groupId>org.apache.dubbogroupId>
        <artifactId>dubboartifactId>
        <version>${dubbo.version}version>
    dependency>

    
    <dependency>
        <groupId>org.apache.curatorgroupId>
        <artifactId>curator-frameworkartifactId>
        <version>${zookeeper.version}version>
    dependency>
    <dependency>
        <groupId>org.apache.curatorgroupId>
        <artifactId>curator-recipesartifactId>
        <version>${zookeeper.version}version>
    dependency>

    
    <dependency>
        <groupId>com.itheimagroupId>
        <artifactId>dubbo-interfaceartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>

	

    
    
dependencies>


Dubbo的使用,看这篇就够了_第5张图片

(2) web.xml中的内容

   
   <servlet>
       <servlet-name>springmvcservlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
       <init-param>
           <param-name>contextConfigLocationparam-name>
           <param-value>classpath:spring/springmvc.xmlparam-value>
       init-param>
   servlet>
   <servlet-mapping>
       <servlet-name>springmvcservlet-name>
       <url-pattern>/url-pattern>
   servlet-mapping>

(3) UserController中的内容

//导入公共接口所在类的包
@RestController
@RequestMapping("/user")
public class UserController {
     
    /**
     * 1. @Reference注解导入的为Dubbo包
     * 2. @Reference注解作用:
     *    (1) 从zookeeper注册中心获取提供方的访问url
     *    (2) 进行远程调用RPC
     *    (3) 将结果封装为一个代理对象,赋值给userService对象
    */
    @Reference
    private UserService userService;

    @RequestMapping("/sayHello")
    public String sayHello(){
     
        return userService.sayHello();
    }
}

(4) springmvc.xml中的内容

<mvc:annotation-driven/>

<context:component-scan base-package="com.itheima.controller"/>



<dubbo:application name="dubbo-web" >
    
    
    <dubbo:parameter key="qos.port" value="33333"/>
dubbo:application>

<dubbo:registry address="zookeeper://192.168.200.130:2181"/>

<dubbo:annotation package="com.itheima.controller" />

  1. 运行结果

(1) 对service模块、web模块分别运行此指令,作为提供方和消费方的两个war项目

在这里插入图片描述

(2) web模块运行之后的日志信息如下

在这里插入图片描述

(3) 运行效果如下

在这里插入图片描述

三、序列化

当提供方(生产者)与消费方(消费者)需要传递Pojo类型时,需要使Pojo类实现IO包下的Serializable 接口,成为二进制流进行传输

四、地址缓存

  1. 问:当注册中心挂了之后,服务是否可以正常访问

  2. 答:可以;因为消费者在第一次调用服务时,会将生产者的地址缓存到本地,之后访问此地址时 不会再经过注册中心;当生产者的地址发生变化之后,注册中心通过notify机制通知消费者 新地址;
    注意:注册中心挂了之后,已经存在的消费者可以访问服务,但新的消费者将无法进行访问

五、超时

  1. 消费者在调用生产者的服务时,如果发生了阻塞、等待等情况,消费者会一直等待下去

  2. 在某个峰值时刻,如果大量的请求阻塞,会造成雪崩现象

  3. Dubbo使用超时机制解决此问题,设置一个超时时间,如果在此时间内无法完成服务的访问,则 自动断开连接,并报timeout错误

  4. 使用timeout属性配置超时时间,默认值1000,单位毫秒

//timeout属性设置超时时间,单位毫秒;
@Service(timeout = 3000)
  1. 消费者的@Reference注解也可使用timeout属性,但一般建议使用在生产者中,因为在生产者中 定义服务,可以预估需要的时间,方便进行超时设置

六、重试

  1. 设置了超时时间,在此时间内如果无法完成服务的调用,会自动断开连接并报错

  2. 如果出现网络抖动(网络不稳定短暂中断但很快恢复),则此次请求就会失败

  3. Dubbo使用重试机制避免此类问题的发生

  4. 通过retries属性设置重试次数,默认为两次(加上第一次的请求,共三次)

//retries属性设置重传次数
@Service(timeout = 3000, retries = 3)

七、多版本

  1. 当生产者的服务出现新版本时,并不会让所有的消费者访问此版本,而是会让一部分消费者先调 用此版本,确认没有问题之后再让所有消费者调用此版本,称为灰度发布

  2. Dubbo中使用version属性设置和调用同一个接口的不同版本

生产者代码:

@Service(version = "v1.0", timeout = 3000)
public class UserServiceImpl1 implements UserService {
     ...}

@Service(version = "v2.0")
public class UserServiceImpl2 implements UserService {
     ...}

消费者代码:

@Reference(version = "v2.0")
private UserService userService;
//成功调用v2.0版本的服务

八、负载均衡

  1. 消费者访问生产者集群,需要使用负载均衡策略,有四种:

(1) Random:默认策略;按权重设置随机概率,权重越高,越容易被访问
(2) RoundRobin:按请求先后轮询
(3) LeastActive:响应时间越短越容易被访问
(4) ConsistentHash:相同的请求总是调用同一个服务

注意:四种策略与Nginx的负载均衡策略类似

  1. 生产者配置,通过weight属性设置权重,默认值为100
@Service(weight = 200)
  1. 消费者配置,通过loadbalance属性设置策略,默认值为random
@Reference(loadbalance = "random")
@Reference(loadbalance = "roundrobin")
@Reference(loadbalance = "leastactive")
@Reference(loadbalance = "consistenthash")
  1. 注意:同一台机器上启动多个服务,需要修改以下两个端口,每个服务都不可相同,防止冲突

Dubbo的使用,看这篇就够了_第6张图片

九、集群容错

  1. 集群容错模式有以下几种:

(1) Failover Cluster: 默认模式;失败重试,默认重试两次,使用retries配置;当出现失败,报错, 并重试其它服务器两次,一般用于读操作,写操作可能由于延迟等导致写入数据重复

(2) Failfast Cluster : 快速失败;发起一次调用,如果失败立即报错,不会重试,通常用于写操作

(3) Failsafe Cluster: 失败安全,出现异常时,不报错,直接忽略,返回一个空结果

(4) Failback Cluster: 失败自动恢复;请求失败后,后台记录失败请求,定时重发

(5) Forking Cluster : 并行调用多个服务,只要一个成功即返回

(6) Broadcast Cluster: 广播调用所有提供者,逐个调用,任意一个调用失败则报错

  1. 消费者配置,使用cluster属性设置集群容错模式,默认值为failover
@Reference(cluster = "failover")

十、服务降级

  1. 当服务器压力较大时,根据实际情况,释放某些服务,仅保留核心服务以保证服务整体高效运作

  2. 服务降级方式有如下两种

(1) mock = force:return null:表示消费者对该服务的调用都是返回空值,相当于把服务屏蔽

(2) mock = fail:return null:表示消费方对该服务的调用在失败后(会重试),再返回空值,不报错

  1. 消费方配置,使用mock属性设置服务降级方式
@Reference(mock = "force : return null")

你可能感兴趣的:(SOA架构,分布式,java,spring,linux,zookeeper)