Springboot整合Dubbo

  • 一 .介绍
  • 背景
  • 什么是Dubbo和Zookeeper
  • 二. 调用实例搭建与测试
  • 框架搭建
  • 父项目
  • api模块
  • provider模块
  • consumer模块
  • 访问测试
  • 三 监控与管理
  • Dubbo Monitor
  • Dubbo Admin
  • 四 Dubbo 配置负载均衡
  • 什么是负载均衡
  • Dubbo 的内置负载均衡策略
  • Random (随机)
  • RoundRobin (轮询)
  • LeastActive (最少活跃)
  • ConsistentHash (一致性哈希)
  • 负载均衡测试案例搭建
  • 项目多启动修改
  • 指定负载均衡策略
  • 1. Consumer 注解配置
  • 2. Consumer配置文件配置
  • 3. Provider 注解配置
  • 4. Provider 配置文件配置
  • 指定权重配置
  • 1. 轮询策略配置权重
  • 2. 随机策略配置权重
  • 五 项目打包
  • 基于 SpringBoot 整合 Dubbo 的打包方式
  • 基于 Assembly 插件打包


一 .介绍

该博文所用到的所有软件包将会在底部以百度云形式分享

背景

在微服务/SpringCloud项目中, 我们通常会用到注册中心来注册服务和发布服务, 例如SpringCloud Netflix的 Eureka 和SpringCloud Alibaba的Nacos.
我们暂且不论他们的优劣, 而是来讨论另一个同样重要的问题 : 在单体架构或者soa(面向服务架构)的项目甚至是SpringBoot项目中我们该如何实现服务的发布和消费呢 —— 使用Dubbo+zookeeper, 作为注册中心来实现服务的注册和发布

什么是Dubbo和Zookeeper

  1. Dubbo

Dobbo技术, 他是一个高性能的服务框架 ,用于实现服务的输入和输出(服务注册和服务发现)。 它是基于面向服务的架构(SOA)与远程过程调用(RPC)的技术而研发的.

注意这里的dubbo只是一个框架,至于你架子上放什么是完全取决于你的,就像一个汽车骨架,你需要配你的轮子引擎。这个框架中要完成调度必须要有一个分布式的注册中心,储存所有服务的元数据,你可以用zk(zookeeper),也可以用别的, 但是官方推荐用zk。关于dubbo介绍

  1. Zookeeper

zookeeper技术, 它是一种分布式的开源的程序协调服务 .它的存储结构是树形结构, 包含四种类型的节点:持久化节点, 持久化顺序节点,临时节点和临时编号节点. 它的主要作用分为 :配置管理,名字服务,分布式锁与集群管理等

zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知道,简单来说就是ip地址和服务名称的对应关系。 zookeeper通过心跳机制可以检测挂掉的机器并将挂掉机器的ip和服务对应关系从列表中删除。至于支持高并发,简单来说就是横向扩展,在不更改代码 的情况通过添加机器来提高运算能力。通过添加新的机器向zookeeper注册服务,服务的提供者多了能服务的客户就多了。 关于zk介绍

  1. zookeeper和dubbo的关系
  • Dubbo的将注册中心进行抽象,使得它可以外接不同的存储媒介给注册中心提供服务,有ZooKeeper,Memcached,Redis等。
  • 引入了ZooKeeper作为存储媒介,也就把ZooKeeper的特性引进来。
    首先是负载均衡,单注册中心的承载能力是有限的,在流量达到一定程度的时 候就需要分流,负载均衡就是为了分流而存在的,一个ZooKeeper群配合相应的Web应用就可以很容易达到负载均衡;
    其次是资源同步,单单有负载均衡还不够,节点之间的数据和资源需要同步,ZooKeeper集群就天然具备有这样的功能;
    命名服务,将树状结构用于维护全局的服务地址列表,服务提供者在启动 的时候,向ZK上的指定节点/dubbo/${serviceName}/providers目录下写入自己的URL地址,这个操作就完成了服务的发布。 其他特性还有Mast选举,分布式锁等。
  • 注意: 一般使用dubbo都会使用zookeeper的, 因为zk集群能为我们提供服务的动态发布和集群间的负载均衡以及集群横向扩展等功能

二. 调用实例搭建与测试

代码地址 : https://gitee.com/TimePause/springboot_dubbo_project

项目整体结构

springboot dubbo 消费端请求超时_dubbo

框架搭建

如果直接使用gitee上面的代码, 需要 1. 手动创建父项目(空目录即可) 2. 然后点击右上角 File ->Project Structure -> 点击+ -> Import Modules-> 添加api,provider,consumer模块

springboot dubbo 消费端请求超时_ide_02

父项目

父项目(springboot-dubbo), 可以创建pom项目用于对jar进行管理, 也可以新建一个空项目/空目录, 在空目录下创建子模块项目. 这里是直接创建空的父项目

  • 步骤1: 退出原有项目: File->close project, 进入图1页面
  • 步骤2: 创建空的父项目: 点击Create New Project->选择Empty Project(图2)-> 填入项目名和目录地址

图1

springboot dubbo 消费端请求超时_spring_03


图2

springboot dubbo 消费端请求超时_spring boot_04

api模块

api模块(springboot-dubbo-api)作用规定服务接口样式, 用于其他模块实现和重写

步骤:

  1. 创建模块
    点击右上角File -> New -> module -> 选择新建的模块为 maven, 无需添加其他坐标
  2. 创建接口
package com.njhrt.service;

/**
 * dubbo被调用方接口
 *
 * @author caohaiyang
 */
public interface ProviderService {

    public String showMsg(String msg);
}

provider模块

provider模块(springboot-dubbo-provider)的作用是用于创建用于注册和发布的服务

步骤:

  1. 创建模块
    点击右上角File->New ->Project->选择SpringBoot initializr(快速构建springboot项目)->填写项目信息后点击 Next -> 选择需要导入的坐标 Spring Web(图2)即可
  2. springboot dubbo 消费端请求超时_spring boot_05

  3. pom文件添加坐标
<!--阿帕奇提供的springboot整合dubbo的依赖,其版本对应当前dubbo版本-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>
        <!--duboo整合zookeeper作为注册中心的依赖, 实际上dubbo还支持其他类型的注册中心-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>2.7.6</version>
        </dependency>
        <!--依赖api模块项目-->
        <dependency>
            <groupId>com.njhrt</groupId>
            <artifactId>springboot-dubbo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
  1. 修改properties配置文件
    需要我们安装zookeeper或者zookeeper集群, 教程地址 第二章: zookeeper的安装
#指定服务名称
dubbo.application.name=springboot-dubbo-provider
#指定zk注册中心地址, 集群版写法zookeeper://192.168.233.130:2181?backup=192.168.233.130:2182,192.168.233.130:2183
dubbo.registry.address=zookeeper://192.168.233.130:2181
dubbo.registry.timeout=10000
#指定服务使用协议和端口号
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
#指定dubbo接口实现类地址
dubbo.scan.base-packages=com.njhrt.provider.impl

yml格式配置如下

#指定服务的名称
dubbo:
  application:
    name: myProvider
  registry:
    address: zookeeper://118.195.183.138:2181?backup=118.195.183.138:2182,118.195.183.138:2183
    timeout: 10000
  #配置服务所使用的协议
  protocol:
    name: dubbo
    port: 20880
  scan:
    base-packages: com.njhrt.provider.impl

注意: 需要我们注意 dubbo.scan.base-packages 这个参数, 用于扫描服务接口实现类所在包地址. 我们要根据自己实际情况来配置

  1. 业务层实现类, 继承api模块接口样式
    注意: 导入的是dubbo下的@Service注解而不是springframework包下的@Service注解
import com.njhrt.service.ProviderService;
import org.apache.dubbo.config.annotation.Service;

/**
 * 服务提供者接口实现
 * 注意: 导入的是dubbo下的@Service注解
 *       而不是springframework包下的@Service注解
 * @author caohaiyang
 * @create 2021-05-08 下午 04:59
 */
@Service
public class ProviderServiceImpl implements ProviderService {

    @Override
    public String showMsg(String msg) {
        return "hello springboot duboo! "+msg;
    }
}
  1. 点击启动类启动,查看日志是否启动成功(图1), 然后登录zk查看发布的接口服务信息(图2)
    图1

    图2

consumer模块

consumer模块(springboot-dubbo-consumer)用于消费Ddubbo服务

步骤:

  1. 创建模块
    点击右上角File->New ->Project->选择SpringBoot initializr(快速构建springboot项目)->填写项目信息后点击 Next -> 选择需要导入的坐标 Spring Web(图2)即可
  2. pom文件添加坐标
<!--阿帕奇提供的springboot整合dubbo的依赖,其版本对应当前dubbo版本-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.6</version>
        </dependency>
        <!--duboo整合zookeeper作为注册中心的依赖, 实际上dubbo还支持其他类型的注册中心-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-zookeeper</artifactId>
            <version>2.7.6</version>
        </dependency>
        <!--依赖api模块项目-->
        <dependency>
            <groupId>com.njhrt</groupId>
            <artifactId>springboot-dubbo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
  1. 修改properties配置文件
#指定服务名称
dubbo.application.name=springboot-dubbo-consumer
#指定zk注册中心地址, 集群版写法zookeeper://192.168.233.130:2181?backup=192.168.233.130:2182,192.168.233.130:2183
dubbo.registry.address=zookeeper://118.195.183.138:2181?backup=1118.195.183.138:2182,118.195.183.138:2183
dubbo.registry.timeout=10000
#指定服务使用协议和端口号
dubbo.protocol.name=dubbo
  1. 创建用于规定消费者接口格式的接口类
public interface ConsumerService {

    public String getMsg(String Msg);
}
  1. 创建消费者实现类
    注意: @Service和@Reference锁导入的包
import com.njhrt.service.ProviderService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

/**
 * 消费服务业务层
 * 注意: 这里@Service 导入的是springframework的包而不是Dubbo
 * 区别:
 *     服务提供者(provider): @Service使用的是dubbo包下的
 *     服务消费者(consumer): @Service使用的是springframework包下的
 * @author caohaiyang
 * @create 2021-05-10 下午 04:10
 */
@Service
public class ConsumerServiceImpl implements ProviderService {

    //使用的是dubbo包下的@Reference
    @Reference
    private ProviderService providerService;

    @Override
    public String showMsg(String msg) {
        return this.providerService.showMsg(msg);
    }

}
  1. 创建消费者controller
@RestController
public class ConsumerController {

    @Autowired
    private ConsumerServiceImpl consumerServiceImpl;

    @RequestMapping("/getMsg/{msg}")
    public String getMsg(@PathVariable String msg){
        return this.consumerServiceImpl.showMsg(msg);
    }
}
  1. 点击启动类启动, 启动成功关键日志如下

访问测试

浏览器输入下面url进行访问

http://localhost:8080/getMsg/我成功啦

页面反馈访问结果如下图, 说明服务消费者消费发布的服务成功!!!

springboot dubbo 消费端请求超时_spring_06


三 监控与管理

Dubbo Monitor

Dubbo Admin为Dubbo框架监控提供了一个图形化界面, 方便我们对Dubbo进行监控
主要功能包括: 监控注册的服务, 注册中心, 日志, 软件运行环境等信息

使用步骤

  1. 下载安装包
  2. 修改配置文件
    主要是修改连接zk/zk集群地址, 以及图形化界面访问端口
  3. 在软件bin目录下, 点击start.bat(windows), 或者使用 ./start.sh (Linux), 启动Dobbo Monitor
  4. 访问
http://127.0.0.1:7777/

Dubbo Monitor主页功能展示

Menu Name

Menu Desc

Home

主页, 显示所有功能列表(图1)

Applications

显示dubbo服务角色关系(提供者, 消费者, 依赖情况, 使用情况), 图2

Services

显示注册中心注册的服务(图3)

Hosts

显示提供者和消费者所在主机及相关信息(图4)

Registries

显示注册中心状态和注册服务信息(图5)

Servers

显示导出的业务服务器(图6)

Status

显示系统状态(图7)

Log

显示Dubbo Admin日志(图8)

System

显示系统环境信息(图9)

图1

springboot dubbo 消费端请求超时_负载均衡_07

图2

springboot dubbo 消费端请求超时_spring boot_08

图3

springboot dubbo 消费端请求超时_spring_09


图4

springboot dubbo 消费端请求超时_dubbo_10


图5

springboot dubbo 消费端请求超时_spring_11

图6

springboot dubbo 消费端请求超时_负载均衡_12

图7

springboot dubbo 消费端请求超时_负载均衡_13


springboot dubbo 消费端请求超时_负载均衡_14


图9

springboot dubbo 消费端请求超时_spring boot_15

Dubbo Admin

Dubbo Admin为Dubbo框架管理提供了一个图形化界面, 方便我们对Dubbo进行管理
其主要功能包含:路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功能。

使用步骤

  1. 修改配置文件
    修改连接zk/zk集群地址以及dubbo admin图形化界面端口
    修改后保存即可生效, 如果保存失败了, 建议重启电脑
  2. 打开cmd, 然后输入你所在的盘跳转到文件所在盘 eg: d: , 在通过cd 文件所在目录 跳转到该jar目录, 最后通过java -jar dubbo-admin-server.jar 运行(也可上传至linux服务器上通过java -jar运行)
  3. 访问
    dubbo admin实际上是一个SpringBoot打包后的jar
    因此访问的端口取决与是否在第1步修改了其访问端口, 如果没有修改默认为 8080, 如果按照第1步的配置, 则访问的地址为: http://localhost:9999/ (默认以中文显示,通俗易懂)

springboot dubbo 消费端请求超时_dubbo_16


四 Dubbo 配置负载均衡

什么是负载均衡

负载均衡(Load Balance),是指将负载(工作任务,访问请求)进行平衡、分摊到多个操作单元(服务器,组件)上进行执行。

最常见的负载均衡场景

  • 常见场景是我们在网站上下载某软件时, 为我们提供的各种下载通道
    负载依赖用户手动选择下载通道. 这一种古老的方式,通过入口提供不同线路、不同服务器链接的方式,来实现负载均衡
  • 各种软件或者框架中配置
    Nginx 负载均衡, Dubbo负载均衡, SpringCloud Ribbon,Feign调用时的负载均衡, Dubbo Spring Cloud配置负载均衡, emq 消息队列配置消息消费的负载均衡

注意: Dubbo Spring Cloud 构建在原生的 Spring Cloud 之上,其服务治理方面的能力可 认为是 Spring Cloud Plus,不仅完全覆盖 Spring Cloud 原生特性,而且提供更为稳定和成熟 的实现

负载均衡解决方案分类及特征

  • 集中式负载均衡
    即在客户端和服务端之间使用独立的负载均衡设施(可以是硬件,如 F5, 也可以是软件, 如 nginx), 由该设施负责把访问请求通过某种策略转发至服务端
  • 进程内负载均衡
    将负载均衡逻辑集成到服务组件中,服务组件从服务注册中心获知有哪些地址可用,然后根据指定的负载均衡策略选择出一个合适的服务来调用。

集中式负载均衡方式

  • 基于硬件的负载均衡
    硬件负载均衡解决方案是直接在服务器和外部网络间安装负载均衡设备,这种设备通常称之为负载均衡器,由专门的设备完成专门的任务,独立于操作系统,整体性能得到大大提高,加上多样化的负载均衡策略,智能化的流量管理,可达到最佳的负载均衡需求。
    常见的主流产品: F5 BIG-IP 负载均衡器(LTM),思科 IOS 路由器以及Radware 的 AppDirector 系列
  • DNS 轮询
    大多域名注册商都支持 DNS 轮询,DNS 服务器将解析请求按照配置顺序,逐一分配到不同的 IP 上,这样就完成了简单的负载均衡。
  • 反向代理负载均衡
    使用代理服务器,可以将请求转发给内部的服务器。Nginx 是比较常见的服务反向代理 技术。在 Nginx 中是支持对代理的服务的负载均衡处理的

进程内负载均衡方式

  • 基于注册中心 / 消息队列的集中式负载均衡
    将负载均衡逻辑集成到服务组件中,服务组件从服务注册中心获知有哪些地址可用,然 后根据指定的负载均衡策略选择出一个合适的服务来调用

Dubbo 的内置负载均衡策略

需要注意的是, 在后续进行配置时, 配置的策略名称就是下面的标题名称, 但是要注意的是在填写dubbo配置参数时所有字母都要小写

Random (随机)

随机访问集群中节点。访问概率和权重有关。是 Dubbo 的默认负载均衡策略。 权重(weight):占有比例。集群中每个项目部署的服务器的性能可能是不同,性能好的服务器权重应该高一些

RoundRobin (轮询)

访问频率和权重有关, 如果未配置权重, 则访问则是一一访问

LeastActive (最少活跃)

最少活跃调用数,相同活跃数的随机。 如果某个机器性能越差,那么接收的请求越少,越不活跃,此时就会给不活跃的性能差的机器分配更少的请求

ConsistentHash (一致性哈希)

一致性 Hash 算法,相同参数的请求一定分发到同一个 Provider 如果需要某一类请求都到一个节点,那么可以使用一致性 Hash 策略

负载均衡测试案例搭建

在基于第二章的基础上进行配置, 添加多个服务提供者, 并且在每个服务上面添加标记然后启动, 通过多次访问消费者接口来进行消费和测试
代码地址 : https://gitee.com/TimePause/springboot_dubbo_project

项目多启动修改

  1. 为了能够让idea能够启动多个服务提供者项目, 需要修改idea的启动配置
  2. 复制启动配置
    复制后修改启动项名称, 这里复制了两个 SpringbootDubboProviderApplication-2, SpringbootDubboProviderApplication-3
  3. 修改复制后的启动配置
    需要注意的是, 原有的无需配置, 二在复制后的配置中, 需要重新配置连接的dubbo端口–dubbo.protocol.port=20881 , --dubbo.protocol.port=20882 如果是多个参数, 中间以空格隔开, eg: --server.port=8082 --dubbo.protocol.port=20882
  4. 在编辑好启动项参数后, 依次进行启动
    但是在启动时, 为了我们能够区分消费者到底消费的是哪个服务, 我们需要在提供的服务接口上面打印一句话. 每次启动一个服务前就修改下打印的内容
  5. 启动服务消费者, 进行访问测试
    在浏览器多次刷新服务消费者接口http://localhost:8080/getMsg/testLoadBalance 可以看到每个服务的负载情况(因为没有配置, 默认策略为随机, 当次数足够多时, 最终访问的频率会趋向于一致)

指定负载均衡策略

1. Consumer 注解配置

除非配置权重, 否则无需向provider配置其他参数即可使策略生效

随机策略配置
在provider项目的@Reference注解中添加loadbalance 参数, 指定负载均衡参数@Reference(loadbalance = "random ")

package com.njhrt.consumer.service.impl;

import com.njhrt.service.ProviderService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

/**
 * 消费服务业务层
 * 注意: 这里@Service 导入的是springframework的包而不是Dubbo
 * 区别:
 *     服务提供者(provider): @Service使用的是dubbo包下的
 *     服务消费者(consumer): @Service使用的是springframework包下的
 * @author caohaiyang
 */
@Service
public class ConsumerServiceImpl implements ProviderService {

    /**
     * 使用的是dubbo包下的@Reference
     *      dubbo服务级别
     *         1. 权重随机算法的 RandomLoadBalance、
     *         2. 基于最少活跃调用数算法的 LeastActiveLoadBalance、
     *         3. 基于 hash 一致性的 ConsistentHashLoadBalance,
     *         4. 以及基于加权轮询算法的 RoundRobinLoadBalance。
     * 对应负载均衡策略参数: random,leastactive,consistenthash,roundrobin
     */
    @Reference(loadbalance = "random ")
    private ProviderService providerService;

    @Override
    public String showMsg(String msg) {
        return this.providerService.showMsg(msg);
    }

}

轮询策略配置

在provider项目的@Reference注解中添加loadbalance 参数, 指定负载均衡参数@Reference(loadbalance = "roundrobin")

package com.njhrt.consumer.service.impl;

import com.njhrt.service.ProviderService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

/**
 * 消费服务业务层
 * 注意: 这里@Service 导入的是springframework的包而不是Dubbo
 * 区别:
 *     服务提供者(provider): @Service使用的是dubbo包下的
 *     服务消费者(consumer): @Service使用的是springframework包下的
 * @author caohaiyang
 */
@Service
public class ConsumerServiceImpl implements ProviderService {

    /**
     * 使用的是dubbo包下的@Reference
     *      dubbo服务级别
     *         1. 权重随机算法的 RandomLoadBalance、
     *         2. 基于最少活跃调用数算法的 LeastActiveLoadBalance、
     *         3. 基于 hash 一致性的 ConsistentHashLoadBalance,
     *         4. 以及基于加权轮询算法的 RoundRobinLoadBalance。
     * 对应负载均衡策略参数: random,leastactive,consistenthash,roundrobin
     */
    @Reference(loadbalance = "roundrobin")
    private ProviderService providerService;

    @Override
    public String showMsg(String msg) {
        return this.providerService.showMsg(msg);
    }

}
2. Consumer配置文件配置

除非配置权重, 否则无需向provider配置其他参数即可使策略生效

在 SpringBoot 的配置文件中可以配置全局的负载均衡。Consumer 中所有调用 Provider 集群的业务层都会使用该负载均衡策略。

与注解配置方式区别:

  • 注解配置方式:
    局部,只针对当前业务层生效。
  • 配置文件方式:
    全局,对所有业务层生效。
  • 全局配置(配置文件)的优先级低于局部配置(注解配置 )
#配置负载均衡策略  random, roundrobin, leastactive, consistenthash
dubbo.consumer.loadbalance=random
#配置负载均衡策略  random, roundrobin, leastactive, consistenthash
dubbo.consumer.loadbalance=roundrobin
3. Provider 注解配置

在Provider配置负载均衡策略之后, Consumer也无需配置负载策略即可使策略生效

在 Provider的@Service 注解中配置负载均衡策略, 如需配置权重, 直接在注解后配置即可 @Service(loadbalance = "random",weight = 4)

@Service(loadbalance = "random")
public class ProviderServiceImpl implements ProviderService {

    @Override
    public String showMsg(String msg) {
        //System.out.println("调用测试duboo负载均衡服务1");
        //System.out.println("调用测试duboo负载均衡服务2");
        System.out.println("调用测试duboo负载均衡服务3");
        return "hello springboot duboo! "+msg;
    }
4. Provider 配置文件配置

在Provider配置负载均衡策略之后, Consumer也无需配置负载策略即可使策略生效

直接在SpringBoot的配置文件application.properties中配置

#全局配置(配置文件)的优先级低于局部配置(注解配置)
dubbo.provider.loadbalance=.loadbalance=roundrobin
dubbo.provider.weight=2

指定权重配置

这里使用的是 Provider 注解配置的权重, 当然我们也可以使用 Provider 配置文件配置权重

1. 轮询策略配置权重

如果我们将等量的请求分配给性能较差的服务器,这显然是不合理的。因此,这个时候我们需要对轮询过程进行加权,以调控每台服务器的负载。经过加权后,每台服务器能够得到的请求数比例,接近或等于他们的权重比

配置方式

通过 Provider 的@Service 注解配置权重 @Service(weight = 权重数)

@Service(weight = 4)
public class ProviderServiceImpl implements ProviderService {

    @Override
    public String showMsg(String msg) {
        //System.out.println("调用测试duboo负载均衡服务1");
        //System.out.println("调用测试duboo负载均衡服务2");
        System.out.println("调用测试duboo负载均衡服务3");
        return "hello springboot duboo! "+msg;
    }
}
2. 随机策略配置权重

随机获取一个[0, totalWeight)之间的数, offset = offset - weight,如果 offset 小于 0,则选中.
很明显 weight 大的更容易让 offset 的值小于 0。 举个例子 有 4 权重分别为(1,2, 3, 4),
totalWeight = 10, 假如 offset = 6, 6 - 1 = 5, 5 大于 0,
继续 5 - 2 = 3 大于 0,3 - 3 = 0, 0 - 4 小于 0 ,所以选择权重为 4 的 invoker,
这里可以发现只要 offset >= 6 则选择权重为 4 的 invoker, 正好是 40%。
权重的值是可以随便配置的, 系统会自动计算权重和

配置方式

通过 Provider 的@Service 注解配置权重 @Service(weight = 权重数)

@Service(weight = 4)
public class ProviderServiceImpl implements ProviderService {

    @Override
    public String showMsg(String msg) {
        //System.out.println("调用测试duboo负载均衡服务1");
        //System.out.println("调用测试duboo负载均衡服务2");
        System.out.println("调用测试duboo负载均衡服务3");
        return "hello springboot duboo! "+msg;
    }
}

五 项目打包

在项目打包时, 需要明确:

  1. SpringBoot项目中, 可以使用其自带的打包插件进行打包
  2. 在基于Maven或者是Maven+Spring项目中, 需要手动添加Assembly进行打包

基于 SpringBoot 整合 Dubbo 的打包方式

  1. 只需确认当前SpringBoot项目的pom文件下, 是否有 spring-boot-maven-plugin插件坐标, 如果没有需要添加
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
  1. 在idea右侧竖向工具条中, 找到maven选项, 然后找到需要打包的SpringBoot项目. 在Lifecycle 中点击 install 进行打包
  2. 如果打包出现下面错误, 则说明在打包时把在test文件打入jar时运行出现问题(没有则跳过)
    解决方法:1. 使其跳过编译时的测试 2. 去掉spring-boot-starter-test 坐标
Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.2:test (default-test) on project springboot-dubbo-consumer: There are test failures.

Please refer to D:\work-code\springboot-dubbo\springboot-dubbo-consumer\target\surefire-reports for the individual test results.
Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.

springboot dubbo 消费端请求超时_dubbo_17


解决方式1:

idea:

界面中选择右边的Maven projects 界面,在界面中有一排按钮选择如下图红框中按钮(Toggle ‘Skip Tests’ Mode),此时按钮就是选中状态;

springboot dubbo 消费端请求超时_dubbo_18


myeclipse:

在debug Configurations 中选择你项目的Maven build,在其右边选中Skip Tests

springboot dubbo 消费端请求超时_spring boot_19


解决方式2:

springboot dubbo 消费端请求超时_spring_20

  1. 找到相关jar, 通过 java -jar jar包名称 命令运行即可

基于 Assembly 插件打包

Assembly 插件 Assembly是Maven打包插件,他的作用是可以帮助我们对jar项目做打包处理。
在Spring 整合 dubbo 的项目中,需要使用 Assembly 打包插件来对项目做打包处理。

打包步骤

  1. 在项目根下创建一个目录,名称为 assembly
  2. 将dubbo-monitor-simple-2.5.3 中 bin,conf 目录拷贝到 assembly 的根目录中
    相关文件百度云将会分享至博客最下方
  3. 删除 conf 目录中 dubbo.properties 配置文件中的内容
    dubbo.properties原来配置的是dubbo-monitor中的配置, 因此需要删除
  4. 修改项目的 POM 文件添加 assembly 的打包插件
<build>
		<plugins>
			<!-- 指定项目的打包插件信息, maven install 特性变更. 变化为-打包. -->
			<plugin>
				<artifactId>maven-assembly-plugin</artifactId>
				<configuration>
					<!-- 指定打包描述文件的位置:相对项目根目录的路径 -->
					<!-- assembly打包的描述文件 -->
					<descriptor>assembly/assembly.xml</descriptor>
				</configuration>
				<executions>
					<execution>
						<id>make-assembly</id>
						<!-- 要执行的功能. 打包. -->
						<phase>package</phase>
						<goals>
							<goal>single</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
  1. 在 assembly 目录下添加 assembly.xml 配置文件
<?xml version='1.0' encoding='UTF-8'?>
<assembly
	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
	<!-- 该字符会添加到最终tar.gz包的名称后面,作为后缀
		当前应用 : homework-provider-impl
		打包后 : homework-provider-impl-assembly.gar.gz
	 -->
	<id>assembly</id>
	<!-- 指定打包的格式为tar.gz,该类型压缩包在linux中比较常见 -->
	<formats>
		<format>tar.gz</format>
	</formats>
	<!-- 在tar.gz压缩包中是否包含根文件夹,该根文件夹名称和tar.gz去掉id后缀一致 -->
	<includeBaseDirectory>true</includeBaseDirectory>
	<fileSets>
		<!-- 将项目根路径下assembly/bin路径中的内容打包到压缩包中的根目录下的bin目录中 -->
		<fileSet>
			<!-- 相对项目根路径的相对路径 -->
			<directory>assembly/bin</directory>
			<outputDirectory>bin</outputDirectory>
			<!-- 设置最终tar.gz中该文件夹下的权限,跟linux权限写法一致 -->
			<fileMode>0755</fileMode>
		</fileSet>
		<!-- 将项目根路径下assembly/conf路径中的内容打包到压缩包中的根目录下的conf目录中 -->
		<fileSet>
			<directory>assembly/conf</directory>
			<outputDirectory>conf</outputDirectory>
			<!-- 设置其linux权限 -->
			<fileMode>0644</fileMode>
		</fileSet>
	</fileSets>
	<!-- 将所有依赖的jar包打包到压缩包中的根目录下的lib目录中 -->
	<!-- 此lib目录中包含自己开发的项目jar包以及demo_service.jar,还有第三方的jar包 -->
	<dependencySets>
		<dependencySet>
			<outputDirectory>lib</outputDirectory>
		</dependencySet>
	</dependencySets>
</assembly>
  1. 运行打包插件,对项目进行打包处理。
    可以使用 maven 的 install 命令,也可以使用插件的命令
  2. 修改 start.sh 或 start.bat 中配置信息,将启动类修改为当前 dubbo 版本的启动类
    找到下面这行参数, 确定启动参数 org.apache.dubbo.container.Main是否是和自己当前Dubbo的启动类所在包一致, 如果不一致则修改
nohup java $JAVA_OPTS $JAVA_MEM_OPTS $JAVA_DEBUG_OPTS $JAVA_JMX_OPTS -classpath $CONF_DIR:$LIB_JARS org.apache.dubbo.container.Main > $STDOUT_FILE 2>&1 &

springboot dubbo 消费端请求超时_负载均衡_21