主流配置中心對比:
目前市面上用的比較多的配置中心有: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