在前面的两篇中,我们分别介绍了项目的基本架构、相关知识,和整合 MyBatis-Plus 、Knife4j。这一篇,我们来介绍在项目中整合 Nacos、OpenFeign。

1. 注册中心管理

1.1. 关于 Nacos

Nacos 是 Dynamic Naming and Configuration Service 的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 的关键特性包括:服务发现和服务健康监测、动态配置服务、动态 DNS 服务、服务及其元数据管理。关于 Nacos 的更详细介绍请参考官方文档链接地址)。

1.2. 版本选择

由于我们 Spring Cloud Alibaba 选择的是 2022.0.0.0 版本,其中的 nacos-client 版本为 2.2.1,我们的 nacos-server 也选择版本为 2.2.1。

1.3. 搭建 nacos-server

1.3.1. 下载 nacos-server

nacos-server-2.2. 1 可到 GitHub 进行下载( 链接地址)。

1.3.2. 安装 nacos-server

以 Linux 系统为例,我们将 Nacos 的 nacos-server-2.2.1.tar.gz 安装包下载下来,然后上传到Linux服务器,例如上传到”/soft“目录下。

第一步:输入 tar -zxvf nacos-server-2.2.1.tar.gz 命令进行解压,解压后如下所示。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_COLA

第二步:创建数据库 mall-nacos,执行 nacos ”\conf“目录下的 mysql-schema.sql 文件。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud Alibaba_02

第三步:修改 application.properties 配置文件信息,将数据源连接信息修改为 mysql ,如下所示。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Boot3_03

注意:由于我们使用的 Nacos 是 2.2.1 版本,需执行以下变更。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Nacos、OpenFeign_04

nacos.core.auth.plugin.nacos.token.secret.key 的值为 Base 64 字符串,自己随便生成,长度超过32位即可。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud Alibaba_05

第四步:进入到 nacos 的 bin 目录执行 ”./startup.sh -m standalone“ 命令进行启动。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud_06

执行”cat /soft/nacos/logs/start.out“命令,查看启动日志。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Nacos、OpenFeign_07

第五步:看到启动日志没报错,就可以打开浏览器输入”http://{ip}:8848/nacos/#/login“进行访问了。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud Alibaba_08

输入用户名:nacos,密码:nacos,登录成功后如下所示。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Boot3_09

1.4. 服务注册

1.4.1. 整合 Nacos

给每个模块的 start 工程添加如下依赖。

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

然后,给 start 工程的启动类添加 @EnableDiscoveryClient 注解。例如,账户模块的启动类如下。

@Slf4j
@SpringBootApplication(scanBasePackages = {"org.example.account","org.example.component"})
@MapperScan("org.example.account.infra.mapper")
@EnableDiscoveryClient
public class MallAccountCenterApplication {

    public static void main(String[] args) {
        log.info("Begin to start Spring Boot Application");
        long startTime = System.currentTimeMillis();

        SpringApplication.run(MallAccountCenterApplication.class, args);

        long endTime = System.currentTimeMillis();
        log.info("End starting Spring Boot Application, Time used: "+ (endTime - startTime) );
    }
}

最后,在 application.yml 文件中配置 nacos-server 的地址。

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

1.4.2. 注册中心测试

启动各个模块的服务,登录 nacos,可以看到 mall-account-service、mall-product-service、 mall-order-service 都在服务列表中了。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Boot3_10

1.4.3. 名称空间与分组

1.4.3.1. 名称空间

名称空间(Namespace)用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

上面截图的服务列表中, mall-account-service、mall-product-service、 mall-order-service 三个服务,默认都注册到 public 名称空间下。为例区分开发环境和生成环境的配置信息,我们需要创建开发环境、生成环境的名称空间,让服务分别注册到对应的名称空间中。以开发环境为例,我们创建名称空间为:dev。如下图所示。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud Alibaba_11

配置文件,给账户模块、商品模块、订单模块指定名称空间。以账户模块为例,配置如下。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud_12

重新启动账户模块、商品模块、订单模块,可以看到三个服务都注册到dev名称空间下了。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_COLA_13

1.4.3.2. 配置分组

Nacos 中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如 database_url 配置和 MQ_topic 配置。

从上面的截图中可以看到,我们账户模块、商品模块、订单模块都是注册到 DEFAULT_GROUP 分组下的,我们给账户模块、商品模块、订单模块指定一个分组,取名为:mall。以账户模块为例,配置如下。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud Alibaba_14

重新启动账户模块、商品模块、订单模块,可以看到三个服务都归到mall分组下了。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Nacos、OpenFeign_15

1.5. 服务发现

1.5.1. 功能需求

实现在订单模块根据商品id查询商品信息。

1.5.2. 需求实现

要实现"在订单模块根据商品 id 查询商品信息"的功能,涉及到跨服务调用,由商品服务提供接口,让订单服务来调用,我们可以通过集成 OpenFeign 来实现微服务之间的调用。

1.5.3. 关于 OpenFeign

OpenFeign 是 Spring Cloud 中的组件,是一个声明式 REST 客户端。关于 OpenFeign 更详细的介绍,可以参考官网(链接地址)。

1.5.4. 整合 OpenFeign

给商品模块中的 mall-product-center-client 工程添加必要的依赖,如下。

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.example.product</groupId>
        <artifactId>mall-product-center</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>mall-product-center-client</artifactId>
    <name>mall-product-center-client</name>
    <description>api输出层</description>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--mall-product-center-dto-->
        <dependency>
            <groupId>org.example.product</groupId>
            <artifactId>mall-product-center-dto</artifactId>
        </dependency>
        <!--spring-cloud-starter-openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--2020版本以后就已经移除了对ribbon的支持,而是使用LoadBalancer-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>
    </dependencies>

</project>

在 mall-product-center-client 工程的 org.example.product.client 包目录下创建名称为 ProductClient 的接口,内容如下。

@FeignClient(name = BaseConstant.Domain.PRODUCT)
public interface ProductFeignClient {

    @Operation(summary = "根据id查询商品信息")
    @GetMapping(BaseConstant.AdapterType.CLIENT+"/product/v1/queryById/{id}")
    @Parameter(name = "id",description = "商品id",required = true)
    ProductRspDTO queryById(@PathVariable(value = "id") Long id);
}

其中,常量 BaseConstant.Domain.PRODUCT 对应服务名 mall-product-service。

在 mall-product-center-adapter 工程的 org.example.product.adapter.client 目录下添加 ProductClient 接口的实现类,名称为 ProductClientController ,内容如下。

@Slf4j
@Tag(name = "product-client端api")
@RestController
public class ProductClientController implements ProductFeignClient {

    @Resource
    private ProductExecutor productExecutor;

    @Override
    public ProductRspDTO queryById(Long id){
        log.info("query product detail,id is :{}",id);
        return this.productExecutor.queryProductById(id);
    }
}

1.5.5. 本地接口测试

在 mall-product-center-dto 工程的 Knife4jConfig 类中新增 client 分组,代码如下。

@Bean
    public GroupedOpenApi clientApi() {
        return GroupedOpenApi.builder()
                .group("adapter-"+BaseConstant.AdapterType.CLIENT)
                .pathsToMatch("/"+ BaseConstant.AdapterType.CLIENT+"/**")
                .build();
    }

启动商品服务,访问 http://localhost:7040/doc.html ,打开 Knife4j 文档。选择 adapter-client 组。找到”根据id查询商品信息“ 接口,输入商品id,测试如下。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_COLA_16

1.5.6. 跨服务调用测试

在订单模块的 mall-order-center-app 工程中添加 mall-product-center-client 工程的依赖,如下。

<!--mall-product-center-client-->
        <dependency>
            <groupId>org.example.product</groupId>
            <artifactId>mall-product-center-client</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

在订单模块 mall-order-center-start 启动类添加 @EnableFeignClients 注解。

@Slf4j
@SpringBootApplication(scanBasePackages = {"org.example.order","org.example.component"})
@MapperScan("org.example.order.infra.mapper")
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "org.example.*")
public class MallOrderCenterApplication {

    public static void main(String[] args) {
        log.info("Begin to start Spring Boot Application");
        long startTime = System.currentTimeMillis();

        SpringApplication.run(MallOrderCenterApplication.class, args);

        long endTime = System.currentTimeMillis();
        log.info("End starting Spring Boot Application, Time used: "+ (endTime - startTime) );
    }
}

在订单模块 mall-order-center-app 工程的 OrderExecutor 类中实现接口调用。

@Component
public class OrderExecutor {

    @Resource
    private OrderService orderService;
    @Resource
    private ProductFeignClient productFeignClient;

    /**
     *本地CRUD方法,省略粘贴。
     */

    /**
     *  根据商品id查询商品信息
     */
    public ProductRspDTO queryProductById(Long id) {
        return this.productFeignClient.queryById(id);
    }

}

启动订单服务,访问 http://localhost:7050/doc.html ,打开 Knife4j 文档。选择 adapter-web 组。找到”根据id查询商品信息“ 接口,输入商品id,测试如下。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud Alibaba_17

2. 配置中心管理

Nacos 不仅可以作为注册中心,还可以作为配置中,使用 Nacos 作为配置中心,可以更方便地对配置信息进行管理。

目前,我们的账户模块、商品模块、订单模块都涉及到数据库连接配置,可以使用 Nacos 将数据库连接配置信息抽取出来创建单独的文件,供各个模块使用。对应 Knife4j 的配置,也可以统一做成一个文件,供各个模块使用。

下面我们来实现使用 Nacos 作为配置中心。

2.1. 配置中心实现

给每个模块的 start 工程添加如下配置中心依赖。

<!-- nacos配置中心-->
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 2020.X.X版本官方重构了bootstrap引导配置的加载方式,需要添加以下依赖 -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

在 Nacos 中,分别创建 datasource.yaml、knife4j.yaml。

datasource.yaml 内容如下。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_COLA_18

knife4j.yaml 内容如下。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud Alibaba_19

配置列表如下所示。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Boot3_20

每个模块的 start 工程 resources 目录下的 application.yml 文件,改名为 bootstrap.yml 。这里修改文件名,是为了保证工程中的配置先于 Nacos 中的配置信息被加载。

配置信息加载顺序依次为:bootstrap.properties、bootstrap.yml、application.properties、application.yml 。

在每个模块的 start 工程 resources 目录下创建 bootstrap.properties 文件,该文件主要用来定义变量信息,供 bootstrap.yml 文件引用。以账户模块为例,bootstrap.properties 文件内容如下。

#nacos服务地址
NACOS_ADDR=127.0.0.1:8848
#nacos名称空间
NACOS_NAMESPACE=dev
#数据库名称
DB_NAME=mall-account

在 bootstrap.yml 文件中引用 Nacos 配置信息。以账户模块为例,bootstrap.yml 文件内容如下。

server:
  port: 7030
spring:
  application:
    name: mall-account-service
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_ADDR}
        namespace: ${NACOS_NAMESPACE}
        group: mall
      config:
        server-addr: ${NACOS_ADDR}
        namespace: ${NACOS_NAMESPACE}
        file-extension: yaml
        group: mall
        extension-configs:
          - data-id: datasource.yaml
            group: mall
            refresh: true
          - data-id: knife4j.yaml
            group: mall
            refresh: true

基于以上 bootstrap.yml 的配置,如果有新的组件(例如:redis)需要增加配置信息,我们就可以在 Nacos 上继续新增 yaml 文件,然后将 yaml 文件名追加到 bootstrap.yml 文件中即可。若是修改某个 yaml 文件的配置信息,则直接在 Nacos 上进行修改即可。

2.2. 配置中心测试

重新启动各个模块的服务,可以看到服务都正常注册。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud_21

测试"在订单模块根据商品 id 查询商品信息"的功能,也是正常返回。

基于 COLA 架构的 Spring Cloud Alibaba(三)整合 Nacos、OpenFeign_Spring Cloud Alibaba_22

3. 总结

本篇先介绍了 Nacos 的搭建。然后介绍了以 Nacos 作为注册中,实现微服务的注册与发现,并分别进行了测试。在介绍 Nacos 服务发现的过程中,我们集成了 OpenFeign 作为 REST 客户端,以实现跨服务之间的接口调用。最后介绍了用 Nacos 作为配置中心,以便更好地对配置信息进行管理。


基础篇项目代码:链接地址