Dubbo-2.7.x学习简单概要(一)

1.springboot+dubbo

工程结构
在这里插入图片描述
项目依赖

<?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>com.wernch</groupId>
    <artifactId>spring-dubbo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>spring-dubbo-interface</module>
        <module>spring-dubbo-provider</module>
        <module>spring-dubbo-consumer</module>
    </modules>


    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <dubbo-version>2.7.8</dubbo-version>
        <spring-boot.version>2.3.0.RELEASE</spring-boot.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Apache Dubbo  -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-dependencies-bom</artifactId>
                <version>${dubbo-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo</artifactId>
                <version>${dubbo-version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>javax.servlet</groupId>
                        <artifactId>servlet-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- Dubbo Spring Boot Starter -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo-version}</version>
        </dependency>
        <!-- Dubbo核心组件 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <!--Spring Boot 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <!-- Zookeeper客户端框架 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.0.1</version>
        </dependency>
        <!-- Zookeeper dependencies -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>${dubbo-version}</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
</project>

spring-dubbo-interface 通过dubbo需要远程调用的接口

/**
 * @author xmz
 */
public interface OrderService {
    /**
     * 获取订单详情
     * @param orderId
     * @return
     */
    String getOrder(Long orderId);
}

spring-dubbo-provider 服务提供方

    <dependencies>
        <!-- Dubbo Spring Boot Starter -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo-version}</version>
        </dependency>
        <!-- Dubbo 核心依赖 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <!-- 公用RPC接口依赖 -->
        <dependency>
            <groupId>com.wernch</groupId>
            <artifactId>spring-dubbo-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
/**
 * @author xmz
 * @date 2022/11/28 13:02
 */
@SpringBootApplication
public class DubboProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboProviderApplication.class,args);
    }
}
@DubboService(
        version = "${dubbo.spring.provider.version}"
)
public class OrderServiceImpl implements OrderService {

    /**
     * 服务端口
     */
    @Value("${server.port}")
    private String serverPort;

    /**
     * 获取订单详情
     * @param orderId
     * @return
     */
    public String getOrder(Long orderId) {
        System.out.println("Service:"+serverPort);
        return "Get Order Detail, Id: " + orderId + ", serverPort: " + serverPort;
    }
}
server:
  port: 18090
dubbo:
  protocol:
    name: dubbo
    port: -1
  scan:
    base-packages: com.wrench
    ## Dubbo 注册器配置信息
  registry:
    address: zookeeper://127.0.0.1:2181
    file:  ${user.home}/dubbo-cache/${spring.application.name}/dubbo.cache
  spring:
    provider:
      version: 1.0.0
  application:
    name: spring-dubbo-provider # 必须设置的属性

spring-dubbo-consumer 服务消费方

<dependencies>
    <!-- Dubbo Spring Boot Starter -->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>${dubbo-version}</version>
    </dependency>
    <!-- 公用RPC接口依赖 -->
    <dependency>
        <groupId>com.wernch</groupId>
        <artifactId>spring-dubbo-interface</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>
@SpringBootApplication
public class DubboConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DubboConsumerApplication.class, args);
    }
}
@Controller
public class OrderController {

    private final Logger logger = LoggerFactory.getLogger(getClass());


    /**
     * 订单服务接口
     */
    @DubboReference(version = "${dubbo.spring.provider.version}")
    private OrderService orderService;

    /**
     * 获取订单详情接口
     * @param orderId
     * @return
     */
    @RequestMapping("/getOrder")
    @ResponseBody
    public String getOrder(Long orderId) {
        String result = orderService.getOrder(orderId);
        return result;
    }
}
server:
  # 服务端口
  port: 18091
dubbo:
  registry:
    # 消费端注册器配置信息
    address: zookeeper://127.0.0.1:2181
    file:  ${user.home}/dubbo-cache/${spring.application.name}/dubbo.cache
#服务版本号
  spring:
    provider:
      version: 1.0.0
spring:
  application:
    #服务名称
    name: spring-dubbo-consumer # 必须设置的属性

在未启动provider时候启动consumer,consumer启动报错解决方法

   @DubboReference(
            version = "${dubbo.spring.provider.version}",
            lazy = true
    )

2.Dubbo高阶配置运用

2.1 不同配置覆盖关系

在这里插入图片描述

配置规则:

  • 方法级优先,接口级次之,全局配置再次之。
  • 如果级别一样,则消费方优先,提供方次之。

2.1.1 服务端超时设定

服务端超时配置

@Configuration
public class DubboConfig {

    /***
     * 服务端全局配置
     */
    @Bean
    public ProviderConfig registryConfig(){
        ProviderConfig config = new ProviderConfig();
        //全局超时时间 1s
        config.setTimeout(1000);
        return config;
    }
}

对某个接口

    @DubboReference(
            version = "${dubbo.spring.provider.version}"
            ,methods = {
                    @Method(name = "getOrder",timeout = 1000)
            }
    )
    private OrderService orderService;

客户端超时配置

全局

@Configuration
public class DubboConfig {


    /***
     * 客户端全局配置
     */
    @Bean
    public ConsumerConfig config(){
        ConsumerConfig config = new ConsumerConfig();
        config.setTimeout(4000);
        return config;
    }
}

对某个方法

@DubboService(
        version = "${dubbo.spring.provider.version}"
        ,timeout = 1000
        ,methods = {
                //某个方法超时配置
                @Method(name = "getOrder",timeout = 2000)
        }
)
public class OrderServiceImpl implements OrderService {
    /**
     * 服务端口
     */
    @Value("${server.port}")
    private String serverPort;

    /**
     * 获取订单详情
     * @param orderId
     * @return
     */
    public String getOrder(Long orderId) {
        if(orderId==4){
            try {
                //TimeUnit.SECONDS.sleep(1500);
                Thread.sleep(900);
            } catch (Exception e) {
            }
        }else if(orderId==5){
            throw new RuntimeException("哈哈哈");
        }
        System.out.println("Service:"+serverPort);
        return "Get Order Detail, Id: " + orderId + ", serverPort: " + serverPort;
    }
}

2.2 属性配置优先级

优先级规则
在这里插入图片描述

优先级从高到低:

  • JVM -D 参数;(运行时为了改变对应的配置)
  • XML(application.yml/application.properties)配置会重写 dubbo.properties 中的;(经常变动的属性)
  • dubbo.properties默认配置,仅仅作用于以上两者没有配置时。 (全局属性)

2.3 重试与容错处理机制

  1. 容错机制:
  • Failfast Cluster
    • 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
  • Failsafe Cluster
    • 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
  • Failback Cluster
    • 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
  • Forking Cluster
    • 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。
  • Broadcast Cluster
    • 广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。

调整客户端重试次数
默认情况下重试两次
@DubboService注解重试默认值

修改重试次数(consumer)

    @DubboReference(
            version = "${dubbo.spring.provider.version}",
            //重试次数
            retries = 3
    )
     private OrderService orderService;

2.4 负载均衡

  1. 默认负载策略

Dubbo默认采用的是随机负载策略。
开启三个服务节点,通过消费端访问验证: http://127.0.0.1:18091/getOrder?orderId=123通过控制后台日志输出, 可以看到每个服务节点呈现不规则的调用。

  1. Dubbo 支持的负载均衡策略(默认的负载均衡策略为random)
    • Random LoadBalance

    随机,按权重设置随机概率。 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

    • RoundRobin LoadBalance

    轮询,按公约后的权重设置轮询比率。 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

    • LeastActive LoadBalance

    最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

    • ConsistentHash LoadBalance

    一致性 Hash,相同参数的请求总是发到同一提供者。 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

    • dubbo在2.7.7以上支持最短时间算法(ShortestResponse LoadBalance)

    上次响应的时间最短(最快),下次请求依然到那台机器去

源码实现: org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance

Dubbo提供了四种实现:

  • 2.7.7以下
    在这里插入图片描述
  • 2.7.7以下
    在这里插入图片描述

客户端配置负载均衡
方式一

    /***
    * 客户端全局配置
    */
   @Bean
   public ConsumerConfig config(){
       ConsumerConfig config = new ConsumerConfig();
       //config.setTimeout(4000);

       //负载均衡
       config.setLoadbalance("roundrobin");   //轮询
       //config.setLoadbalance("random");   //随机
       //config.setLoadbalance("consistenthash");   //Hash
       //config.setLoadbalance("leastactive");   //平均处理效率最高的节点优先
       return config;
   }

方式二

    @DubboReference(
            version = "${dubbo.spring.provider.version}"
            //随机,具有权重随机
            ,loadbalance = "random"
    )

服务端
方式一

   @Bean
    public ProviderConfigconfig(){
        ConsumerConfig config = new ConsumerConfig();
        //config.setTimeout(4000);

        //负载均衡
        config.setLoadbalance("roundrobin");   //轮询
        //config.setLoadbalance("random");   //随机
        //config.setLoadbalance("consistenthash");   //Hash
        //config.setLoadbalance("leastactive");   //平均处理效率最高的节点优先
        return config;
    }

方式二

@DubboService(
        version = "${dubbo.spring.provider.version}",
        loadbalance = "random"
)
  1. 四种配置方式:

优先级从下至上:
服务端的服务级别>客户端的服务级别>服务端方法级别>客户端方法级别:

  1. 调用验证
    修改客户端的负载策略, 改为轮询策略:
@DubboReference(version = "${dubbo.spring.provider.version}",
retries = 3,
loadbalance = "roundrobin")

开启三个服务节点, 进行访问验证: http://127.0.0.1:18091/getOrder?orderId=123会依次轮询进行调用。

  1. 动态权重调整验证
    使用Dubbo admin 进行权重配置
    管理后台地址: http://127.0.0.1:8080/#
    通过管理后台修改服务的权重配置:
    在这里插入图片描述调整权重
    在这里插入图片描述
    调整后可以看到权重配置已经生效:
    在这里插入图片描述代码中设置权重
    以客户端为例
    @Bean
    public ProviderConfig registryConfig(){
        ProviderConfig config = new ProviderConfig();
        config.setWeight(100);
        return config;
    }

2.5 多版本控制

  1. 启动三个服务端
    第一个服务端版本为1.0.0, 第二个服务端版本为2.0.0。
    修改application.yml配置:
dubbo:
	spring:
		provider:
			version: 1.0.0
  1. 消费端指定版本号为2.0.0
    修改application.properties配置:
#服务版本号
dubbo:
	spring:
		provider:
			version: 2.0.0

在注解中指定调用的版本程序
@DubboReference(version = “2.0.0”)

2.6 本地存根调用

  1. 远程调用前执行本地存根类似拦截器
    在这里插入图片描述
  2. 客户端存根实现(一般接口中进行编写)
public class OrderServiceStub implements OrderService {

    //代理对象->Proxy->Remote($Proxy)
    private final OrderService orderService;

    public OrderServiceStub(OrderService orderService) {
        this.orderService = orderService;
    }

    /***
     * 订单查询
     * @param orderId
     * @return
     */
    @Override
    public String getOrder(Long orderId) {
        if(orderId!=null){
            //远程调用
            return orderService.getOrder(orderId);
        }
        return "本地校验不合法....";
    }
}
  1. 修改客户端调用配置(哪里调用哪里写对应的数据)
    //本地存根使用
    @DubboReference(
            version = "${dubbo.spring.provider.version}",
            //指定本地存根
            stub = "com.wrench.dubbo.stub.OrderServiceStub"
    )
    private OrderService orderService;

注:stub要配置存根接口的完整路径。

2.7 服务降级运用

服务发生异常,进行友好提示

  1. 服务动态禁用
    启动单个服务节点,进入Dubbo Admin, 创建动态配置规则:
    在这里插入图片描述
    将disabled属性设为true, 服务禁用
configVersion: v2.7
enabled: true
configs:
  - side: provider
    addresses:
      - '0.0.0.0:20881'
    parameters:
      timeout: 6000
      disabled: true

将disabled属性改为false

configVersion: v2.7
enabled: true
configs:
  - side: provider
    addresses:
      - '0.0.0.0:20881'
    parameters:
      timeout: 6000
      disabled: false
  1. 服务降级
    https://dubbo.apache.org/zh/docsv2.7/user/examples/service-downgrade/
    降级 Dubbo 服务

可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。

向注册中心写入动态配置覆盖规则:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf(“zookeeper://10.20.153.10:2181”));
registry.register(URL.valueOf(“override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null”));

其中:

  • mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来
    屏蔽不重要服务不可用时对调用方的影响。

  • 还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

    @DubboReference(
            version = "${dubbo.spring.provider.version}",mock = "force:return null"
    )
@DubboService(
        version = "${dubbo.spring.provider.version}",mock = "mock=fail:return null"
)

提示
2.2.0 以上版本支持

2.8 并发与连接控制

实际运用, 会碰到高并发与峰值场景, Dubbo是可以做到并发与连接数控制。

并发数控制

  1. 服务端控制
  • 服务级别
//springboot配置方式
  @DubboService(
         version = "${dubbo.spring.provider.version}"
         ,executes = 10
  )
 public class OrderServiceImpl implements OrderService {
  		public String getOrder(Long orderId) {
 		........
		}
 }

<!---xml配置方式-->
<dubbo:service interface="com.xxx.OrderService " executes="10" />

服务器端并发执行(或占用线程池线程数)不能超过 10 个。

  • 方法级别
//springboot配置方式
@DubboService(
       version = "${dubbo.spring.provider.version}",
       executes = 10,
       methods = {
               //指定某个方法并发数量
               @Method(name = "getOrder",executes = 3)
       }
)
<!---xml配置方式-->
<dubbo:service interface="com.xxxx.OrderService ">
<dubbo:method name="getOrder" executes="3" />
</dubbo:service>

限制具体的方法,服务器端并发执行(或占用线程池线程数)不能超过 3 个。
优先级:方法的并发数设置优先服务的设置
全局的并发数(服务端示例)

  /***
    * 服务端全局配置
   */
   @Bean
   public ProviderConfig registryConfig(){
     ProviderConfig config = new ProviderConfig();
      //全局并发数量
      //config.setExecutes(100);
      return config;
   }
  1. 客户端控制
  • 调用的服务控制
//springboot配置方式
  @DubboReference(
         version = "${dubbo.spring.provider.version}"
         ,actives = 10
  )
 private OrderService orderService;

<!---xml配置方式-->
<dubbo:reference interface="com.xxx.BarService" actives="10" />

客户端并发执行(或占用线程池线程数)不能超过 10 个。

  • 方法级别
//springboot配置方式
@DubboService(
       version = "${dubbo.spring.provider.version}",
       actives= 10,
       methods = {
               //指定某个方法并发数量
               @Method(name = "getOrder",executes = 3)
       }
)
<!---xml配置方式-->
<dubbo:reference interface="com.xxx.OrderService ">
<dubbo:method name="getOrder" executes="3" />
</dubbo:reference >

客户端并发执行(或占用线程池线程数)不能超过 3 个。

限制具体的方法,客户端并发执行(或占用线程池线程数)不能超过 3 个。
优先级:方法的并发数设置优先服务的设置
全局的并发数(服务端示例)

  /***
    * 客户端全局配置
   */
   @Bean
   public ConsumerConfigregistryConfig(){
     ConsumerConfigconfig = new ConsumerConfig();
      //全局并发数量
      config.setActives(1000); 
      return config;
   }

客户端负载配置

  @DubboReference(
            version = "${dubbo.spring.provider.version}",
            loadbalance = "leastactive"
    )
    private OrderService orderService; 
<!--xml配置方式--->
<dubbo:reference interface="com.xxx.orderService" loadbalance="leastactive" />

负载策略为最小连接数时, Loadbalance 会调用并发数最小的 Provider。

连接数控制

  1. 服务端连接控制
@DubboService(
        version = "${dubbo.spring.provider.version}",
        connections= "10"
)
<dubbo:provider protocol="dubbo" accepts="10" />

限制服务器端接受的连接不能超过 10 个

  1. 客户端连接控制
 //本地存根使用
    @DubboReference(
            version = "${dubbo.spring.provider.version}",   
            connections = 10
    )
<dubbo:reference interface="com.xxx.OrderService " connections="10" />

限制客户端服务使用连接不能超过 10 个
如果 dubbo:service 和 dubbo:reference 都配了 connections,dubbo:reference 优先。
如果服务端和客户端都配置了连接数控制,那么客户端优先

dubbo官方文档:https://dubbo.apache.org

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值