SpringBoot整合Dubbo的第一种方式——application.properties + @DubboService + @DubboReference

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: SpringBoot整合Dubbo的第一种方式——application.properties + @DubboService + @DubboReference

1.文档参照


dubbo配置官方文档

2.三个工程


2.1 公共接口工程

这个工程中存放的是一些公共的Java Bean、相关接口信息。

其中UserService接口是针对服务提供者的,OrderService接口是针对服务消费者的。

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
</dependency>
package com.szh.gmall.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
 *
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserAddress implements Serializable {
    private Integer id;
    private String userAddress; //用户地址
    private String userId;      //用户id
    private String consignee;   //收货人
    private String phoneNum;    //电话号码
    private String isDefault;   //是否为默认地址 Y-是 N-否
}
package com.szh.gmall.service;
import com.szh.gmall.bean.UserAddress;
import java.util.List;
/**
 *
 */
public interface UserService {
    /**
     * 根据用户id返回所有的收货地址
     */
    List<UserAddress> getUserAddressList(String userId);
}
package com.szh.gmall.service;
import com.szh.gmall.bean.UserAddress;
import java.util.List;
/**
 *
 */
public interface OrderService {
    /**
     * 初始化订单
     */
    void initOrder(String userId);
    List<UserAddress> initOrder2(String userId);
}

2.2 服务提供者工程

springboot这里我使用的是 2.3.12.RELEASEdubbo2.7.8

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- Dubbo Spring Boot Starter -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>com.szh</groupId>
            <artifactId>common-gmall-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

那么在这个服务提供者中,我们肯定要对上面公共接口中的UserService进行具体的实现。  下面有两个实现类是为了后面测试Dubbo的多版本功能(也即version属性信息)。 @DubboService注解用来暴露服务。

package com.szh.service.impl;
import com.szh.gmall.bean.UserAddress;
import com.szh.gmall.service.UserService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
 * 1.将服务提供者注册到注册中心
 *      1) 引入dubbo依赖、zookeeper客户端依赖
 *      2) 配置服务提供者
 * 2.让服务消费者从注册中心订阅服务提供者的相关服务
 */
@Service
@DubboService(interfaceClass = UserService.class, version = "1.0.0")
public class UserServiceImpl implements UserService {
    //The default value of ${dubbo.application.name} is ${spring.application.name}
    @Value("${dubbo.application.name}")
    private String applicationName;
    @Override
    public List<UserAddress> getUserAddressList(String userId) {
        UserAddress userAddress1 = new UserAddress(1, "浙江省杭州市", "1", "张三", "123456", "Y");
        UserAddress userAddress2 = new UserAddress(2, "湖北省武汉市", "1", "李四", "999999", "N");
        try {
            TimeUnit.MILLISECONDS.sleep(2000); //测试timeout
//            TimeUnit.MILLISECONDS.sleep(4000); //测试重试次数
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(applicationName + " old....");
        return Arrays.asList(userAddress1, userAddress2);
    }
}
package com.szh.service.impl;
import com.szh.gmall.bean.UserAddress;
import com.szh.gmall.service.UserService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
 * 1.将服务提供者注册到注册中心
 *      1) 引入dubbo依赖、zookeeper客户端依赖
 *      2) 配置服务提供者
 * 2.让服务消费者从注册中心订阅服务提供者的相关服务
 */
@Service
@DubboService(interfaceClass = UserService.class, version = "2.0.0")
public class UserServiceImpl2 implements UserService {
    //The default value of ${dubbo.application.name} is ${spring.application.name}
    @Value("${dubbo.application.name}")
    private String applicationName;
    @Override
    public List<UserAddress> getUserAddressList(String userId) {
        UserAddress userAddress1 = new UserAddress(1, "浙江省杭州市", "1", "张三", "123456", "Y");
        UserAddress userAddress2 = new UserAddress(2, "湖北省武汉市", "1", "李四", "999999", "N");
        try {
            TimeUnit.MILLISECONDS.sleep(2000); //测试timeout
//            TimeUnit.MILLISECONDS.sleep(4000); //测试重试次数
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(applicationName + " new....");
        return Arrays.asList(userAddress1, userAddress2);
    }
}


properties配置文件如下,这种方式主要也就是 properties + 注解。 

spring.application.name=boot-user-service-provider
dubbo.application.name=boot-user-service-provider
dubbo.scan.base-packages=com.szh.service.impl
dubbo.registry.address=127.0.0.1:2181
dubbo.registry.protocol=zookeeper
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.monitor.protocol=registry

主启动类上添加 @EnableDubbo注解开启Dubbo的注解配置功能。  

package com.szh;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class BootUserServiceProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootUserServiceProviderApplication.class, args);
    }
}

2.3 服务消费者工程

这里是一个springboot web工程,版本仍然和上面的服务提供者相同。dubbo2.7.8

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Dubbo Spring Boot Starter -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.8.0</version>
        </dependency>
        <dependency>
            <groupId>com.szh</groupId>
            <artifactId>common-gmall-interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

这里我们要通过浏览器访问具体的接口,所以需要一个controller

package com.szh.controller;
import com.szh.gmall.bean.UserAddress;
import com.szh.gmall.service.OrderService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
 *
 */
@RestController
public class OrderController {
    @Autowired
    private OrderService orderService;
    @GetMapping(value = "/initOrder/{userId}")
    public List<UserAddress> initOrder(@PathVariable("userId") String userId) {
        return orderService.initOrder2(userId);
    }
}

然后需要对公共接口工程中的OrderService进行实现,因为这是服务消费者。(要表示如何消费,即实现接口就可以了)

@DubboReference注解用来引用服务。

package com.szh.service.impl;
import com.szh.gmall.bean.UserAddress;
import com.szh.gmall.service.OrderService;
import com.szh.gmall.service.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Method;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 *
 */
@Service
public class OrderServiceImpl implements OrderService {
    @DubboReference(interfaceClass = UserService.class, //服务接口名
                    version = "2.0.0", //服务版本,与服务提供者的版本一致
                    check = false,  //启动时检查提供者是否存在,true报错,false忽略
                    timeout = 3000, //服务方法调用超时时间(毫秒)
                    methods = @Method(name = "getUserAddressList"), //精确到服务接口的某个方法
                    retries = 3) //远程服务调用重试次数,不包括第一次调用,不需要重试请设为0
    private UserService userService;
    @Override
    public List<UserAddress> initOrder2(String userId) {
        System.out.println("用户id:" + userId);
        List<UserAddress> addressList = userService.getUserAddressList(userId);
        return addressList;
    }
    @Override
    public void initOrder(String userId) {
    }
}
server.port=8081
spring.application.name=boot-order-service-consumer
dubbo.application.name=boot-order-service-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.monitor.protocol=registry

主启动类上添加 @EnableDubbo注解开启Dubbo的注解配置功能。 

package com.szh;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo
public class BootOrderServiceConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootOrderServiceConsumerApplication.class, args);
    }
}


3.启动测试


启动服务提供者和消费者之前,要先将zookeeper开启,然后再将dubbo管控台打开。

我这里为了方便,就直接在windows下启动zookeeper了,下载请移步官网:https://zookeeper.apache.org/,下载解压之后,找到conf目录下的zoo.cfg文件,做如下修改:

# example sakes.
dataDir=E:\\zookeeper\\zookeeper-3.4.11\\data
# the port at which the clients will connect
clientPort=2181

然后转到bin目录下,cmd启动 zkServer.cmd 即可。

zookeeper相关配置等链接参考:https://dubbo.apache.org/zh/docs/references/registry/zookeeper/

这里需要先启动服务提供者,再启动服务消费者。 


由于我们在服务消费者的 @DubboReference 注解中配置了 check=false,所以这里即使启动顺序不对,或者找不到服务提供者,也不会报错,而是直接忽略。


下面是dubbo的管控台,这个不安装也无所谓,我这里就不给出下载安装的步骤了。。。(可以参考尚硅谷-雷神老师的Dubbo课程)


下面通过服务消费者中的接口,可以直接调用到服务提供者的接口,同时获取到相关数据内容。 


下面的截图是对应了服务提供者中的 TimeUnit.MILLISECONDS.sleep(2000); //测试timeout 代码。和服务消费者中的 @DubboReference 注解中的timeout属性。

如果服务提供者睡眠时间超过了服务消费者中定义的超时时间,那么就会出现下图的异常。

反之,则可以正常远程调用服务提供者的接口,也就是下下张图。


下面的截图演示的是重试次数,远程服务调用重试次数,不包括第一次调用,不需要重试请设为0


对应的是服务提供者  TimeUnit.MILLISECONDS.sleep(4000); //测试重试次数。和服务消费者中的 @DubboReference 注解中的 retries 属性。


这里需要保证服务提供者的响应时间大于服务消费者的等待超时时间,一旦满足,服务消费者此时调不到服务提供者,那么在服务提供者方就会进行重试。


最后这个测试的Dubbo的多版本问题。也就是用到了服务提供者中的两个具体实现类,这二者通过 @DubboService 注解中的 version 加以区分,一个版本为1.0.0、另一个版本为2.0.0  而在服务消费者中通过  @DubboReference 注解中的version属性来指定具体要消费服务提供者的哪个实现类。


4.Dubbo配置原则



JVM启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。

XML次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。

Properties最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名。

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
6月前
|
Dubbo Java 应用服务中间件
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
|
10天前
|
Dubbo Java 应用服务中间件
深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案
本文深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案。通过检查GraalVM版本兼容性、配置反射列表、使用代理类、检查配置文件、禁用不支持的功能、查看日志文件、使用GraalVM诊断工具和调整GraalVM配置等步骤,帮助开发者快速定位并解决问题,确保服务的正常运行。
26 1
|
1月前
|
监控 Dubbo Java
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
这篇文章详细介绍了如何将Spring Boot与Dubbo和Zookeeper整合,并通过Dubbo管理界面监控服务注册情况。
79 0
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
|
2月前
|
消息中间件 NoSQL 安全
(转)Spring Boot加载 不同位置的 application.properties配置文件顺序规则
这篇文章介绍了Spring Boot加载配置文件的顺序规则,包括不同位置的application.properties文件的加载优先级,以及如何通过命令行参数或环境变量来指定配置文件的名称和位置。
|
3月前
|
Dubbo Java Nacos
【实战攻略】破解Dubbo+Nacos+Spring Boot 3 Native打包后运行异常的终极秘籍——从零开始彻底攻克那些让你头疼不已的技术难题!
【8月更文挑战第15天】Nacos作为微服务注册与配置中心受到欢迎,但使用Dubbo+Nacos+Spring Boot 3进行GraalVM native打包后常遇运行异常。本文剖析此问题及其解决策略:确认GraalVM版本兼容性;配置反射列表以支持必要类和方法;采用静态代理替代动态代理;检查并调整配置文件;禁用不支持的功能;利用日志和GraalVM诊断工具定位问题;根据诊断结果调整GraalVM配置。通过系统排查方法,能有效解决此类问题,确保服务稳定运行。
98 0
|
5月前
|
Dubbo Java 应用服务中间件
Spring Boot 调用 Dubbo 接口与编写 Dubbo 接口实战
Spring Boot 调用 Dubbo 接口与编写 Dubbo 接口实战
619 1
|
4月前
|
消息中间件 Java 数据库连接
理解java的springboot+mybatisplus+dubbo+nacos+kafka这一套技术栈
理解java的springboot+mybatisplus+dubbo+nacos+kafka这一套技术栈
88 0
|
6月前
|
SQL 监控 Java
nacos常见问题之dubbo+nacos+springboot3的native打包成功后运行出现异常如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
333 2
|
6月前
|
Dubbo Java 应用服务中间件
Spring Boot整合Dubbo+Zookeeper实现RPC调用
Spring Boot整合Dubbo+Zookeeper实现RPC调用 技术栈说明 Dubbo:Dubbo作为RPC框架,能在多个服务之间实现远程服务的调用。比如有两个独立的微服务A和B,A服务想要调用B服务时,因为两者不在同个内存空间中,不能直接调用,所以可以通过Dubbo实现这点。 功能和Spring Cloud的Feign相同,两者都是应用于微服务架构的远程调用框架 Zookeeper:作为注册中心去管理Dubbo服务,这点和Eureka、Nacos相同。 概述 通过一个示例说明Dubbo+Zookeeper在Spring Boot中的应用。 现有两个服务provider和con
180 4
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
143 1