最近一直在折腾架构的事儿,之前开发的能力在慢慢的恢复,今天给大家分享一下我在熟悉的过程一些技巧和遇到的一些坑
Nacos介绍
Nacos大家想必都不会很陌生,他是alibaba开源的一个微服务中间件,支持服务注册和配置管理,相较于Eureka来说,nacos在性能和使用方面还是比较合适国内开发者的,包括它的组件工具也比较全。
Nacos在做服务提供者(例如一个微服务实例)在启动时,会将自己的服务信息(如服务名称、IP 地址、端口号、服务的健康状态等)发送给 Nacos 服务器进行注册。例如,一个用户服务启动后,它会通过 Nacos 提供的客户端 SDK 或者相关的集成插件(如在 Spring Cloud Alibaba 中使用@EnableDiscoveryClient注解)将自身的信息注册到 Nacos 中,Nacos 会将这些信息存储在其服务注册表中。
Nacos 可以作为配置中心,集中存储应用程序的各种配置信息。这些配置可以是不同环境(如开发环境、测试环境、生产环境)下的配置文件,包括但不限于数据库连接信息、日志级别、服务的各种参数等。例如,将数据库连接的 URL、用户名和密码等配置信息存储在 Nacos 中,配置文件可以是properties格式或yaml格式。
Nacos Server是 Nacos 的核心服务器组件,负责处理服务注册与发现、配置管理等核心功能。它存储了服务注册表和配置信息,并且提供了相应的接口用于客户端的访问和操作。
Nacos Client是集成在应用程序中的客户端组件。它负责与 Nacos Server 进行通信,将服务注册信息发送给服务器,从服务器获取服务发现信息和配置信息,并且接收服务器发送的配置更新通知等。例如,在 Java 应用中,通过引入 Nacos 的客户端依赖,使用相关的 API 来实现与 Nacos Server 的交互。
控制台(Dashboard)是Nacos 提供的一个可视化的控制台,通过浏览器访问控制台可以方便地对服务和配置进行管理。在控制台上,可以查看服务的注册信息、实例状态,进行配置的编辑、发布和管理等操作。例如,管理员可以在控制台上轻松地添加新的服务、修改配置文件,以及监控各个服务的运行状态。
安装Nacos
安装Nacos其实很简单,建议通过官网下载并安装,官网介绍的步骤非常详尽,这里我就不过多介绍。
官网地址: https://nacos.io/docs/next/quickstart/quick-start/
使用Nacos注册服务
我这里是创建了一个简单的微服务项目
因为微服务项目会有一个总的工程项目,所以我创建了一个父级的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.leon.store</groupId>
<artifactId>store-examples</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<java.version>1.8</java.version>
</properties>
<!-- 依赖版本控制-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2020.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>store-loginserver</module>
<module>store-core</module>
</modules>
</project>
上面的POM文件是主工程的POM配置信息,下面的是我的store-loginserver服务的配置信息:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.leon.store</groupId>
<artifactId>store-examples</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<!-- 项目描述信息-->
<artifactId>store-loginserver</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>store-loginserver</name>
<!-- <name>SpringBootProject Maven Webapp</name>-->
<!-- <!– FIXME change it to the project's website –>-->
<!-- <url>http://www.example.com</url>-->
<!-- 项目中的一些属性变量,具有传递性-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- hystrix服务降级服务熔断-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</exclusion>
<exclusion>
<groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 微服务依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--redis引用-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- FastJson 引用-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<!-- Mybatis-plus引用-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.9</version>
</dependency>
<!-- 数据库驱动-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.4</version>
</dependency>
<!-- HikariCP 连接池-->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
<scope>compile</scope>
</dependency>
<!-- log4j2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!--nacos配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--nacos服务注册与发现中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-spring-context</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
<build>
<finalName>store-loginserver</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<mainClass>com.manage.project.ManageProject</mainClass>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
</includes>
</resource>
</resources>
</build>
</project>
使用nacos作为注册中心时,一定要注意不要忘记引用这两个pom,这是最为关键的,而且要注意版本,版本不合适的话会出现很多意想不到的问题
<!--nacos服务注册与发现中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
各组件间版本关系我截图放在这里了,大家自行对比
接下来配置应用服务store-loginserver的配置信息,主要是配置nacos的注册信息
server:
port: 8081
spring:
application:
name: manageproject
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: 2fa09388-6a71-45df-870b-a910b159ce21
discovery:
enabled: true
最后在主启动类加上@EnableDiscoveryClient 注解,在应用服务启动后,就能看到这个服务的注册情况啦
package com.manage.project;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@MapperScan("com.manage.project.mapper")
public class ManageProject {
public static void main(String[] args){
try{
SpringApplication.run(ManageProject.class,args);
}catch(Exception e){
e.printStackTrace();
}
}
}
当服务启动后,可以看到我的服务已经正常在Nacos服务列表里发现了。这里有的同学可能要问为什么服务名不是store-loginserver而是manageproject,这是因为在项目工程目录的application.yml文件中spring:application:name对应的值为managerproject,Nacos client发起注册时取的是该配置信息。
使用Nacos做配置中心
我不知道大家在实际工作中是否会将所有配置都放到配置中心,我的习惯是尽可能的将配置都放在配置中心,这样更便于配置管理,也不会出现测试环境打包的时候误将测试环境配置打到生产上(以前框架中没有使用配置中心的时候,已经被这个问题坑了好多次😭)
前面已经完成了Nacos的安装,不需要再重复操作,直接进入我们的项目工程中开始,Nacos的配置中心涉及到的POM配置包括以下关键内容
<!--nacos配置中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-spring-context</artifactId>
<version>1.1.2</version>
</dependency>
Nacos的相关配置最好要单独写在bootstrap.yml配置文件中,它加载的优先级高于application.yml,更利于我们一些需要初始化配置的加载
spring:
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: properties
enable-remote-sync-config: true
refresh-enabled: true
在这个配置中,我们指定了配置中心的地址server-add,指定了配置文件的格式file-extension,在Nacos中创建配置的时候也要按照这些信息去创建,配置文件的名字还是取的spring:application:name这个属性值,拼接上file-extension的属性值,就形成了一个简单的配置文件名称,也就是Data ID,当然Data ID还有很多高级用法,比如区分不同环境的,这里我们先不介绍。
在实际的代码编写中,我是对于业务属性的配置信息,我单独创建了一个ConfigLoader.java类,用于从Nacos获取配置,这样更方便对配置的管理,其他类在获取配置时,可以直接使用@AAutowried进行装载
package com.manage.project.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
@Component
@RefreshScope
public class ConfigLoader {
@Value("${testParam}")
private String testParam;
public String getTestParam(){
return testParam;
}
}
在编写配置类的时候,一定不要忘了增加@RefreshScope注解,否则你的配置可能无法实现动态刷新。这样通过@Value注解就可以轻松获取naco中的配置啦
避坑指南
在使用nacos搭建注册/配置中心时我也遇到了不少的问题,下面给大家一一列举一下
版本问题
在文章开始我就给大家介绍过在搭建框架时要提前了解相关组件的版本关系,最开始我也是踩了不少的坑,发现引入的版本一致存在冲突,当你引入的jar跟其他组件存在冲突时,可以通过下图Idea的工具进行查看,如果存在冲突,将会有红色的线显示出来
配置命名
Nacos的配置命名,也即是Data id ,它是有格式的
${prefix}-${spring.profile.active}.${file-extension}
prefix就是spring.application.name(也可以用配置文件中的配置spring.cloud.nacos.config.prefix来声明)
${spring.profile.active}表示不同的环境,可以通过它来进行不同环境的配置隔离,通常写dev、pro这些,如果不设置的话,它前面的“-”也不用写
file-extension就是配置文件的数据格式,通常我喜欢选择properties,因为用yaml真的容易出错
因为Data id的坑出现的问题真的不少,如果选择的配置格式是yaml,那么你data id一定要写成xxxxx.yaml,不要写xxxxx或xxxxx.yml
这里先介绍两点,如果大家还有其他遇到的难题也可以私信我,我来进行补充,让更多的人受益。