day79(order模块,stock模块,Dubbo,对(order,stock)进行修改,负载均衡,Dubbo内置的负载均衡算法)

目录

1.创建order模块

1.项目搭建

1.修改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>
    </parent>
    <groupId>cn.tedu</groupId>
    <artifactId>csmall-order</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>csmall-order</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>
    </dependencies>

</project>

2.添加配置文件

application.yml

server:
  port: 20002
#公共配置
mybatis:
  configuration:
    # 禁用缓存
    cache-enabled: false
    # 配置映射驼峰命名法,数据库中user_name的字段,会映射在java的userName属性上
    map-underscore-to-camel-case: true
    # 将运行的sql语句输出到控制台
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
knife4j:
  # 开启增强配置
  enable: true
  # 生产环境屏蔽,开启将禁止访问在线API文档
  production: false
  # Basic认证功能,即是否需要通过用户名、密码验证后才可以访问在线API文档
  basic:
    # 是否开启Basic认证
    enable: false
    # 用户名,如果开启Basic认证却未配置用户名与密码,默认是:admin/123321
    username: root
    # 密码
    password: root
spring:
  profiles:
    active: dev

application-dev.yml

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:
    name: nacos-order
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

3.config配置

将cart的config文件直接复制

1.knief4j主要修改

/**
 * 【重要】指定Controller包路径
 */
private String basePackage = "cn.tedu.csmall.order.controller";
/**
 * 分组名称
 */
private String groupName = "base-order";

2.Mybatis配置

@Configuration
// Mybatis扫描必须指定到mapper包
@MapperScan("cn.tedu.csmall.order.mapper")
public class MybatisConfiguration {

}

2.编写新增订单功能

1.持久层

mapper.OderMapper

@Repository
public interface OrderMapper {
    // 新增订单的mapper方法
    @Insert("insert into order_tbl(user_id,commodity_code,count,money) " +
            "values(#{userId},#{commodityCode},#{count},#{money})")
    void insertOrder(Order order);
}

2.业务逻辑层

1.service.IOrderService

public interface IOrderService {

    // 新增订单到数据库的业务逻辑层方法
    void orderAdd(OrderAddDTO orderAddDTO);
}

2.service.impl.OrderServiceImpl

public interface IOrderService {

    // 新增订单到数据库的业务逻辑层方法
    void orderAdd(OrderAddDTO orderAddDTO);
}

3.控制层

controller.OrderController

@RestController
@RequestMapping("/base/stock")
@Api(tags = "库存管理")
public class StockController {

    @Autowired
    private IStockService stockService;
    @PostMapping("/reduce/count")
    @ApiOperation("减少商品库存业务")
    public JsonResult reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO){
        stockService.reduceCommodityCount(stockReduceCountDTO);
        return JsonResult.ok("商品库存减少完成!");
    }

}

2.Stock模块

1.项目搭建

1.修改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>
    </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>
    <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>
    </dependencies>

</project>

2.添加配置文件

application.yml

server:
  port: 20003
#公共配置
mybatis:
  configuration:
    # 禁用缓存
    cache-enabled: false
    # 配置映射驼峰命名法,数据库中user_name的字段,会映射在java的userName属性上
    map-underscore-to-camel-case: true
    # 将运行的sql语句输出到控制台
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
knife4j:
  # 开启增强配置
  enable: true
  # 生产环境屏蔽,开启将禁止访问在线API文档
  production: false
  # Basic认证功能,即是否需要通过用户名、密码验证后才可以访问在线API文档
  basic:
    # 是否开启Basic认证
    enable: false
    # 用户名,如果开启Basic认证却未配置用户名与密码,默认是:admin/123321
    username: root
    # 密码
    password: root
spring:
  profiles:
    active: dev

application-dev.yml

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:
    name: nacos-stock
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

3.config配置

将cart的config文件直接复制

1.knief4j主要修改

/**
 * 【重要】指定Controller包路径
 */
private String basePackage = "cn.tedu.csmall.stock.controller";
/**
 * 分组名称
 */
private String groupName = "base-stock";

2.Mybatis配置

@Configuration
// Mybatis扫描必须指定到mapper包
@MapperScan("cn.tedu.csmall.stock.mapper")
public class MybatisConfiguration {

}

2.编写减少库存功能

1.持久层

mapper.StockMapper

@Repository
public interface StockMapper {
    // 减少指定商品库存的方法
    @Update("update stock_tbl set count=count-#{reduceCount} " +
            " where commodity_code=#{commodityCode} and count>=#{reduceCount}")
    void updateStockByCommodityCode(@Param("commodityCode") String commodityCode,
                                    @Param("reduceCount") Integer reduceCount);
}

2.业务层

1.service.IStockService

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

2.service.impl.StockServiceImpl

@Service
@Slf4j
public class StockServiceImpl implements IStockService {

    @Autowired
    private StockMapper stockMapper;

    @Override
    public void reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO) {
        stockMapper.updateStockByCommodityCode(
                stockReduceCountDTO.getCommodityCode(), // 第一个参数是商品编号
                stockReduceCountDTO.getReduceCount());  // 第二个参数是减少的库存数
        log.info("库存减少完成!");

    }
}

3.控制层

controller.StockController

@RestController
@RequestMapping("/base/stock")
@Api(tags = "库存管理")
public class StockController {

    @Autowired
    private IStockService stockService;
    @PostMapping("/reduce/count")
    @ApiOperation("减少商品库存业务")
    public JsonResult reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO){
        stockService.reduceCommodityCount(stockReduceCountDTO);
        return JsonResult.ok("商品库存减少完成!");
    }

}

3.Dubbo概述

1.RPC

RPC是Remote Procedure Call的缩写 翻译为:远程过程调用

目标是为了实现两台(多台)计算机\服务器,互相调用方法\通信的解决方案

RPC的概念主要定义了两部分内容

1.序列化协议

通信协议指的就是远程调用的通信方式

再上面图片调用中,老婆使用手机信息的方法通知老公去洗碗

实际上这个通知的方式可以有多种

例如:写信,飞鸽传书,闪送等等

2.通信协议

序列化协议指通信内容的格式,双方都要理解这个格式

上面的图片中,老婆给老公发信息,一定是双方都能理解的信息

发送信息是序列化过程,接收信息需要反序列化

2.Dubbo

1.Dubbo是一套RPC框架。

既然是框架,我们可以在框架结构高度,定义Dubbo中使用的通信协议,使用的序列化框架技术,而数据格式Dubbo定义,我们负责配置之后直接通过客户端调用服务端代码

2.Dubbo就是RPC概念的实现

Dubbo是Spring Cloud Alibaba提供的一个框架

能够实现微服务项目的互相调用

3.Dubbo的协议支持

Dubbo框架支持多种通信协议和序列化协议,可以通过配置文件进行修改

1.支持的通信协议有

  • dubbo协议(默认)
  • rmi协议
  • hessian协议
  • http协议
  • webservice
  • .....

2.支持的序列化协议

  • hessian2(默认)
  • java序列化
  • compactedjava
  • nativejava
  • fastjson
  • dubbo
  • fst
  • kryo

3.Dubbo默认情况下,协议的特征如下

  • 采用NIO单一长连接
  • 优秀的并发性能,但是大型文件的处理差
  • Dubbo开发简单,有助于提升开发效率

4.Dubbo服务的注册与发现

1.Dubbo的调用过程中,必须包含注册中心的支持,推荐Nacos(Redis,zookeeper等也能实现)

2.服务发现

消费端自动发现服务地址列表的能力,是微服务框架需要具备的关键能力,借助于自动化的服务发现,微服务之间可以在无需感知对端部署位置与 IP 地址的情况下实现通信。

consumer服务的消费者,指服务的调用者(使用者)也就是老婆的位置

provider服务的提供者,指服务的拥有者(生成者)也就是老公的位置

在Dubbo中,远程调用依据是服务的提供者在Nacos中注册的服务名称

一个服务名称,可能有多个运行的实例,任何一个空闲的实例都可以提供服务

3.Dubbo的注册发现流程

1.首先服务的提供者启动服务到注册中心注册,包括各种ip端口信息,Dubbo会同时注册该项目提供的远程调用的方法

2.服务的消费者(使用者)注册到注册中心,订阅发现

3.当有新的远程调用方法注册到注册中心时,注册中心会通知服务的消费者有哪些新的方法,如何调用的信息

4.RPC调用,在上面条件满足的情况下,服务的调用者无需知道ip和端口号,只需要服务名称就可以调用到服务提供者的方法

3.Dubbo实现微服务调用

1.确定调用关系

在上面的模型中,以order调用stock减少库存的业务举例

order模块是消费者stock模块是生产者

在代码调用时,首先要对项目进行必要的配置

我们调用时一般会在消费者项目的代码业务逻辑层中,编写调用生产者业务逻辑层方法的代码

这样做的好处

我们的生成者正常编写mapper>service>controller这个开发流程不会因为Dubbo的介入而变化

4.修改stock项目

1.创建csmall-stock-service项目

  1. stock模块要新建一个项目单独保存要公开给其他微服务项目的方法接口

  2. 创建csmall-stock-service项目

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

  4. csmall-stock父项目pom文件添加必要配置

    <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>
    </modules>
    
  5. 子项目要编写最低限度的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>
        </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>
        <dependencies>
            <dependency>
                <groupId>cn.tedu</groupId>
                <artifactId>csmall-commons</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
        </dependencies>
    
    </project>
    
  6. 将原有的业务逻辑层接口复制到这个项目中即可:IStockService

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

2.创建csmall-stock-webapi项目

1.创建csmall-stock-webapi项目

2.删除test测试文件夹

3.父子相认

4.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>
    </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>

5.修改子项目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>
    </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>
        <!-- 添加camall-stock-service的依赖,以实现业务逻辑层接口 -->
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>csmall-stock-service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

6.复制application.yml和application-dev.yml(csmall-stock项目的)

7.修改application-dev.yml

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:
    name: nacos-stock
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
dubbo:
  protocol:
    port: -1 # 设置Dubbo服务调用的端口 设置-1能够实现动态自动设置合适端口,生成规则是从20880开始递增
    name: dubbo # 设置端口名称,一般固定就叫dubbo
  registry:
    address: nacos://localhost:8848 # 配置当前Dubbo注册中心的类型和地址
  consumer:
    check: false # 设置为false表示当前项目启动时,不检查要调用的远程服务是否可用,避免报错

8.删除业务逻辑层接口

9.复制cn.tedu.....这个包中的所有内容(到webapi包下)

10.删除csmall-stock项目的src文件夹

11.调整webapi项目的中配置路径

1.Knife4jConfiguration:

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

2.MyBatisConfiguration:

@Configuration
// Mybatis扫描必须指定到mapper包
@MapperScan("cn.tedu.csmall.stock.webapi.mapper")
public class MybatisConfiguration {

}

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

// @DubboService注解表示当前业务逻辑层实现类中的所有方法
// 均会注册到Nacos,成为Dubbo可以发现的业务逻辑层方法
@DubboService
@Service
@Slf4j
public class StockServiceImpl implements IStockService {

    @Autowired
    private StockMapper stockMapper;

    @Override
    public void reduceCommodityCount(StockReduceCountDTO stockReduceCountDTO) {
        stockMapper.updateStockByCommodityCode(
                stockReduceCountDTO.getCommodityCode(), // 第一个参数是商品编号
                stockReduceCountDTO.getReduceCount());  // 第二个参数是减少的库存数
        log.info("库存减少完成!");

    }
}

13.当前项目的Spring启动类要添加一个注解,表示当前项目有Dubbo服务提供:@EnableDubbo

@SpringBootApplication
// 如果当前项目是Dubbo服务的生产者,必须添加这个注解
@EnableDubbo
public class CsmallStockWebapiApplication {

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

}

14.测试启动

5.修改cart模块

参考stock

6.负载均衡

在实际开发中,一个服务基本都是集群模式的,也就是多个功能相同的项目在运行,这样才能承受更高的并发

这时一个请求到这个服务,就需要确定访问哪一个服务器

Dubbo框架内部支持负载均衡算法,能够尽可能的让请求在相对空闲的服务器上运行

我们要实现设置好负载均衡的策略算法,并设置好每个服务器的运行权重

才能更好的实现负载均衡的效果

Loadbalance:就是负载均衡的意思

7.Dubbo内置负载均衡策略算法

Dubbo内置4种负载均衡算法

  • random loadbalance:随机分配策略(默认)
  • round Robin Loadbalance:权重平均分配
  • leastactive Loadbalance:活跃度自动感知分配
  • consistanthash Loadbalance:一致性hash算法分配

1.随机分配策略(默认)

随机生成随机数

在哪个范围内让哪个服务器运行

优点:

算法简单,效率高,长时间运行下,任务分配比例准确

缺点:

偶然性高,如果连续的几个随机请求发送到性能弱的服务器,会导致异常甚至宕机

2.权重平均分配

如果几个服务器权重一致,那么就是依次运行

3个服务器 1>1 2>2 3>3 4>1

但是服务器的性能权重一致的可能性很小

所以我们需要权重评价分配

Dubbo2.6.4之前平均分配权重算法是有问题的

如果3个服务器的权重比5:3:1

1>1 2>1 3>1 4>1 5>1 6>2 7>2 8>2 9>3

10>1

Dubbo2.7之后更新了这个算法使用"平滑加权算法"优化权重平均分配策略

3.活跃度自动感知

记录每个服务器处理一次请求的时间

安装时间比例来分配任务数,运行一次需要时间多的分配的请求数较少

4.一致性Hash算法

根据请求的参数进行hash运算

以后每次相同参数的请求都会访问固定服务器

因为根据参数选择服务器,不能平均分配到每台服务器上

使用的也不多

posted @ 2022-06-22 19:23  约拿小叶  阅读(94)  评论(0)    收藏  举报