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。
配置本地优先:
yaml
复制代码
#配置本地优先 spring: cloud: config: override-none: true
之后再创建实例的时候,可以通过添加参数的方式去配置端口等。
如何灵活的切换配置文件?
传参:
spring.profiles.active=test还是dev还是prod等
实例
特有配置
yaml
复制代码
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里的服务。
所以
yaml
复制代码
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里的
要注意区分服务注册发现和服务配置文件的信息。
yaml
复制代码
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
xml
复制代码
<!-- 上报服务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>
结果:
ini
复制代码
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里配置:
yaml
复制代码
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文件里也没有。
yaml
复制代码
#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工程里用扩展引用
yaml
复制代码
#发送请求的时候,自带/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
里的部分
yaml
复制代码
extension-configs: - data-id: content-service-${spring.profiles.active}.yaml group: xuecheng-plus-project refresh: true profiles: active: dev #环境名,拼接配置文件用的
service的nacos里的配置:
yaml
复制代码
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可以当成项目名字或者分类。
将
yaml
复制代码
#logging # 日志文件配置路径 logging: config: classpath:log4j2-dev.xml
yaml
复制代码
swagger: title: "学成在线项目结构文档" description: "学成在线内容管理系统接口文档" base-package: com.xuecheng version: 1.0.0 enabled: true
都配置到nacos里的新建公共分组xuecheng-plus-common里
本地配置:
yaml
复制代码
#发送请求的时候,自带/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 #环境名,拼接配置文件用的
新增:
yaml
复制代码
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
复制代码
<?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配置:
yaml
复制代码
#微服务配置 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)的微服务。
yaml
复制代码
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以上,有一个窗口期。