dubbo的springboot集成

1.什么是dubbo?

Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。

以上是官方的解释,我个人的理解,dubbo作为一个RPC服务开发框架,除了满足我微服务之间远程调用的目的之外,还能有以下几个重要的点。

1.和nacos等注册中心,完成dubbo接口服务的服务发现,消费方调用接口无需关注服务端的ip、端口

2.和sentinel集成,可以完成限流和熔断的目的

3.dubbo实现了多个负载均衡算法,只需yml文件配置即可。

4.dubbo和seata可以很方便的集成,轻松达到业务数据一致性的目的。

2.dubbo的常用注解

@EnableDubbo:创建Springboot启动类,需添加@EnableDubbo注解,开启Dubbo自动配置功能

@DubboService:Dubbo会将对应的服务注册到spring, 在spring启动后调用对应的服务导出方法,将服务注册到注册中心, 这样Consumer端才能发现我们发布的服务并调用(与spring的@Service注解作用类似)

@DubboReference:通过@DubboReference注解对需要调用的服务进行引入。即可像调用本地方法一样调用远程服务了。(和spring的@Autowired功能类似)

*注@DubboService 和**@DubboReference**的version参数和group参数的值必须一致。这两个参数可以确定一个实现类,接口一般可以有多个实现类的,多个实现类可以通过version和group参数进行区分。

3.代码示例

示例需要三个工程,一个接口定义、一个服务端,一个消费端。

maven依赖的版本号取决于项目使用的springboot版本及springcloud版本,我使用的版本如下:

XML 复制代码
<!-- SpringBoot的依赖配置-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.6.11</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2021.0.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2021.0.4.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-bom</artifactId>
                <version>3.0.9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

3.1接口示例代码

工程名称:dubbo-demo-interface

实体类必须实现序列化接口,因为在远程调用时,实体类数据是序列化后传输的

java 复制代码
package com.jc.shop.dubbo.demo.domain;

/**
 * 用户表
 */
public class User implements java.io.Serializable{

    /**
     * 主键ID
     */
    private long id;

    /**
     * 用户名称
     */
    private String name;

    /**
     * 所属部门
     */
    private long deptId;

    /**
     * 岗位
     */
    private String post;

    private Dept dept;

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getDeptId() {
        return deptId;
    }

    public void setDeptId(long deptId) {
        this.deptId = deptId;
    }

    public String getPost() {
        return post;
    }

    public void setPost(String post) {
        this.post = post;
    }
}

接口定义:

java 复制代码
package com.jc.shop.dubbo.demo.service;

import com.jc.shop.dubbo.demo.domain.User;

/**
 * 业务接口
 */
public interface IUserService {


    public int insert(User user);
}

3.2服务端示例

服务端工程名:dubbo-demo-provider

jar包依赖,maven

XML 复制代码
        <!-- dubbo与spring集成,可实现dubbo的自动初始化 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>

        <!-- 实现将dubbo的服务注册到nacos -->
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>

        <!-- nacos的相关依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <!-- 加载bootstrap.yml文件 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

        <!-- 引入接口层jar包 -->
        <dependency>
            <groupId>com.jc</groupId>
            <artifactId>dubbo-demo-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

yml配置

bash 复制代码
dubbo:
  application:
    name: dubbo-provider
  protocol:  #dubbo协议信息
    name: dubbo
    host: 127.0.0.1
    port: 20881

  registry:
    address: nacos://localhost:8848  #使用nacos作为注册中心

服务层的代码实现:

java 复制代码
package com.jc.shop.dubbo.demo.service.impl;

import com.jc.shop.dubbo.demo.domain.User;
import com.jc.shop.dubbo.demo.mapper.UserMapper;
import com.jc.shop.dubbo.demo.service.IUserService;
import io.seata.core.context.RootContext;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 业务层接口,@Service注解不用加,因为我在当前工程的controller中需要调用,所以加了@Service注解
 */
@Service
@DubboService(version = "1.0.0",loadbalance = "leastactive")//负载策略为"最少活跃优先 + 加权随机"
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper mapper;

    @Override
    public int insert(User user) {
        //以下打印信息是为了集成seata框架的,可忽略,本次不涉及seata框架内容
        System.out.println("用户新增的事务ID为:"+ RootContext.getXID());
        return mapper.insert(user);
    }
}

在当前工程的启动类中,添加@EnableDubbo注解,开启dubbo配置的自动配置功能:

java 复制代码
package com.jc;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class DubboProviderApplication {
    public static void main(String[] args) {
        //以下4个变量的设置是为了避免同一台机器,启动多个dubbo服务,缓存默认使用的同一个地址会报错。
        System.setProperty("dubbo.meta.cache.filePath","/media/zhangzz/localDisk/home/zhangzz/dubbo/provider/");
        System.setProperty("dubbo.meta.cache.fileName","provider");

        System.setProperty("dubbo.mapping.cache.filePath","/media/zhangzz/localDisk/home/zhangzz/dubbo/provider/");
        System.setProperty("dubbo.mapping.cache.fileName","provider1");
        SpringApplication.run(DubboProviderApplication.class,args);
    }
}

3.3消费端代码示例

消费端工程名:dubbo-demo-consumer

maven依赖配置:

XML 复制代码
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>3.2.7</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

yml配置:

bash 复制代码
dubbo:
  application:
    name: dubbo-consumer
  protocol:  #dubbo协议信息
    name: dubbo
    port: -1   # -1表示端口随机
  registry:
    address: nacos://localhost:8848  #nacos地址

业务层代码调用:

java 复制代码
package com.jc.shop.dubbo.demo.service.impl;

import com.jc.shop.dubbo.demo.domain.User;
import com.jc.shop.dubbo.demo.service.IConsumerService;
import com.jc.shop.dubbo.demo.service.IUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

@Service
public class ConsumerServiceImpl implements IConsumerService {


    @DubboReference(version = "1.0.0")  //版本号需和服务端一致,若有group,也需保持一致
    private IUserService userService;

    @Override
    public int insertUser(User user) {

        int j = userService.insert(user);
        System.out.println("用户新增,影响行数:"+j);


        return j;
    }
}

controller层代码:

java 复制代码
package com.jc.shop.dubbo.demo.controller;

import com.jc.core.domain.AjaxResult;
import com.jc.shop.dubbo.demo.domain.User;
import com.jc.shop.dubbo.demo.service.IConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/demo")
public class DemoController {


    @Autowired
    private IConsumerService service;

    @PostMapping("/insert")
    public AjaxResult insert(@RequestBody User user){

        int i = service.insertUser(user);
        if(i>0) {
            return AjaxResult.success("success");
        }else{
            return AjaxResult.error();
        }
    }
}

应用启动类:

java 复制代码
package com.jc;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class DubboConsumerApplication {
    public static void main(String[] args) {
        System.setProperty("dubbo.meta.cache.filePath","/media/zhangzz/localDisk/home/zhangzz/dubbo/consumer/");
        System.setProperty("dubbo.meta.cache.fileName","consumer");

        System.setProperty("dubbo.mapping.cache.filePath","/media/zhangzz/localDisk/home/zhangzz/dubbo/consumer/");
        System.setProperty("dubbo.mapping.cache.fileName","consumer1");
        SpringApplication.run(DubboConsumerApplication.class,args);
    }
}

启动之后,访问http://localhost:8082/demo/insert地址

4.与sentinel集成

集成的配置可参考《sentinel-单机流量控制》或《sentinel-集群流量控制》,此处不再赘述。此处只说明下限流、熔断的资源名称如何定义:

以我的代码为例,规则定义如下:

java 复制代码
FlowRule flowRule = new FlowRule(IUserService.class.getName())
        .setCount(10)
        .setGrade(RuleConstant.FLOW_GRADE_QPS);
FlowRuleManager.loadRules(Collections.singletonList(flowRule));

由以上代码可以看出,资源名称是类的全路径"com.jc.shop.dubbo.demo.service.IUserService",一般我们的流控规则都是在nacos中配置,由代码动态加载。nacos中的配置如下:

javascript 复制代码
[
    {
        "resource":"com.jc.shop.dubbo.demo.service.IUserService", 
        "limitApp":"default",  
        "grade":1,            
        "count":1,            
        "strategy":0,         
        "controlBehavior":0,  
        "clusterMode":false
    }
]

官方文档传送门:dubbo与Sentinel集成的限流示例

5.负载均衡

目前 Dubbo 内置了如下负载均衡算法,用户可直接配置使用:

算法 特性 备注 配置值
Weighted Random LoadBalance 加权随机 默认算法,默认权重相同 random (默认)
RoundRobin LoadBalance 加权轮询 借鉴于 Nginx 的平滑加权轮询算法,默认权重相同, roundrobin
LeastActive LoadBalance 最少活跃优先 + 加权随机 背后是能者多劳的思想 leastactive
Shortest-Response LoadBalance 最短响应优先 + 加权随机 更加关注响应速度 shortestresponse
ConsistentHash LoadBalance 一致性哈希 确定的入参,确定的提供者,适用于有状态请求 consistenthash
P2C LoadBalance Power of Two Choice 随机选择两个节点后,继续选择"连接数"较小的那个节点。 p2c
Adaptive LoadBalance 自适应负载均衡 在 P2C 算法基础上,选择二者中 load 最小的那个节点 adaptive

5.1 使用方式

@DubboService(loadbalance = "leastactive")

@DubboReference(loadbalance = "leastactive")

服务端方法级别的负载配置:

@DubboService(method={@Method(name="insert",loadbalance = "leastactive")})

消费端方法级别的负载配置:

@DubboReference(method={@Method(name="insert",loadbalance = "leastactive")})

相关推荐
蓝田~4 分钟前
SpringBoot-自定义注解,拦截器
java·spring boot·后端
theLuckyLong5 分钟前
SpringBoot后端解决跨域问题
spring boot·后端·python
A陈雷6 分钟前
springboot整合elasticsearch,并使用docker desktop运行elasticsearch镜像容器遇到的问题。
spring boot·elasticsearch·docker
.生产的驴7 分钟前
SpringCloud Gateway网关路由配置 接口统一 登录验证 权限校验 路由属性
java·spring boot·后端·spring·spring cloud·gateway·rabbitmq
小扳10 分钟前
Docker 篇-Docker 详细安装、了解和使用 Docker 核心功能(数据卷、自定义镜像 Dockerfile、网络)
运维·spring boot·后端·mysql·spring cloud·docker·容器
v'sir20 分钟前
POI word转pdf乱码问题处理
java·spring boot·后端·pdf·word
李少兄24 分钟前
解决Spring Boot整合Redis时的连接问题
spring boot·redis·后端
冰逸.itbignyi1 小时前
SpringBoot之AOP 的使用
java·spring boot
码上一元5 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
计算机-秋大田5 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue