最近给一个mybatis-plus框架的项目整合nacos、dubbo,经历了No provider available from registry、com.alibaba.dubbo.rpc.RpcException Failed to invoke the
method、java.lang.NoClassDefFoundError:
org/apache/commons/lang3/StringUtils等一系列错误,现在把我的创建过程分享一下。

环境:Springboot2.3,Dubbo2.7.8,mybatis-plus,nacosServer1.4.3

由于是在已有项目基础上整合,所以会缺少一部分无关紧要的代码,适合有一定经验的开发者阅读

搭建步骤

1. 创建一个公共模块

我这里创建的是dubbo-common,名称自己定

我的项目结构如下:


pom.xml引入nacos、dubbo依赖:

<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <!--  此依赖是为了解决java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils 错误-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

2.建立提供者(生产者)模块
pom引入对公共模块的依赖:

<dependency>
            <groupId>com.zhongrui.uthink</groupId>
            <artifactId>dubbo-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

建立启动类:

@SpringBootApplication
@EnableDiscoveryClient
@EnableDubbo
public class Application {
    public static void main(String[] args) {
       SpringApplication.run(Application.class, args);
    }
 }

建立服务实现类:

//引入的接口要和刚才在common建立的一致
import service.huawei.DeviceBindingService;
//引入dubboservice
import org.apache.dubbo.config.annotation.DubboService;
@Service
//供dubbo暴露的接口,要指定版本号
@DubboService(version = "1.0.0",group = "db1")
public class DeviceBindingServiceImpl extends ServiceImpl<DeviceBindingDao, DeviceBinding> implements DeviceBindingService { 
		//服务实现代码
}

applicaiton配置参数(重要)
我的配置:

#提供者的服务名,一定要记住
spring.application.name=userservice
#dubbo
#协议名为dubbo
dubbo.protocol.name=dubbo
#端口号,配置为-1代表自增长
dubbo.protocol.port=-1
#配置nacos注册中心地址
dubbo.registry.address=nacos://localhost:8848
#在提供者需要加上这一配置
dubbo.consumer.check=false
#设置订阅的服务
dubbo.cloud.subscribed-services=userservice
#重要,一定要和注解了DubboService的包目录一致
dubbo.scan.base-packages=com.zhongrui.uthink.business.impl
spring.main.allow-bean-definition-overriding=true

注:dubbo.scan.base-packages要配置正确,这里的配置比较重要

3. 建立消费者模块
pom引入dubbo-common依赖,与提供者一致

<dependency>
            <groupId>com.zhongrui.uthink</groupId>
            <artifactId>dubbo-common</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

建立消费者实现类:

import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
//这是要调用的接口,和生产者import的一致
import service.huawei.DeviceBindingService;
@Service
@Slf4j
public class PushReceiveServiceImpl {
	//使用DubboReference注解,括号内的内容要和提供者的一致
    @DubboReference(version = "1.0.0",group = "db1")
    DeviceBindingService bindingService;

	//其他实现代码...
}

建立消费者Controller

@RestController
@Api(tags = "推送数据接口")
@RequestMapping("/receive")
public class ReceiveController {
    @Resource
    private PushReceiveServiceImpl pushReceiveService;
    @PostMapping("/test")
    @ResponseBody
    @ApiOperation("测试云推送")
    public ResponseEntity pushReceiverTest(@RequestBody String jsonString) throws Exception {
        System.out.println(jsonString);
        return new ResponseEntity(HttpStatus.OK);
    }
}

配置文件:

#消费者名称
spring.application.name=huaweiservice
#dubbo
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
dubbo.registry.address=nacos://localhost:8848
#订阅服务的名称,要和提供者的应用名一致 
dubbo.cloud.subscribed-services=userservice

4.先后启动提供者、消费者服务

启动提供者服务之后,再启动消费者服务。

最后应在nacos-server看到provider和consumer的名称,如下图所示:

(我这里有其它的服务,没有在代码中体现出来)

dubbo和nacos有啥区别_spring

注意,consumer和provider后面的名称需要完全一致,否则会出现No provider available from registry的错误。
如果没有发现注册的providers服务,请检查@DubboService注解是否正确标明,以及dubbo.scan.base-packages是否配置正确

4.调用测试

在浏览器访问测试消费者模块提供的接口:

dubbo和nacos有啥区别_spring cloud_02


如上图所示,返回200,表成功访问。

5.常见问题

  1. 在使用了mybatis-plus框架的项目中,如果在服务接口使用的时候有wrapper的传输,会报com.alibaba.dubbo.rpc.RpcException Failed to invoke the…错误,需要在impl里将涉及直接使用wrapper的地方在Service中为其新建一个接口
    例如这种代码:

    需要在提供者的bindingServiceImpl里面为其新建一个接口:

    再到消费者调用:

dubbo和nacos有啥区别_spring_03


这样来避免wrapper的直接传输。

  1. 调用服务时提示No provider available for the service xxx from registry xxx on the consumer
    这个问题解决起来比较复杂,要检查服务名称、扫描包等配置项,可先到nacos查看已经注册的服务是否包含需要的provider,如果没有则检查配置包是否扫描到,如果有则检查服务名是否一致等。

第一次接触Dubbo,如有不对,请多指教