Nacos
为什么要在Nacos进行配置?
方便管理,不用重启项目就可以更改配置。如果微服务的实例多了,里面的配置可以方便统一管理。
配置三要素
搭建完成Nacos服务发现中心,下边搭建Nacos为配置中心,其目的就是通过Nacos去管理项目的所有配置。
先将项目中的配置文件分分类:
1、每个项目特有的配置
是指该配置只在有些项目中需要配置,或者该配置在每个项目中配置的值不同。
比如:spring.application.name每个项目都需要配置但值不一样,以及有些项目需要连接数据库而有些项目不需要,有些项目需要配置消息队列而有些项目不需要。
2、项目所公用的配置
是指在若干项目中配置内容相同的配置。比如:redis的配置,很多项目用的同一套redis服务所以配置也一样。swagger的配置,log的配置等等
另外还需要知道nacos如何去定位一个具体的配置文件,即:namespace、group、dataid.
1、通过namespace、group找到具体的环境和具体的项目。
2、通过dataid找到具体的配置文件,dataid有三部分组成
比如:content-service-dev.yaml配置文件 由(content-service)-(dev). (yaml)三部分组成
content-service:第一部分,它是在application.yaml中配置的应用名,即spring.application.name的值。
dev:第二部分,它是环境名,通过spring.profiles.active指定,
Yaml: 第三部分,它是配置文件 的后缀,目前nacos支持properties、yaml等格式类型,本项目选择yaml格式类型。
所以,如果我们要配置content-service工程的配置文件:
在开发环境中配置content-service-dev.yaml
在测试环境中配置content-service-test.yaml
在生产环境中配置content-service-prod.yaml
我们启动项目中传入spring.profiles.active的参数决定引用哪个环境的配置文件,例如:传入spring.profiles.active=dev表示使用dev环境的配置文件即content-service-dev.yaml。
3.配置优先级
如果本地的配置和nacos的配置文件有冲突,那么,以谁的为主?
应用场景:该工程在开发环境启动一个实例,又由于开发需要,在启动一个实例,需要更改端口,但是只是开发需要,去改nacos不合理,这时候就适合在本地改动配置。
到目前为止已将所有微服务的配置统一在nacos进行配置,用到的配置文件有本地的配置文件 bootstrap.yaml和nacos上的配置文件,SpringBoot读取配置文件 的顺序如下:
引入配置文件的形式有:
1、以项目应用名方式引入
2、以扩展配置文件方式引入
3、以共享配置文件 方式引入
4、本地配置文件
1,2,3都在nacos。4在本地
各配置文件 的优先级:项目应用名配置文件 > 扩展配置文件 > 共享配置文件 > 本地配置文件。
有时候我们在测试程序时直接在本地加一个配置进行测试,比如下边的例子:
我们想启动两个内容管理微服务,此时需要在本地指定不同的端口,通过VM Options参数,在IDEA配置启动参数。
通过-D指定参数名和参数值,参数名即在bootstrap.yml中配置的server.port。
启动ContentApplication2,发现端口仍然是63040,这说明本地的配置没有生效。
这时我们想让本地最优先,可以在nacos配置文件 中配置如下即可实现。
再次启动ContentApplication2,端口为63041。
配置本地优先:
#配置本地优先
spring:
cloud:
config:
override-none: true
之后再创建实例的时候,可以通过添加参数的方式去配置端口等。
如何灵活的切换配置文件?
传参:
spring.profiles.active=test还是dev还是prod等
实例
特有配置
spring:
application:
name: content-api #服务名称
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
username: root
password: mysql
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery:
namespace: devNeu
group: xuecheng-plus-project
这里在配置的时候,服务名称,server-addr和group,namespace都不能配到ncaos里,因为如果配置走,本地将无法发现nacos里的服务。
所以
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery:
namespace: devNeu
group: xuecheng-plus-project
和
application:
name: content-api #服务名称
不能配置到nacos的配置文件里。
需要拼装配置文件的例如content-api-dev.yaml里的东西在本地都不能删除。
本地配置的时候不要忘了配置config
注意区分profiles下的active的dev和自己的namespace里的
要注意区分服务注册发现和服务配置文件的信息。
spring:
application:
name: content-api #服务名称
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
# username: root
# password: mysql
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery: #服务注册发现的相关配置
namespace: devNeu
group: xuecheng-plus-project
config: #配置文件的相关信息
namespace: devNeu #我的命名空间,无论是配置也好,服务也好,都在我的命名空间下
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
profiles:
active: dev #环境名,拼接配置文件用的
注意对应配置文件的依赖
如果想用注册,就加discovery,如果想用配置中心,就加config
<!-- 上报服务nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- nacos配置依赖-->
<!-- 微服务里有一个配置的客户端,去nacos定时的拉取配置-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
结果:
2023-10-21 14:11:44,739 DEBUG [com.alibaba.nacos.client.Worker.longPolling.fixed-192.168.101.65_8848-devNeu][NacosRestTemplate.java:476] - HTTP method: POST, url: http://192.168.101.65:8848/nacos/v1/cs/configs/listener, body: {Listening-Configs=content-api-dev.yaml•xuecheng-plus-project•b1560ddf63798a362c47f567fa2516e2•devNeu•content-api.yaml•xuecheng-plus-project••devNeu•content-api•xuecheng-plus-project••devNeu•, tenant=devNeu}
2023-10-21 14:11:44,739 DEBUG [com.alibaba.nacos.client.Worker.longPolling.fixed-192.168.101.65_8848-devNeu][NacosRestTemplate.java:494] - Execute via interceptors :[com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$LimiterHttpClientRequestInterceptor@403264c2]
2023-10-21 14:11:44,759 DEBUG [com.alibaba.nacos.client.Worker.longPolling.fixed-192.168.101.65_8848-devNeu][NacosRestTemplate.java:476] - HTTP method: POST, url: http://192.168.101.65:8848/nacos/v1/cs/configs/listener, body: {Listening-Configs=content-api-dev.yaml•xuecheng-plus-project•b1560ddf63798a362c47f567fa2516e2•devNeu•content-api.yaml•xuecheng-plus-project••devNeu•content-api•xuecheng-plus-project••devNeu•, tenant=devNeu}
从nacos里拿配置
接口层本身是不需要配置数据库的,但是他依赖着service层的代码,当打包启动的时候,就将service的mapper,service等代码全部依赖到接口层工程,接口层本身是不需要数据库连接的。
所以,在service层里配置数据库,在接口层去引用service工程的
service模块下的test里的bootstrap.yml里配置:
spring:
application:
name: content-service #服务名称
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
# username: root
# password: mysql
cloud:
nacos:
server-addr: 192.168.101.65:8848
config: #配置文件的相关信息
namespace: devNeu #我的命名空间,无论是配置也好,服务也好,都在我的命名空间下
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
profiles:
active: dev #环境名,拼接配置文件用的
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
# username: root
# password: mysql
# 日志文件配置路径
logging:
config: classpath:log4j2-dev.xml
我们的接口工程里不需要直接配置数据库,而是去引用service的。
api工程没有数据库连接,api的nacos文件里也没有。
#nacos配置里也注释掉datasource
server:
servlet:
context-path: /content
port: 63040
# spring:
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
# username: root
# password: mysql
api工程里用扩展引用
#发送请求的时候,自带/content内容,这个服务里就不用再写了
#server:
# servlet:
# context-path: /content
# port: 63040
#微服务配置
spring:
application:
name: content-api #服务名称
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
# username: root
# password: mysql
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery: #服务注册的相关配置
namespace: devNeu
group: xuecheng-plus-project
config: #配置文件的相关信息
namespace: devNeu #我的命名空间,无论是配置也好,服务也好,都在我的命名空间下
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
extension-configs:
- data-id: content-service-${spring.profiles.active}.yaml
group: xuecheng-plus-project
refresh: true
profiles:
active: dev #环境名,拼接配置文件用的
# 日志文件配置路径
logging:
config: classpath:log4j2-dev.xml
swagger:
title: "学成在线内容管理系统"
description: "学成在线内容管理系统接口文档"
base-package: com.xuecheng.content
version: 1.0.0
enabled: true
里的部分
extension-configs:
- data-id: content-service-${spring.profiles.active}.yaml
group: xuecheng-plus-project
refresh: true
profiles:
active: dev #环境名,拼接配置文件用的
service的nacos里的配置:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
username: root
password: mysql
api接口工程重启,如果能正常查询数据库,则证明配置成功。
当一个服务想要依赖另一个服务里的配置的时候,可以考虑用extension-configs:
公用配置
logging,swagger等。
公用配置,group可以当成项目名字或者分类。
将
#logging
# 日志文件配置路径
logging:
config: classpath:log4j2-dev.xml
swagger:
title: "学成在线项目结构文档"
description: "学成在线内容管理系统接口文档"
base-package: com.xuecheng
version: 1.0.0
enabled: true
都配置到nacos里的新建公共分组xuecheng-plus-common里
本地配置:
#发送请求的时候,自带/content内容,这个服务里就不用再写了
#server:
# servlet:
# context-path: /content
# port: 63040
#微服务配置
spring:
application:
name: content-api #服务名称
# datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://192.168.101.65:3306/xcplus_content?serverTimezone=UTC&userUnicode=true&useSSL=false&
# username: root
# password: mysql
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery: #服务注册的相关配置
namespace: devNeu
group: xuecheng-plus-project
config: #配置文件的相关信息
namespace: devNeu #我的命名空间,无论是配置也好,服务也好,都在我的命名空间下
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
extension-configs:
- data-id: content-service-${spring.profiles.active}.yaml
group: xuecheng-plus-project
refresh: true
shared-configs: #共享文件,nacos里
- data-id: swagger-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
- data-id: logging-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
profiles:
active: dev #环境名,拼接配置文件用的
新增:
shared-configs:
- data-id: swagger-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
- data-id: logging-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
网关配置
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>
<parent>
<groupId>com.xuecheng</groupId>
<artifactId>xuecheng-plus-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../xuecheng-plus-parent</relativePath>
</parent>
<artifactId>xuecheng-plus-gateway</artifactId>
<dependencies>
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--服务发现中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 排除 Spring Boot 依赖的日志包冲突 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Spring Boot 集成 log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
本地:
yml配置:
#微服务配置
spring:
application:
name: gateway
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery:
namespace: devNeu
group: xuecheng-plus-project
config:
namespace: devNeu
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
shared-configs:
- data-id: logging-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
profiles:
active: dev
nacos中:
gateway-dev.yaml
- Path=/content/** # 这个是按照路径匹配,只要以/content/开头就符合要求,都会路由到id值(例如content-api)的微服务。
server:
port: 63010 # 网关端口
spring:
cloud:
gateway:
# filter:
# strip-prefix:
# enabled: true
routes: # 网关路由配置
- id: content-api # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://content-api # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/content/** # 这个是按照路径匹配,只要以/content/开头就符合要求,都会路由到id值的微服务。
# filters:
# - StripPrefix=1
- id: system-api
# uri: http://127.0.0.1:8081
uri: lb://system-api
predicates:
- Path=/system/**
# filters:
# - StripPrefix=1
- id: media-api
# uri: http://127.0.0.1:8081
uri: lb://media-api
predicates:
- Path=/media/**
# filters:
# - StripPrefix=1
- id: search-service
# uri: http://127.0.0.1:8081
uri: lb://search
predicates:
- Path=/search/**
# filters:
# - StripPrefix=1
- id: auth-service
# uri: http://127.0.0.1:8081
uri: lb://auth-service
predicates:
- Path=/auth/**
# filters:
# - StripPrefix=1
- id: checkcode
# uri: http://127.0.0.1:8081
uri: lb://checkcode
predicates:
- Path=/checkcode/**
# filters:
# - StripPrefix=1
- id: learning-api
# uri: http://127.0.0.1:8081
uri: lb://learning-api
predicates:
- Path=/learning/**
# filters:
# - StripPrefix=1
- id: orders-api
# uri: http://127.0.0.1:8081
uri: lb://orders-api
predicates:
- Path=/orders/**
# filters:
# - StripPrefix=1
503报错: 服务不可用。
服务不是立即启动完毕,nacos就可以发现服务,需要等30s以上,有一个窗口期。