在微服务整合dubbo,以为微服务版的若依为例
一、环境
微服务版若依3.6.3
dubbo2021.0.1
nacos2.2.1
二、整合过程
1、父模块依赖
xml
<?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.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>3.6.3</version>
<name>human</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<properties>
<ruoyi.version>3.6.3</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-boot.version>2.7.13</spring-boot.version>
<spring-cloud.version>2021.0.8</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>
<spring-boot-admin.version>2.7.10</spring-boot-admin.version>
<swagger.fox.version>3.0.0</swagger.fox.version>
<swagger.core.version>1.6.2</swagger.core.version>
<tobato.version>1.27.2</tobato.version>
<kaptcha.version>2.3.3</kaptcha.version>
<pagehelper.boot.version>1.4.7</pagehelper.boot.version>
<druid.version>1.2.16</druid.version>
<dynamic-ds.version>3.5.2</dynamic-ds.version>
<commons.io.version>2.11.0</commons.io.version>
<velocity.version>2.3</velocity.version>
<fastjson.version>2.0.34</fastjson.version>
<jjwt.version>0.9.1</jjwt.version>
<minio.version>8.2.2</minio.version>
<poi.version>4.1.2</poi.version>
<transmittable-thread-local.version>2.14.3</transmittable-thread-local.version>
<dubbo.version>2021.0.1.0</dubbo.version>
<hutool-all.version>5.8.16</hutool-all.version>
<lombok.version>1.18.24</lombok.version>
<minio.version>8.2.2</minio.version>
<guava.version>33.0.0-jre</guava.version>
</properties>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringCloud Alibaba 微服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringBoot 依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- FastDFS 分布式文件系统 -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>${tobato.version}</version>
</dependency>
<!-- Swagger 依赖配置 -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>${swagger.core.version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger.core.version}</version>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>pro.fessional</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.boot.version}</version>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- 代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version>
</dependency>
<!-- JSON 解析器和生成器 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!-- 线程传递值 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${transmittable-thread-local.version}</version>
</dependency>
<!-- 核心模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 接口模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 安全模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 权限范围 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datascope</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 多数据源 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 分布式事务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-seata</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 日志记录 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-log</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 缓存服务 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 系统接口 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api-system</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!-- hutool工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- Minio -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<!--这个依赖是整合dubbo时要用到的-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>ruoyi-auth</module>
<module>ruoyi-gateway</module>
<module>ruoyi-visual</module>
<module>ruoyi-modules</module>
<module>ruoyi-api</module>
<module>ruoyi-common</module>
</modules>
<packaging>pom</packaging>
<dependencies>
<!-- bootstrap 启动器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
2、生产者
因为我要调用若依的文件服务,所以直接将文件服务作为生产者。依赖如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-modules-file</artifactId>
<description>
ruoyi-modules-file文件服务
</description>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- FastDFS -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
</dependency>
<!-- RuoYi Api System -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api-system</artifactId>
</dependency>
<!-- RuoYi Common Swagger -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!-- hutool工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- Minio -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- RuoYi Common DataSource -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
</dependency>
<!-- RuoYi Common DataScope -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datascope</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
主要是这个依赖
xml
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
<version>2021.0.1.0</version>
</dependency>
先在文件服务的 bootstrap.yml 加上如下配置,解决循环引用
yaml
# Tomcat
server:
port: 9300
# Spring
spring:
application:
# 应用名称
name: ruoyi-file
main:
allow-circular-references: true # 中断循环引用
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
如何在nacos中对应的配置文件中添加如下配置:
yaml
# dubbo相关配置
dubbo:
protocol:
name: dubbo # dubbo协议
port: -1 # -1表示端口从20880开始递增,不会造成端口冲突
registry:
address: nacos://127.0.0.1:8848
# check: false # dubbo默认有启动检查
scan:
base-packages: com.ruoyi.file.service
接着在启动类中加上 @EnableDubbo 注解
接着是dubbo的接口,接口放在这里
具体如下:
java
package com.ruoyi.system.api;
import com.ruoyi.system.api.domain.SysFileInfo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* dubbo文件接口
*
* @author:gan
* @date: 2024-01-30 09:58
*/
public interface DubboFileService {
/**
* 文件上传接口原始
*
* @param file 上传的文件
* @return 访问地址
* @throws Exception
*/
String uploadFile(MultipartFile file) throws Exception;
/**
* 文件上传接口(自定义)
*
* @param file 上传的文件
* @param secondPath 文件二级路径
* @return 访问地址
* @throws Exception
*/
SysFileInfo upload(MultipartFile file, String secondPath) throws Exception;
/**
* 文件上传接口(自定义)
*
* @param file 上传的文件
* @return 访问地址
* @throws Exception
*/
SysFileInfo upload(MultipartFile file) throws Exception;
/**
* 根据文件id查询文件
* @param params
* @return
*/
List<SysFileInfo> getSysFileInfoList(SysFileInfo params);
}
对应的实现类
java
package com.ruoyi.file.service;
import com.ruoyi.system.api.DubboFileService;
import com.ruoyi.system.api.domain.SysFileInfo;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.List;
/**
* dubbo文件服务
*
* @author:gan
* @date: 2024-02-21 17:53
*/
@DubboService(version = "1.0.0")
public class DubboFileServiceImpl implements DubboFileService {
@Resource
private IMinioSysFileService minioSysFileService;
@Override
public String uploadFile(MultipartFile file) throws Exception {
return minioSysFileService.uploadFile(file);
}
@Override
public SysFileInfo upload(MultipartFile file, String secondPath) throws Exception {
return minioSysFileService.upload(file, secondPath);
}
@Override
public SysFileInfo upload(MultipartFile file) throws Exception {
return minioSysFileService.upload(file);
}
@Override
public List<SysFileInfo> getSysFileInfoList(SysFileInfo params) {
return minioSysFileService.getSysFileInfoList(params);
}
}
其实要用的方法都在 IMinioSysFileService 的实现类中写好了,这里只是为了使用 @DubboService 注解。
然后启动文件服务
再查看nacos中的服务列表
可以看到生产者已经启动成功了。
3、消费者
在 ruoyi-modules 模块下新建了一个 名为 common-test 的模块作为消费者,依赖如下:
xml
<?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">
<parent>
<artifactId>ruoyi-modules</artifactId>
<groupId>com.ruoyi</groupId>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common-test</artifactId>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- RuoYi Api System -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api-system</artifactId>
</dependency>
<!-- RuoYi Common DataSource -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
</dependency>
<!-- RuoYi Common DataScope -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datascope</artifactId>
</dependency>
<!-- RuoYi Common Swagger -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!--这个依赖是整合dubbo时要用到的-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
</project>
添加项目中的 bootstrap.yml 配置文件,具体内容如下:
yaml
# Tomcat
server:
port: 9302
# Spring
spring:
application:
# 应用名称
name: common-test
main:
allow-circular-references: true # 中断循环引用
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
在nacos中添加名为 common-test-dev.yml 的配置,具体内容如下:
yaml
# spring配置
spring:
servlet:
multipart:
maxFileSize: 30MB
maxRequestSize: 30MB
datasource:
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: 123456
dynamic:
druid:
initial-size: 5
min-idle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,slf4j
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
connectTimeout: 1800000
socketTimeout: 1800000
datasource:
# 主库数据源
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/hr-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
username: root
password: 123456
druid: # 配置数据库连接参数
connectTimeout: 1800000
socketTimeout: 1800000
# mybatis配置
mybatis:
# 搜索指定包别名
typeAliasesPackage: com.common.test
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath:mapper/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# dubbo相关配置
dubbo:
protocol:
name: dubbo # dubbo协议
port: -1 # -1表示端口从20880开始递增,不会造成端口冲突
registry:
address: nacos://127.0.0.1:8848
consumer:
check: false # dubbo默认有启动检查
retries: 0 # dubbo内置的重试机制
接着在服务启动类中加上 @EnableDubbo 注解
消费者的测试接口
java
package com.common.test.service;
/**
* 测试接口
*
* @author:gan
* @date: 2024-02-04 16:45
*/
public interface CommonService {
/**
* 测试dubbo调用
* @return
*/
Object testDubbo();
}
接口实现类
java
package com.common.test.service.impl;
import com.common.test.service.CommonService;
import com.ruoyi.system.api.DubboFileService;
import com.ruoyi.system.api.domain.SysFileInfo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 测试接口实现类
*
* @author:gan
* @date: 2024-02-04 16:47
*/
@Service
public class CommonServiceImpl implements CommonService {
@DubboReference(version = "1.0.0")
private DubboFileService dubboFileService;
@Override
public Object testDubbo() {
SysFileInfo selectSysFileInfoParams = new SysFileInfo();
selectSysFileInfoParams.setFileId("1752583940597551104");
List<SysFileInfo> sysFileInfoList = dubboFileService.getSysFileInfoList(selectSysFileInfoParams);
System.out.println(sysFileInfoList.get(0));
return sysFileInfoList.get(0);
}
}
测试前端控制器
java
package com.common.test.controller;
import com.common.test.service.CommonService;
import com.ruoyi.common.core.web.domain.AjaxResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 测试controller
*
* @author:gan
* @date: 2024-02-04 16:48
*/
@RestController
@RequestMapping("/test")
public class CommonController {
@Resource
private CommonService commonService;
@GetMapping("/testDubbo")
public AjaxResult test() {
AjaxResult result = null;
try {
result = AjaxResult.success(commonService.testDubbo());
} catch (Exception e) {
e.printStackTrace();
result = AjaxResult.error(e.getMessage());
} finally {
return result;
}
}
}
然后启动测试服务
再查看服务列表
可以看到消费者也启动成功了。
这里只是测试,就不需要用token了,在 ruoyi-gateway 的配置文件中加上如下配置:
重启 ruoyi-gateway 服务,再进行接口测试
三、修改若依的服务调用方式为dubbo
在开始之前,先给小伙伴们打个预防针,改造的过程会比较麻烦,这里以依赖冲突为最,若是对dubbo、若依不够熟悉或者怕麻烦的就跳过这一块。这里放个局部修改图:
看到这里如果没有跳过,那就开始吧。
1、改造系统模块
先引入依赖,父依赖和前面的父依赖一样,这里是处理系统模块的依赖,添加如下依赖:
xml
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!--这个依赖是整合dubbo时要用到的-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
然后排除掉 openfeign 的依赖,去掉若依自带的日志模块:
如果没有排掉,启动服务时会报 openfeign 和 dubbo 的依赖冲突的错。去掉日志模块是因为日志中也使用了 openfeign 。
完整依赖如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-modules-system</artifactId>
<description>
ruoyi-modules-system系统模块
</description>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- RuoYi Common DataSource -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
</dependency>
<!-- RuoYi Common DataScope -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datascope</artifactId>
<exclusions>
<exclusion>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</exclusion>
<exclusion>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- <!– RuoYi Common Log –>-->
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <artifactId>ruoyi-common-log</artifactId>-->
<!-- </dependency>-->
<!-- RuoYi Common Swagger -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
<!-- hutool工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!--这个依赖是整合dubbo时要用到的-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
然后在启动类中去掉 openfeign 的注解,再加上 dubbo 的注解
然后在 nacos 中系统模块的配置文件中加上 dubbo 的相关配置
yaml
# dubbo相关配置
dubbo:
protocol:
name: dubbo # dubbo协议
port: -1 # -1表示端口从20880开始递增,不会造成端口冲突
registry:
address: nacos://127.0.0.1:8848
# check: false # dubbo默认有启动检查
scan:
base-packages: com.ruoyi.system.service
去掉日志模块再起编译时系统模块的前端控制器应该都会报错,需要把报错的地方注释掉或者去掉,我这里以参数管理的前端控制器为例:
完成了这些系统模块应该能正常启动了。
2、改造认证授权中心
但还没结束,启动系统模块后使用默认的 admin 登录,我们会发现报错 admin 不存在。
查找原因:
一开始以为是 admin 账号误删了,看了一下数据库发现账号还在,看了一下控制台,发现是认证授权中心的 SysLoginService
类中报错了,原来是 SysLoginService 这个类使用了系统接口模块的 RemoteUserService 中的
getUserInfo 方法,也就是使用了 openfeign ,用来调用系统模块的根据用户名查询用户接口,虽然认证授权中心中还存在 openfeign 依赖,但是系统模块的已被排除了,自然就报错了。
解决办法:
注释或者去掉认证授权中心 openfeign 相关的使用,以 dubbo 代之。
同样,先处理依赖的问题,经过观察,发现认证授权中心的 openfeign 相关的依赖在如下依赖中,做出排除
然后加上 dubbo 相关的依赖:
xml
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!--这个依赖是整合dubbo时要用到的-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
完整依赖如下:
xml
<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">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-auth</artifactId>
<description>
ruoyi-auth认证授权中心
</description>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- RuoYi Common Security-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId>
<exclusions>
<exclusion>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</exclusion>
<exclusion>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!--这个依赖是整合dubbo时要用到的-->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
然后在 nacos 中认证授权中心的配置文件中加上如下配置:
yaml
# dubbo相关配置
dubbo:
protocol:
name: dubbo # dubbo协议
port: -1 # -1表示端口从20880开始递增,不会造成端口冲突
registry:
address: nacos://127.0.0.1:8848
consumer:
check: false # dubbo默认有启动检查
retries: 0 # dubbo内置的重试机制
接着在启动类中去掉 openfeign 的注解,再加上 dubbo 的注解
然后用 dubbo 的方式写一个接口,以用户服务 RemoteUserService 为例,写一个对应的 DubboUserService 用来替换用户服务 RemoteUserService
完整代码如下:
java
package com.ruoyi.system.api;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
/**
* dubbo用户服务
*
* @author:gan
* @date: 2024-02-28 10:36
*/
public interface DubboUserService {
/**
* 通过用户名查询用户信息
* @param username 用户名
* @return
*/
public LoginUser getUserInfo(String username);
/**
* 注册用户信息
*
* @param sysUser 用户信息
* @return 结果
*/
public Boolean registerUserInfo(SysUser sysUser);
}
其实现类就放在系统模块的包下,完整代码如下:
java
package com.ruoyi.system.service.impl;
import com.ruoyi.common.core.utils.VerifyUtil;
import com.ruoyi.system.api.DubboUserService;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysPermissionService;
import org.apache.dubbo.config.annotation.DubboService;
import javax.annotation.Resource;
/**
* dubbo用户服务 业务处理层
*
* @author:gan
* @date: 2024-02-28 10:41
*/
@DubboService(version = "1.0.0")
public class DubboUserServiceImpl implements DubboUserService {
@Resource
private SysUserMapper sysUserMapper;
@Resource
private ISysPermissionService permissionService;
@Resource
private ISysConfigService configService;
@Override
public LoginUser getUserInfo(String username) {
SysUser sysUser = sysUserMapper.selectUserByUserName(username);
VerifyUtil.checkParam(sysUser, "用户名或密码错误!");
LoginUser sysUserVo = new LoginUser();
sysUserVo.setSysUser(sysUser);
sysUserVo.setRoles(permissionService.getRolePermission(sysUser)); // 角色集合
sysUserVo.setPermissions(permissionService.getMenuPermission(sysUser)); // 权限集合
return sysUserVo;
}
@Override
public Boolean registerUserInfo(SysUser sysUser) {
configService.selectConfigByKey("sys.account.registerUser");
if (!Boolean.TRUE.equals(configService.selectConfigByKey("sys.account.registerUser"))) {
throw new RuntimeException("当前系统没有开启注册功能!");
}
String username = sysUser.getUserName();
VerifyUtil.checkParam(sysUserMapper.checkUserNameUnique(username), "保存用户'" + username + "'失败,注册账号已存在!");
return sysUserMapper.insertUser(sysUser) > 0;
}
}
其中 VerifyUtil 是自己写的判空工具类,可以用自己的方式判空。
接着在 SysLoginService 类中注释掉用户服务 RemoteUserService 相关的逻辑,再以dubbo用户服务 DubboUserService 代之:
日志服务 RemoteLogService 也是同理。改造完成,再成功启动后就可以登录了。
这里贴一下我的日志服务代码
完整代码如下:
java
package com.ruoyi.system.api;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysOperLog;
/**
* dubbo日志服务
*
* @author:gan
* @date: 2024-02-28 11:21
*/
public interface DubboLogService {
/**
* 保存系统日志
*
* @param sysOperLog 日志实体
* @return 结果
*/
public Boolean saveLog(SysOperLog sysOperLog);
/**
* 保存访问记录
*
* @param sysLogininfor 访问实体
* @return 结果
*/
public Boolean saveLogininfor(SysLogininfor sysLogininfor);
}
对应实现类也在系统模块
java
package com.ruoyi.system.service.impl;
import com.ruoyi.system.api.DubboLogService;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysOperLog;
import com.ruoyi.system.mapper.SysLogininforMapper;
import com.ruoyi.system.mapper.SysOperLogMapper;
import org.apache.dubbo.config.annotation.DubboService;
import javax.annotation.Resource;
/**
* dubbo日志服务 服务层处理
*
* @author:gan
* @date: 2024-02-28 11:24
*/
@DubboService(version = "1.0.0")
public class DubboLogServiceImpl implements DubboLogService {
@Resource
private SysOperLogMapper operLogMapper;
@Resource
private SysLogininforMapper logininforMapper;
@Override
public Boolean saveLog(SysOperLog sysOperLog) {
return operLogMapper.insertOperlog(sysOperLog) > 0;
}
@Override
public Boolean saveLogininfor(SysLogininfor sysLogininfor) {
return logininforMapper.insertLogininfor(sysLogininfor) > 0;
}
}
以dubbo日志服务替换掉 SysRecordLogService 类中的日志服务
四、整合过程遇到的问题
1、出现循环引用
我想着文件模块整合dubbo,引入依赖、加上注解之后报错如下:
java
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
targeterBeanPostProcessor defined in class path resource [com/alibaba/cloud/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.class]
↓
com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository (field private com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository.dubboMetadataConfigServiceProxy)
↓
com.alibaba.cloud.dubbo.service.DubboMetadataServiceProxy
┌─────┐
| com.alibaba.cloud.dubbo.autoconfigure.DubboMetadataAutoConfiguration (field private com.alibaba.cloud.dubbo.metadata.resolver.MetadataResolver com.alibaba.cloud.dubbo.autoconfigure.DubboMetadataAutoConfiguration.metadataResolver)
└─────┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
虽然他已经提示要加上配置:
yaml
# Spring
spring:
main:
allow-circular-references: true # 中断循环引用
但是我nacos的配置中加上之后没有效果
重启还是报那个错。
应该在对应模块的 bookstrap.yml 文件中加配置
再次重启
看来配置生效了,再看看nacos中有没有dubbo中的服务
2、出现依赖冲突
我想要在系统模块中使用 dubbo ,但引入 dubbo 相关依赖:
xml
<!-- Dubbo -->
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
报错如下:
java
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
com.alibaba.cloud.dubbo.metadata.RestMethodMetadata.<init>(RestMethodMetadata.java:80)
The following method did not exist:
feign.MethodMetadata.queryMapEncoded()Z
The calling method's class, com.alibaba.cloud.dubbo.metadata.RestMethodMetadata, was loaded from the following location:
jar:file:/D:/environment/Maven/apache-maven-3.6.0/repository/com/alibaba/cloud/spring-cloud-starter-dubbo/2021.0.1.0/spring-cloud-starter-dubbo-2021.0.1.0.jar!/com/alibaba/cloud/dubbo/metadata/RestMethodMetadata.class
The called method's class, feign.MethodMetadata, is available from the following locations:
jar:file:/D:/environment/Maven/apache-maven-3.6.0/repository/io/github/openfeign/feign-core/11.10/feign-core-11.10.jar!/feign/MethodMetadata.class
The called method's class hierarchy was loaded from the following locations:
feign.MethodMetadata: file:/D:/environment/Maven/apache-maven-3.6.0/repository/io/github/openfeign/feign-core/11.10/feign-core-11.10.jar
Action:
Correct the classpath of your application so that it contains compatible versions of the classes com.alibaba.cloud.dubbo.metadata.RestMethodMetadata and feign.MethodMetadata
原来系统模块使用了 openfeign 进行服务调用,引入 dubbo 相关的依赖后就依赖冲突了,可以排除系统模块中的 openfeign 依赖或者移除 dubbo 依赖,我这里选择了前者
3、启动出现端口号被占用
生产者已经启动,消费者启动时报错:
java
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:771)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292)
at com.common.test.CommonTestApplication.main(CommonTestApplication.java:19)
Caused by: org.apache.dubbo.rpc.RpcException: Fail to start server(url: dubbo://192.168.1.12:20880/com.alibaba.cloud.dubbo.service.DubboMetadataService?anyhost=true&application=common-test&bind.ip=192.168.1.12&bind.port=20880&channel.readonly.sent=true&codec=dubbo&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=common-test&heartbeat=60000&interface=com.alibaba.cloud.dubbo.service.DubboMetadataService&metadata-type=remote&methods=getAllServiceKeys,getServiceRestMetadata,getExportedURLs,getAllExportedURLs&pid=27496&qos.enable=false&release=2.7.15&revision=2021.0.1.0&service.name=ServiceBean:common-test/com.alibaba.cloud.dubbo.service.DubboMetadataService:1.0.0&side=provider×tamp=1708501506423&version=1.0.0) Failed to bind NettyServer on /192.168.1.12:20880, cause: Address already in use: bind
at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.createServer(DubboProtocol.java:350)
at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.openServer(DubboProtocol.java:322)
at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.export(DubboProtocol.java:305)
at org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper.export(ProtocolListenerWrapper.java:64)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper.export(ProtocolFilterWrapper.java:75)
at org.apache.dubbo.qos.protocol.QosProtocolWrapper.export(QosProtocolWrapper.java:66)
at org.apache.dubbo.rpc.Protocol$Adaptive.export(Protocol$Adaptive.java)
at org.apache.dubbo.registry.integration.RegistryProtocol.lambda$doLocalExport$2(RegistryProtocol.java:262)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
at org.apache.dubbo.registry.integration.RegistryProtocol.doLocalExport(RegistryProtocol.java:260)
at org.apache.dubbo.registry.integration.RegistryProtocol.export(RegistryProtocol.java:212)
at org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper.export(ProtocolListenerWrapper.java:62)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper.export(ProtocolFilterWrapper.java:73)
at org.apache.dubbo.qos.protocol.QosProtocolWrapper.export(QosProtocolWrapper.java:64)
at org.apache.dubbo.rpc.Protocol$Adaptive.export(Protocol$Adaptive.java)
at org.apache.dubbo.config.ServiceConfig.doExportUrlsFor1Protocol(ServiceConfig.java:518)
at org.apache.dubbo.config.ServiceConfig.doExportUrls(ServiceConfig.java:339)
at org.apache.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:314)
at org.apache.dubbo.config.ServiceConfig.export(ServiceConfig.java:238)
at com.alibaba.cloud.dubbo.service.DubboMetadataServiceExporter.export(DubboMetadataServiceExporter.java:82)
at com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository.getDubboMetadataServiceMetadata(DubboServiceMetadataRepository.java:288)
at com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository$$FastClassBySpringCGLIB$$1.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository$$EnhancerBySpringCGLIB$$1.getDubboMetadataServiceMetadata(<generated>)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.attachDubboMetadataServiceMetadata(DubboServiceRegistrationAutoConfiguration.java:172)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.attachDubboMetadataServiceMetadata(DubboServiceRegistrationAutoConfiguration.java:166)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.lambda$null$0(DubboServiceRegistrationAutoConfiguration.java:131)
at java.lang.Iterable.forEach(Iterable.java:75)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.lambda$onDubboBootstrapStarted$1(DubboServiceRegistrationAutoConfiguration.java:130)
at java.util.concurrent.ConcurrentHashMap.forEach(ConcurrentHashMap.java:1597)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.onDubboBootstrapStarted(DubboServiceRegistrationAutoConfiguration.java:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:344)
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:229)
at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:166)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
at com.alibaba.cloud.dubbo.bootstrap.DubboBootstrapStartCommandLineRunner.run(DubboBootstrapStartCommandLineRunner.java:46)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:768)
... 5 common frames omitted
Caused by: org.apache.dubbo.remoting.RemotingException: Failed to bind NettyServer on /192.168.1.12:20880, cause: Address already in use: bind
at org.apache.dubbo.remoting.transport.AbstractServer.<init>(AbstractServer.java:73)
at org.apache.dubbo.remoting.transport.netty4.NettyServer.<init>(NettyServer.java:79)
at org.apache.dubbo.remoting.transport.netty4.NettyTransporter.bind(NettyTransporter.java:35)
at org.apache.dubbo.remoting.Transporter$Adaptive.bind(Transporter$Adaptive.java)
at org.apache.dubbo.remoting.Transporters.bind(Transporters.java:56)
at org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger.bind(HeaderExchanger.java:44)
at org.apache.dubbo.remoting.exchange.Exchangers.bind(Exchangers.java:70)
at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.createServer(DubboProtocol.java:348)
... 56 common frames omitted
Caused by: java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:433)
at sun.nio.ch.Net.bind(Net.java:425)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:141)
at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:562)
at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1334)
at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:600)
at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:579)
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:973)
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:260)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:356)
at io.netty.util.concurrent.AbstractEventExecutor.runTask$$$capture(AbstractEventExecutor.java:174)
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:167)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
原因:
这是因为生产者启动时,20880这个端口被占用,消费者尝试使用20880端口启动就报错了
报错日志中也提到了
可以在配置文件中加入指定端口号或者使用端口号递增,这里选择后者。
yaml
# dubbo相关配置
dubbo:
protocol:
name: dubbo # dubbo协议
port: -1 # -1表示端口从20880开始递增,不会造成端口冲突
registry:
address: nacos://127.0.0.1:8848
consumer:
check: false # dubbo默认有启动检查
retries: 0 # dubbo内置的重试机制
4、出现某个类找不到
就是模块启动时报错:Caused by: java.lang.ClassNotFoundException
java
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:771)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292)
at com.common.test.CommonTestApplication.main(CommonTestApplication.java:19)
Caused by: java.lang.reflect.UndeclaredThrowableException: Failed to invoke event listener method
HandlerMethod details:
Bean [com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration]
Method [public void com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.onDubboBootstrapStarted(com.alibaba.cloud.dubbo.bootstrap.event.DubboBootstrapStartedEvent)]
Resolved arguments:
[0] [type=com.alibaba.cloud.dubbo.bootstrap.event.DubboBootstrapStartedEvent] [value=com.alibaba.cloud.dubbo.bootstrap.event.DubboBootstrapStartedEvent[source=com.alibaba.cloud.dubbo.bootstrap.DubboBootstrapWrapper@30afac00]]
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:361)
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:229)
at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:166)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
at com.alibaba.cloud.dubbo.bootstrap.DubboBootstrapStartCommandLineRunner.run(DubboBootstrapStartCommandLineRunner.java:46)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:768)
... 5 common frames omitted
Caused by: java.lang.NoClassDefFoundError: com/google/common/collect/Maps
at org.apache.dubbo.registry.nacos.util.NacosInstanceManageUtil.<clinit>(NacosInstanceManageUtil.java:39)
at org.apache.dubbo.registry.nacos.NacosRegistry.doSubscribe(NacosRegistry.java:187)
at org.apache.dubbo.registry.support.FailbackRegistry.subscribe(FailbackRegistry.java:299)
at org.apache.dubbo.registry.ListenerRegistryWrapper.subscribe(ListenerRegistryWrapper.java:105)
at org.apache.dubbo.registry.integration.RegistryProtocol.export(RegistryProtocol.java:232)
at org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper.export(ProtocolListenerWrapper.java:62)
at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper.export(ProtocolFilterWrapper.java:73)
at org.apache.dubbo.qos.protocol.QosProtocolWrapper.export(QosProtocolWrapper.java:64)
at org.apache.dubbo.rpc.Protocol$Adaptive.export(Protocol$Adaptive.java)
at org.apache.dubbo.config.ServiceConfig.doExportUrlsFor1Protocol(ServiceConfig.java:518)
at org.apache.dubbo.config.ServiceConfig.doExportUrls(ServiceConfig.java:339)
at org.apache.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:314)
at org.apache.dubbo.config.ServiceConfig.export(ServiceConfig.java:238)
at com.alibaba.cloud.dubbo.service.DubboMetadataServiceExporter.export(DubboMetadataServiceExporter.java:82)
at com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository.getDubboMetadataServiceMetadata(DubboServiceMetadataRepository.java:288)
at com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository$$FastClassBySpringCGLIB$$1.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.alibaba.cloud.dubbo.metadata.repository.DubboServiceMetadataRepository$$EnhancerBySpringCGLIB$$1.getDubboMetadataServiceMetadata(<generated>)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.attachDubboMetadataServiceMetadata(DubboServiceRegistrationAutoConfiguration.java:172)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.attachDubboMetadataServiceMetadata(DubboServiceRegistrationAutoConfiguration.java:166)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.lambda$null$0(DubboServiceRegistrationAutoConfiguration.java:131)
at java.lang.Iterable.forEach(Iterable.java:75)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.lambda$onDubboBootstrapStarted$1(DubboServiceRegistrationAutoConfiguration.java:130)
at java.util.concurrent.ConcurrentHashMap.forEach(ConcurrentHashMap.java:1597)
at com.alibaba.cloud.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.onDubboBootstrapStarted(DubboServiceRegistrationAutoConfiguration.java:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:344)
... 14 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.google.common.collect.Maps
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 51 common frames omitted
一开始想着是不是dubbo的版本的问题,但生产者都已经启动成功了,而且用的还是同一个依赖,就想着加一下这个类的依赖看看能不能解决,依赖如下:
xml
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.0.0-jre</version>
</dependency>
果然启动成功了。
但也纳闷,为什么同样的dubbo依赖,生产者那边就可以,到了消费者这边就不行了?
既然dubbo依赖是相同的,那肯定就是其他依赖的问题,于是对比了其他依赖,最终发现minio的依赖下包含 com.google.guava 依赖
那就注释掉 com.google.guava 依赖,加入 minio 依赖试试,结果发现也能启动成功...
太难了,就这个问题折腾了好久(大哭)
5、找不到生产者
生产者和消费者都启动了,但是消费者调用生产者服务时报如下错:
java
org.apache.dubbo.rpc.RpcException: No provider available from registry 127.0.0.1:8848 for service com.ruoyi.system.api.DubboFileService:1.0.0 on consumer 192.168.1.12 use dubbo version 2.7.15, please check status of providers(disabled, not registered or in blacklist).
at org.apache.dubbo.registry.integration.DynamicDirectory.doList(DynamicDirectory.java:168)
at org.apache.dubbo.rpc.cluster.directory.AbstractDirectory.list(AbstractDirectory.java:99)
at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.list(AbstractClusterInvoker.java:297)
at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:262)
at org.apache.dubbo.rpc.cluster.interceptor.ClusterInterceptor.intercept(ClusterInterceptor.java:47)
at org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster$InterceptorInvokerNode.invoke(AbstractCluster.java:92)
at org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:98)
at org.apache.dubbo.registry.client.migration.MigrationInvoker.invoke(MigrationInvoker.java:170)
at org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareClusterInvoker.doInvoke(ZoneAwareClusterInvoker.java:112)
at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:265)
at org.apache.dubbo.rpc.cluster.interceptor.ClusterInterceptor.intercept(ClusterInterceptor.java:47)
at org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster$InterceptorInvokerNode.invoke(AbstractCluster.java:92)
at org.apache.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:96)
at org.apache.dubbo.common.bytecode.proxy0.getSysFileInfoList(proxy0.java)
at com.common.test.service.impl.CommonServiceImpl.testDubbo(CommonServiceImpl.java:27)
at com.common.test.controller.CommonController.test(CommonController.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:645)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:90)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:41002)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
分析原因:
我的生产者是若依的文件服务,若依的文件服务原来是用 Feign 进行远程调用的,我只是想把 Feign 改为 dubbo ,就定义了一个和原文件接口相同抽象方法的接口,其实就是接口名不一样,再用文件实现类去实现,这样我就不用重新写方法了,具体如下:
因为启动没报错,nacos中也有看到对应的服务,就没有多想,就是会一直报这个错,后面就想着单独见一个类加上 @DubboService(version = "1.0.0") 试试
结果就调用成功了...