微服务06-Dubbo实现微服务调用

一.确定调用结构

下图为典型购物平台订单模块,购物车模块,库存模块结构图

 以上图中各模块关系为例

  • order模块调用stock模块的减少库存的功能
  • order模块调用cart模块的删除购物车的功能
  • business模块调用order新增订单的功能

要想实现Dubbo调用

必须按照Dubbo规定的配置和行业标准的结构来实现

Dubbo调用的好处是直接将要消费的目标(例如order模块中消费stock的方法)编写在当前消费者的业务逻辑层中,无需编写新的代码结构,开发流程不会因为Dubbo而变化

二.修改stock模块

1.创建csmall-stock-service项目

因为当前stock模块减少库存数业务是典型的生成者方法,需要被别的模块调用

那么其它模块就必须添加当前库存数减少的业务接口支持

为了减少添加这个给当前项目带来的负担

业界通用做法,是将生产者项目拆分为两个,

其中一个项目只有业务逻辑层接口

另一个项目包含正常的配置和所有业务代码

当消费者需要时只需要添加包含业务逻辑层接口的项目的依赖即可

创建csmall-stock-service项目

删除test\删除resources\删除SpringBoot启动类

csmall-stock升格为父项目,所以也要修改它的pom文件

<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<modules>
    <module>csmall-stock-service</module>
</modules>

csmall-stock-service项目的pom文件添加最低要求的依赖

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>csmall-stock</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-stock-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>csmall-stock-service</name>
    <description>Demo project for Spring Boot</description>
    <!--  当前业务逻辑层接口项目,只需要commons模块的依赖即可  -->
    <dependencies>
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>csmall-commons</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

然后将原有的业务逻辑层接口IStockService复制到这个项目中即可

public interface IStockService {

    // 减少库存的业务逻辑层方法
    void reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO);
}

2.创建csmall-stock-webapi项目

webapi项目包含stock项目原有的所有配置和业务代码

创建好项目之后删除test文件夹、删除application.properties文件

然后父子相认

最终csmall-stock项目的pom文件为

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>csmall</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-stock</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>csmall-stock</name>
    <description>Demo project for Spring Boot</description>
    <packaging>pom</packaging>
    <modules>
        <module>csmall-stock-service</module>
        <module>csmall-stock-webapi</module>
    </modules>

</project>

csmall-stock-webapi项目的pom文件为

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.tedu</groupId>
        <artifactId>csmall-stock</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-stock-webapi</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>csmall-stock-webapi</name>
    <description>Demo project for Spring Boot</description>
    <dependencies>
        <!--web实例-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--mybatis整合springboot-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <!--alibaba 数据源德鲁伊-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--all-common依赖-->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>csmall-commons</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <!--在线api文档-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
        </dependency>
        <!--  Nacos注册依赖 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--   Dubbo的依赖   -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <!--   当前项目为了能够在业务逻辑层中正常实现业务逻辑层接口
           需要添加业务逻辑层接口所在的csmall-stock-service项目的依赖 -->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>csmall-stock-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

上面的pom文件不只是将原有的stock的pom文件依赖复制,而且添加了Dubbo和业务逻辑层接口的依赖

将csmall-stock项目的application.yml和application-dev.yml复制到csmall-stock-webapi项目的resources文件夹下

yml文件其它的不动,但是在dev.yml文件中要添加dubbo的配置信息

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/csmall_db?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
    username: root
    password: root
  application:
    #  为当前项目起名,这个名字会被Nacos记录并使用
    name: nacos-stock
  cloud:
    nacos:
      discovery:
        # 配置Nacos所在的位置,用于注册时提交信息
        server-addr: localhost:8848
dubbo:
  protocol:
    # port设置-1 表示当前dubbo端口号支持自动生成
    # 生成规则是从20880开始寻找可用的端口号,如果当前端口号被占用,就会自动加1,直到找可用的为止
    port: -1
    # 设置连接的名称,一般固定为dubbo即可
    name: dubbo
  registry:
    # 声明当前dubbo的注册中心类型和位置
    address: nacos://localhost:8848
  consumer:
    # 当本项目启动时,是否检查当前项目需要的所有Dubbo服务是否可用
    # 我们设置它为false,表示启动时不检查,能够减少出错的情况
    check: false

开始复制代码

我们先将csmall-stock模块中的IStockService接口删除

然后直接复制config\mapper\controller\service.impl四个包

粘贴到webapi项目中

业务逻辑层实现类需要重新导入Mapper的包来实现正确编译

注意impl的包名也要修改->service.impl

然后就可以删除原stock模块的src文件夹了

Knife4jConfiguration:

/**
 * 【重要】指定Controller包路径
 */
private String basePackage = "cn.tedu.csmall.stock.webapi.controller";

MyBatisConfiguration

@Configuration
// MyBatis框架扫描mapper接口包的注解
@MapperScan("cn.tedu.csmall.stock.webapi.mapper")
public class MyBatisConfiguration {
}

下面就可以配置实现Dubbo方法提供的步骤了

3.将业务逻辑层实现类方法声明为Dubbo可调用的方法

当前stock模块是单纯的生产者

// @DubboService注解标记的业务逻辑层实现类,其中的所有方法都会注册到Nacos
// 在其他服务启动"订阅"时,就会"发现"当前类中的所有服务(业务逻辑层方法),并表示允许调用
@DubboService
@Service
@Slf4j
public class StockServiceImpl implements IStockService {
    //内容略....
}

如果当前项目是服务的提供者(生产者)

还需要在SpringBoot启动类上添加@EnableDubbo的注解,才能真正让Dubbo功能生效

@SpringBootApplication
// 如果当前项目是Dubbo的生产者,必须在当前项目的SpringBoot启动类上添加@EnableDubbo这个注解
// 添加注解后,当前项目的所有服务才能正确发布到Nacos中!
@EnableDubbo
public class CsmallStockWebapiApplication {

    public static void main(String[] args) {
        SpringApplication.run(CsmallStockWebapiApplication.class, args);
    }

}

先启动nacos在启动

再启动stockWebapi项目

三.修改cart模块

操作步骤和stock完全一致,参考stock模块即可

四.修改order模块支持Dubbo

因为order模块在Dubbo的调用关系中

既是生产者又是消费者

它消费cart和stock的服务

同时又为business模块提供服务

重构的过程和stock\cart有很多相似,但是也要注意不同

1.创建csmall-order-service项目

这个项目创建的过程和stock\cart模块service项目的步骤和注意事项完全一致

2.创建csmall-order-webapi项目

创建项目后父子相认正常

子项目的pom文件依赖需要额外添加下面内容

<!--   Dubbo的依赖   -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!--   当前项目为了能够在业务逻辑层中正常实现业务逻辑层接口
   需要添加业务逻辑层接口所在的csmall-order-service项目的依赖 -->
<dependency>
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-order-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
<!--   作为消费者,order模块需要调用stock和cart模块的业务逻辑层,
                    所以要添加它们的依赖   -->
<dependency>
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-stock-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-cart-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

yml文件配置也和cart\stock模块一致

代码也都正常从csmall-order复制到csmall-order-webapi中

删除csmall-order的src目录

config包中的配置,修改为正确包名

在OrderServiceImpl业务逻辑层实现类中

添加生产者的注解,同时利用Dubbo消费stock和cart模块的方法

Reference:引用

// order模块的功能会被business模块调用,所以它仍然是生产者,@DubboService要写
@DubboService
@Service
@Slf4j
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private OrderMapper orderMapper;

    // 添加@DubboReference注解,表示当前业务逻辑层要消费其他模块的服务
    // 可以编写当前Nacos中注册的其他业务模块的逻辑层接口
    // 因为Nacos中注册了业务的实现类,所以声明的接口会自动匹配到实现类对象
    // 先添加stock模块的业务逻辑层接口,在添加cart模块
    @DubboReference
    private IStockService dubboStockService;
    @DubboReference
    private ICartService dubboCartService;

    @Override
    public void orderAdd(OrderAddDTO orderAddDTO) {
        // 1.减少订单中商品的库存数(要调用stock模块的功能)
        // 实例化减少库存业务的DTO对象
        StockReduceCountDTO countDTO=new StockReduceCountDTO();
        countDTO.setCommodityCode(orderAddDTO.getCommodityCode());
        countDTO.setReduceCount(orderAddDTO.getCount());
        // 执行dubbo调用完成stock模块减少库存的方法
        dubboStockService.reduceCommodityCount(countDTO);
        // 2.从购物车中删除订单中选择中的商品(要调用cart模块的功能)
        dubboCartService.deleteUserCart(orderAddDTO.getUserId(),
                                        orderAddDTO.getCommodityCode());


        // 3.将orderAddDTO中的信息新增到数据库订单表中
        // 要将orderAddDTO对象中的属性赋值给Order类型对象的同名属性
        Order order=new Order();
        BeanUtils.copyProperties(orderAddDTO,order);
        // 执行新增
        orderMapper.insertOrder(order);
        log.info("新增订单信息为:{}",order);
    }
}

因为order模块也是生产者@EnableDubbo注解仍然要写

@SpringBootApplication
@EnableDubbo
public class CsmallOrderWebapiApplication {

    public static void main(String[] args) {
        SpringApplication.run(CsmallOrderWebapiApplication.class, args);
    }

}

我们可以测试这个Dubbo的功能

首先保证Nacos启动

我们项目的启动顺序,尽量保证生产者先启动

启动消费者

stock\cart最后启动order

访问

http://localhost:20002/doc.html运行测试

注意运行前,数据库的数据状态和运行后的比较一下

我们可以再复制一个项目出来

更改端口号后启动它,这样同一个服务就可能出现多个实例

当Dubbo调用这个实例时,就需要一个调用策略,简单来说,就是要可能调用到其中任何一个服务器

而这个策略有一个名称叫负载均衡(微服务07-负载均衡_teyruthy的博客-CSDN博客)

五.修改business模块

business模块是我们设计的新增订单业务的触发者,是起点

它是单纯的消费者

我们不需要像生产者一样去创建两个子项目

直接在现有项目上进行修改即可

pom文件直接添加dubbo和order业务逻辑接口的依赖

<!--  dubbo依赖   -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!-- 添加order模块的业务逻辑层接口的依赖  -->
<dependency>
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-order-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

application-dev.yml添加Dubbo的配置

spring:
  application:
    # 为当前项目起名,这个名字会被Nacos收集,并显示在注册列表中
    name: nacos-business
  cloud:
    nacos:
      discovery:
        # 配置Nacos的位置,用于当前项目连接
        server-addr: localhost:8848
        # ephemeral设置当前项目启动时注册到nacos的类型 true(默认):临时实例 false:永久实例
        ephemeral: false
dubbo:
  protocol:
    port: -1
    name: dubbo
  registry:
    address: nacos://localhost:8848
  consumer:
    check: false

我们要在当前busindess模块的业务逻辑层实现类中

实现Dubbo调用order模块的生成订单方法

BusinessServiceImpl类中

@Service
@Slf4j
public class BusinessServiceImpl implements IBusinessService {

    // Dubbo调用Order模块的新增订单功能
    // Business是单纯的消费者,不需要在类上编写@DubboService
    @DubboReference
    private IOrderService dubboOrderService;


    @Override
    public void buy() {
        // 实例化一个用于新增订单的DTO类对象
        // 并为它赋值
        OrderAddDTO orderAddDTO=new OrderAddDTO();
        orderAddDTO.setUserId("UU100");
        orderAddDTO.setCommodityCode("PC100");
        orderAddDTO.setCount(3);
        orderAddDTO.setMoney(300);

        log.info("新增订单信息为:{}",orderAddDTO);
        // dubbo调用
        dubboOrderService.orderAdd(orderAddDTO);

    }
}

Springboot启动类不必要写@EnableDubbo因为business是单纯的消费者

启动business项目(前提是cart\stock\order正在运行)

http://localhost:20000/doc.html运行测试

六.Dubbo生产者消费者配置小结

Dubbo生产者消费者相同的配置

pom文件添加dubbo依赖,yml文件配置dubbo信息

生产者

  • 要有service接口项目

  • 提供服务的业务逻辑层实现类要添加@DubboService注解

  • SpringBoot启动类要添加@EnableDubbo注解

消费者

  • pom文件添加消费模块的service依赖
  • 业务逻辑层远程调用前,模块使用@DubboReference注解获取业务逻辑层实现类对象

七.Dubbo调用常见错误

No provider available from registry localhost:8848 for service cn.tedu.csmall.stock.service.IStockService on consumer 192.168.126.1 use dubbo version 2.7.8, please check status of providers(disabled, not registered or in blacklist).

(disabled, not registered or in blacklist)是这个错误信息的特征

发生这个错误原因是消费者无法在指定的位置找到需要的服务

  • 检查调用目标的服务是否启动(上面示例中可能是因为stock模块没有启动导致的)
  • 检查被调用的目标服务SpringBoot启动类是否编写的@EnableDubbo注解
  • 检查被调用的模块的业务逻辑层实现类是否编写了@DubboService注
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值