带着小白学习-微服务-5 实战:配置中心-数据库连接

如前所述,服务治理主要包含注册中心,前面所有的微服务子工程均已注册到nacos,然后由相应的应用到nacos进行拉取。

接下来,我们将使用nacos的配置中心,用于保存和分发应用运行所需的动态配置。比如数据库的各类信息等。

一、nacos中新建配置

nacos新建配置

选择"配置列表菜单",点击"+"号。

如图所示,新建一个配置,点击"发布"。

点击"确定"之后,可以在配置列表看到配置结果。

二、server-goods服务中发现配置

1.修改pom,添加config依赖和bootstrap依赖

xml 复制代码
        <!--config-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
         <!-- 开启bootstrap上下文 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

2. 新建bootstrap.yml文件,添加nacos配置

yaml 复制代码
spring:
  cloud:
    nacos:
      config:
        server-addr: 10.50.41.17:8848
        file-extension: yaml
  application:
    name: goods

特别说明:因为目前我使用的是SpringBoot 2.6.3 + SCA 2021.0.1.0(老版本),所以使用的是,原生支持 bootstrap.yml 方式。使用原生方式是因为,其实大家会发现最近这两年,随着AI的兴起,真正古法编程的原来越少,相关的资料也还是停留在以前的版本,所以,为了大家看资料的时候不至于搞不清卡,这里还是使用了bootstrap的方式。 *

也可以

3. 到controller测试是否能够找到配置内容

添加如下代码:

java 复制代码
    @Value("${config.info}")
    private String configInfo;
    @GetMapping("/config/info")
    public String getConfigInfo() {
        return configInfo;
    }

说明:经过前面的配置后,项目启动后先到bootstrap中找到nacos配置,然后到 Nacos 远程拉配置,获取到config.info,最后放到 Spring 环境里。

4.启动项目运行

地址栏输入http://localhost:8100/config/info,显示配置中心config.info信息,说明整个配置中心能够正常运行。

** 特别注意:之所以使用配置中心就是为了将比如数据库等这些设置统一管理,需要修改的时候,只要在配置中心统一修改即可,并且能即时生效,而不需要所有服务重新启动。所以,需要在controller添加一个自动更新配置的注解@RefreshScope**

三、设计数据库

如前所述,所有微服务的配置(比如数据库 url、redis 密码、功能开关)都集中存在配置中心;

  • 微服务启动时,从配置中心拉取自己需要的配置; 配置需要修改时,直接在配置中心改,所有相关服务可动态刷新配置(不用重启服务)。
  • 接下来,我们实战一个数据库的配置。

1.新建数据库db2025

2.新建数据表

(1)tb_stock

sql 复制代码
CREATE TABLE `tb_stock` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
  `goods_id` BIGINT NOT NULL COMMENT '商品id,关联商品表',
  `stock_num` INT NOT NULL DEFAULT 0 COMMENT '可用库存数量',
  `locked_num` INT NOT NULL DEFAULT 0 COMMENT '锁定库存(下单未支付,防超卖)',
  `total_num` INT NOT NULL DEFAULT 0 COMMENT '总库存 = 可用+锁定',
  `warehouse_id` BIGINT DEFAULT 1 COMMENT '仓库id,简单版可以先固定1(默认仓库)',
  `version` INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号(扣库存防并发超卖,重点!)',
  `create_time` DATETIME NULL COMMENT '创建时间',
  `update_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  UNIQUE KEY `uk_goods_warehouse` (`goods_id`,`warehouse_id`) -- 一个商品在同一个仓库只能一条库存记录
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品库存表';

(2)tb_goods

sql 复制代码
CREATE TABLE `tb_goods` (
  `id` BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '商品id',
  `goods_name` VARCHAR(128) NOT NULL COMMENT '商品名称',
  `price` DECIMAL(10,2) NOT NULL COMMENT '售价',
  `pic` VARCHAR(255) DEFAULT '' COMMENT '商品图片',
  `status` TINYINT DEFAULT 1 COMMENT '状态:0下架 1上架',
  `create_time` DATETIME NULL COMMENT '创建时间',
  `update_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

3.添加数据

sql 复制代码
INSERT INTO tb_goods(id,goods_name,price,status,create_time) VALUES
(1,'小米手机14',3999.00,1,now()),
(2,'华为平板',2599.00,1,now()),
(3,'机械键盘',129.00,1,now());

INSERT INTO tb_stock(goods_id,stock_num,locked_num,total_num,version,create_time) VALUES
(1,100,0,100,0,now()),
(2,50,0,50,0,now()),
(3,200,0,200,0,now());

四、到server-store子工程中进行nacos中的数据库配置拉取

1.修改server-store子工程中的pom文件

添加数据库、config、openfeign 、bootstrap、lombok等的依赖

xml 复制代码
<!-- MyBatis-Plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>

<!-- MySQL驱动,适配 MySQL5.7 用 8.0.28 没问题 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<!-- MyBatis-Plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

        <!-- MySQL驱动,适配 MySQL5.7 用 8.0.28 没问题 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <!-- openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--config-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!-- 开启bootstrap上下文 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

2. 添加bootstrap.yml文件

yaml 复制代码
spring:
  application:
    name: store          # ⭐服务名,Feign 里写的就是这个
  cloud:
    nacos:
      config:
        server-addr: 10.50.41.17:8848     # 换成自己的 Nacos 地址
        file-extension: yaml
        prefix: server-store              # 覆盖默认name,去拉 server-store.yml
        group: DEFAULT_GROUP

3. nacos中进行数据库配置

  • DataId:server-store.yml
  • Group:DEFAULT_GROUP
  • 配置格式:YAML
yaml 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db2025?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    username: root
    password: root
    hikari:
      maximum-pool-size: 10
      minimum-idle: 2

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: auto

4. 启动类添加 @MapperScan("com.example.mapper")

5.添加实体类

java 复制代码
package com.example.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@TableName("tb_stock")
public class Stock {

    @TableId(type = IdType.AUTO)
    private Long id;

    private Long goodsId;

    private Integer stockNum;

    private Integer lockedNum;

    private Integer totalNum;

    private Long warehouseId;

    private Integer version;

    private LocalDateTime createTime;

    private LocalDateTime updateTime;
}

6.添加Mapper接口

java 复制代码
package com.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.Stock;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface StockMapper extends BaseMapper<Stock> {
}

7.添加service

(1)添加接口

java 复制代码
package com.example.service;

import com.example.entity.Stock;

public interface StockService {

    /** 按商品id查询库存 */
    Stock getByGoodsId(Long goodsId);

    /** 按库存主键查询 */
    Stock getById(Long id);
}

(2)添加实现类

java 复制代码
package com.example.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.entity.Stock;
import com.example.mapper.StockMapper;
import com.example.service.StockService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class StockServiceImpl implements StockService {

    @Resource
    private StockMapper stockMapper;

    @Override
    public Stock getByGoodsId(Long goodsId) {
        // 一个商品在一个仓库一条记录,用 selectOne
        return stockMapper.selectOne(
                Wrappers.<Stock>lambdaQuery()
                        .eq(Stock::getGoodsId, goodsId)
                        .eq(Stock::getWarehouseId, 1L)
        );
    }

    @Override
    public Stock getById(Long id) {
        return stockMapper.selectById(id);
    }
}

8.修改StoreController

原来这个类中只是进行了nacos服务接口测试。

现在添加两个业务逻辑,一个是按商品id查询库存,这个对应的是goods这个服务中的需求。另一个是自身查找商品。

具体代码如下:

java 复制代码
package com.example.controller;


import com.example.entity.Stock;
import lombok.extern.slf4j.Slf4j;
import com.example.service.StockService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@Slf4j
@RestController
@RequestMapping("/store")
public class StoreController {


    @Value("${server.port}")
    private String port;
    
    @Resource
    private StockService stockService;

    /**
     * 按商品id查询库存
     * 对应 goods 的 Feign:@GetMapping("/store/{id}")
     */
    @GetMapping("/{id}")
    public Stock getStock(@PathVariable("id") Long goodsId) {
        log.info("库存服务端口:{},收到查询商品id:{}", port, goodsId);
        Stock stock = stockService.getByGoodsId(goodsId);
        if (stock == null) {
            // 查不到返回空壳,避免 consumer 端 null 反序列化异常
            Stock empty = new Stock();
            empty.setGoodsId(goodsId);
            empty.setStockNum(0);
            return empty;
        }
        return stock;
    }

    /** 按库存记录主键查询 */
    @GetMapping("/id/{id}")
    public Stock getByStockId(@PathVariable("id") Long id) {
        return stockService.getById(id);
    }

    /** 返回端口,单纯用来验证负载均衡 */
    @GetMapping("/port")
    public String port() {
        return "库存服务端口:" + port;
    }
}

五、修改server-goods调用server-store中的接口

1.修改server-goods中的接口StoreFeignClient

2.修改server-goods中的controller业务逻辑index

六、重新启动运行

(1)首先运行server-store的两个示例(8084、8085)

(2)再运行server-goods(8100)

nacos中服务列表有两个,如图所示:

(3)地址栏输入:http://localhost:8100/config/info,运行效果如下:

(4)地址栏输入:http://localhost:8085/store/1,按商品id搜索,测试server-store运行效果:

(5)地址栏输入:http://localhost:8085/store/id/2,按库存记录主键搜索

(6)地址栏输入:http://localhost:8100/index,按商品id(传递值目前是一个固定值,正常项目由前端传递:1)利用feign实现服务消费调用。

七、在server-goods中再次查看openfeign是否实现了负载均衡

为了清楚的看到负载均衡的效果,我们添加一点内容输出调用port。

1.到serv-store中修改stock实体类

添加一个临时字段port,注意:这个字段非数据表中字段,所以应该添加注解:@TableField(exist = false)

2.修改StoreController

修改StoreController,将获取的端口号写入到stock对象中。

3.重新运行server-store和server-goods

重新运行上述三个服务。

刷新地址栏:http://localhost:8100/index,可以看到port:8085和port:8084实现轮询。

相关推荐
叼烟扛炮1 小时前
Linux 学习笔记(五十):网络层——IP 协议、子网划分与 NAT 魔法
linux·笔记·学习
叼烟扛炮1 小时前
Linux 学习笔记(六十):单线程的逆袭——epoll 高并发服务器实战
linux·服务器·网络·笔记·学习·算法
大维1 小时前
DBX 实测:从 SQLite 查询到 MiniMax-M3 自然语言生成 SQL
数据库·sql·sqlite
玖米GEO运营王总监2 小时前
2026年账号矩阵协同效应怎么量化:三个指标与公式结构
java·大数据·数据库
Rabitebla2 小时前
【Linux操作系统】进程篇(十一):进程程序替换——从底层原理到 exec 函数族
linux·服务器·c++·笔记·学习·算法
叼烟扛炮3 小时前
[LangChain] 学习笔记(03):打破失忆症——对话机制与上下文管理
java·前端·javascript·笔记·学习·langchain
景煜拾年3 小时前
InnoAI SQL 助手
运维·数据库·笔记·sql
旖旎夜光3 小时前
【C++ 基础入门】类和对象(下):初始化列表、static 成员、友元与内部类
c++·笔记·学习
LONGZHIQIN4 小时前
STM32学习笔记
笔记·stm32·学习·arm