Nacos配置管理
主流配置中心对比:
目前市面上用的比较多的配置中心有:Spring Cloud Config、Apollo、Nacos和Disconf等。
由于Disconf不再维护,下面主要对比一下Spring Cloud Config、Apollo和Nacos。
nacos 1.2.0版本已支持权限控制
从配置中心角度来看,性能方面Nacos的读写性能最高,Apollo次之,Spring Cloud Config依赖Git场景不适合开放的大规模自动化运维API。功能方面Apollo最为完善,nacos具有Apollo大部分配置管理功能,而Spring Cloud Config不带运维管理界面,需要自行开发。Nacos的一大优势是整合了注册中心、配置中心功能,部署和操作相比Apollo都要直观简单,因此它简化了架构复杂度,并减轻运维及部署工作。
Nacos 简介:https://nacos.io/zh-cn/
Nacos是阿里的一个开源产品,它是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案。
Nacos 特性:
Nacos主要提供以下四大功能:
1. 服务发现与服务健康检查
Nacos使服务更容易注册,并通过DNS或HTTP接口发现其他服务,Nacos还提供服务的实时健康检查,以防止向不健康的主机或服务实例发送请求。
2. 动态配置管理
动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。Nacos消除了在更新配置时重新部署应用程序,这使配置的更改更加高效和灵活。
3. 动态DNS服务
Nacos提供基于DNS 协议的服务发现能力,旨在支持异构语言的服务发现,支持将注册在Nacos上的服务以域名的方式暴露端点,让三方应用方便的查阅及发现。
4. 服务和元数据管理
Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略。
Nacos 快速入门:
Nacos 依赖 Java 环境来运行(JDK 1.8+)
下载源码或者安装包 https://github.com/alibaba/nacos/releases
启动服务器:nacos的默认端口是8848,需要保证8848默认端口没有被其他进程占用
启动命令:cmd startup.cmd 或者双击startup.cmd运行文件。
启动成功,可通过浏览器访问 http://127.0.0.1:8848/nacos
使用默认用户名:nacos,默认密码:nacos 登录即可打开主页面。
外部mysql数据库支持:单机模式时nacos默认使用嵌入式数据库实现数据的存储,若想使用外部mysql存储nacos数据,需要进行以下步骤:
1. 安装数据库,版本要求:5.6.5+ ,mysql 8 以下
2. 初始化mysql数据库,新建数据库nacos_config,数据库初始化文件已存放在安装目录中:/conf/nacos-mysql.sql
3. 修改 /conf/application.properties 文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。
spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password=root
Nacos配置入门:
发布配置:浏览器访问 http://127.0.0.1:8848/nacos ,打开nacos控制台,并点击菜单配置管理->配置列表,在Nacos添加配置:
注意Data ID是以properties(默认的文件扩展名方式)为扩展名,这里使用yaml。
nacos客户端获取配置:
新增一个项目,引入依赖
<dependencies> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.1.1</version> </dependency> </dependencies>
获取外部化配置
public class SimpleDemoMain { public static void main(String[] args) throws NacosException { //nacos 地址 String serverAddr = "127.0.0.1:8848"; //Data Id String dataId = "nacos_simple_demo.yaml"; //Group String group = "DEFAULT_GROUP"; Properties properties = new Properties(); properties.put("serverAddr", serverAddr); // properties.put("namespace", "xxx"); ConfigService configService = NacosFactory.createConfigService(properties); //获取配置,String dataId, String group, long timeoutMs String content = configService.getConfig(dataId, group, 5000); System.out.println(content); // common: // config1: something } }
Nacos 配置管理基础应用:
Nacos抽象定义了Namespace、Group、Data ID的概念,具体这几个概念代表什么,取决于我们把它们看成什么,这里推荐给大家一种用法,如下图:
Namespace :代表不同环境,如开发、测试、生产环境。
Group:代表某项目,如XX医疗项目、XX电商项目
DataId:每个项目下往往有若干个工程,每个配置集(DataId)是一个工程的主配置文件
获取配置集需要指定:
1、nacos服务地址,必须指定
2、namespace,如不指定默认public
3、group,如不指定默认 DEFAULT_GROUP
4、dataId,必须指定
登录管理:
Nacos当前版本支持简单的登录功能,默认用户名/密码为: nacos/nacos 。
修改默认用户名/密码方法:
1. 生成加密密码
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring‐security‐core</artifactId> <version>5.1.4.RELEASE</version> </dependency>
编写PasswordEncoderUtil类,生成加密后的密码,采用BCrypt加密方法在每次生成密码时会加随机盐,所以生成密码每次可能不一样。
public class PasswordEncoderUtil { public static void main(String[] args) { System.out.println(new BCryptPasswordEncoder().encode("root")); } }
2.将上边程序输出的密码更新到数据库。
INSERT INTO users (username, `password`, enabled) VALUES ('root', '$2a$10$aZtWrA/07boLUy3VbuiIdeUqM5ioVCzySXG1egPq4mvtV9j.0j2bK', TRUE); INSERT INTO roles (username, role) VALUES ('root', 'ROLE_ADMIN');
关闭登录功能:
修改安装目录中 conf/application.properties 文件
spring.security.enabled=false management.security=false security.basic.enabled=false nacos.security.ignore.urls=/** #nacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/v1/auth/login,/v1/console/health/**,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**,/v1/console/server/**
Nacos 配置管理应用于分布式系统:
用户通过 Nacos Server的控制台集中对多个服务的配置进行管理。
各服务统一从 Nacos Server中获取各自的配置,并监听配置的变化。
发布配置:
在Nacos添加如下的配置:( Namespace为开发环境)
service1
service2
创建父工程:
父工程pom.xml如下:
<properties> <project.build.sourceEncoding>UTF‐8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF‐8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring‐cloud‐alibaba‐dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring‐cloud‐dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring‐boot‐dependencies</artifactId> <version>2.1.3.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring‐boot‐maven‐plugin</artifactId> </plugin> </plugins> </build>
微服务service1配置:
新建子模块service1,引入依赖:
<dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>2.1.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.1.3.RELEASE</version> </dependency> </dependencies>
bootstrap.yml配置:
一般来说,spring boot的配置将在application.yml(也可以是application.properties)文件中编写, 由于使用外部配置中心,必须将原先的application.yml重命名为bootstrap.yml
server:
port: 56010
spring:
application:
name: service1
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心地址
file-extension: yaml #dataId由应用名称(name)加文件扩展名组成 service1.yaml
namespace: b0818a15-92f4-438b-ab16-1b0d13c1d225 #开发环境
group: TEST_GROUP #测试组
启动配置客户端:
@SpringBootApplication @RestController public class Service1Bootstrap { public static void main(String[] args) { SpringApplication.run(Service1Bootstrap.class, args); } @Value("${common.name}") private String config1; @GetMapping(value = "/configs") public String getConfigs() { return config1; } }
微服务service2配置:
新建子模块service2,引入依赖:依赖和service1相同
bootstrap.yml配置:
server: port: 56020 spring: application: name: service2 cloud: nacos: config: server-addr: 127.0.0.1:8848 #配置中心地址 file-extension: yaml #dataId由应用名称(name)加文件扩展名组成 service1.yaml,如果配置了spring.profiles.active:dev指定了环境,则dataId为service1-dev.yaml namespace: b0818a15-92f4-438b-ab16-1b0d13c1d225 #开发环境 group: TEST_GROUP #测试组
启动配置客户端:
@SpringBootApplication @RestController public class Service2Bootstrap { public static void main(String[] args) { SpringApplication.run(Service2Bootstrap.class, args); } @Value("${common.name}") private String config2; @GetMapping(value = "/configs") public String getConfigs() { return config2; } }
支持配置的动态更新(上面的获取方式并不能自动获取Nacos更新后的配置信息):除了下面的方法,还可以在对应的类上添加注解@RefreshScope实现配置动态更新
// 注入配置文件上下文 @Autowired private ConfigurableApplicationContext applicationContext; // @Value("${common.name}") // private String config2; @GetMapping(value = "/configs") public String getConfigs() { // return config2; return applicationContext.getEnvironment().getProperty("common.name"); }
注意:可以通过配置spring.cloud.nacos.config.refresh.enabled=false来关闭动态刷新
自定义扩展的 Data Id 配置:既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置文件
server: port: 56010 spring: application: name: service1 cloud: nacos: config: server-addr: 127.0.0.1:8848 #配置中心地址 file-extension: yaml #dataId由应用名称(name)加文件扩展名组成 service1.yaml namespace: b0818a15-92f4-438b-ab16-1b0d13c1d225 #开发环境 group: TEST_GROUP #测试组 # 1、Data Id 在默认的组 DEFAULT_GROUP,不支持配置的动态刷新 ext-config[0]: data-id: ext_config_common01.properties # 2、Data Id 不在默认的组,不支持动态刷新 ext-config[1]: data-id: ext_config_common02.properties group: GLOBALE_GROUP # 3、Data Id 既不在默认的组,也支持动态刷新 ext-config[2]: data-id: ext_config_common03.properties group: REFRESH_GROUP refresh: true
// 注入配置文件上下文 @Autowired private ConfigurableApplicationContext applicationContext; @GetMapping(value = "/configs2") public String getConfigs2() { String name = applicationContext.getEnvironment().getProperty("common.name"); String age = applicationContext.getEnvironment().getProperty("common.age"); String address = applicationContext.getEnvironment().getProperty("common.address"); String birthday = applicationContext.getEnvironment().getProperty("common.birthday"); String sex = applicationContext.getEnvironment().getProperty("common.sex"); return name + "+" + age + "+" + address + "+" + birthday + "+" + sex; }
完全关闭配置:
通过设置 spring.cloud.nacos.config.enabled = false 来完全关闭 Spring Cloud Nacos Config
Nacos集群部署:
1.集群部署
(1)安装3个以上Nacos
复制之前已经解压好的nacos文件夹,分别命名为nacos、nacos1、nacos2
由于是单机演示,需要更改nacos/的conf目录下application.properties中server.port,防止端口冲突。
如果每个服务器使用不同的ip,要指定具体的ip地址,如:nacos.inetutils.ip-address=127.0.0.1
(2)配置集群配置文件
在所有nacos目录的conf目录下,有文件 cluster.conf.example ,将其命名为 cluster.conf ,并将每行配置成 ip:port。
# ip:port
127.0.0.1:8848
127.0.0.1:8849
127.0.0.1:8850
(3)集群模式启动
分别执行nacos目录的bin目录下的startup:startup ‐m cluster
在任意一个nacos的控制台中,可以看到如下内容:
2.客户端配置
所有客户端,分别指定nacos集群中的若干节点:
3.生产环境部署建议
官方推荐的集群方案,通过域名 + VIP模式的方式来实现。客户端使用域名方式配置,当Nacos集群迁移时,客户端配置无需修改。
至于数据库,生产环境下建议至少主备模式。通过修改 conf/application.properties 文件,能够使nacos拥有多个数据源。
spring.datasource.platform=mysql db.num=2 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&autoReconnect=true db.url.1=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&autoReconnect=true db.user=root db.password=root