Nacos是可以代替SpringCloud Eureka和SpringCloud Config的開源組件,有了它我們就不用自己配置和搭建服務端了,服務端直接從最新的發布版本下載即可,我們只需要在服務機器上啟動。
首先我們需要從github的官方地址下載最新版本的壓縮包。解壓縮后進入到bin目錄下,因為我的環境是自己的windows開發機器,所以需要修改startup.cmd中的模式為單機模式。然后再啟動服務端。
set MODE="standalone"
此時訪問localhost:8848/nacos就能訪問已經啟動的服務端應用了。
一、Nacos作為注冊中心
我們創建一個springcloud父工程,只包含web依賴。然后基于該父工程,分別創建服務提供者Provider和消費者Consumer工程。
1.1 服務提供者Provider
需要的依賴如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.1</version>
</dependency>
配置文件如下:
server:
port: 8091
spring:
application:
name: nacos-provider
cloud:
nacos:
server-addr: localhost:8848
然后我們創建一個controller來模擬Provider對外提供服務:
@RestController
public class HelloController {
@GetMapping("/getHello")
public String getHello(){
return "hello from nacos provider!";
}
}
最后,我們在啟動類上添加啟動注解。
@EnableDiscoveryClient
@SpringBootApplication
public class DiscoveryProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryProviderApplication.class, args);
}
}
到此,我們服務提供者就創建好了,在localhost:8091端口等待被調用提供服務。
1.2 服務消費者Consumer
需要的依賴如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.0.3</version>
</dependency>
配置文件如下:
server:
port: 8092
spring:
application:
name: nacos-consumer
cloud:
nacos:
server-addr: localhost:8848
接下來也創建一個Controller類,對外提供調用的接口,然后在Controller中通過OpenFeign轉發調用請求給到Provider。
@RestController
public class HelloController {
@Autowired
private FeignService feignService;
@GetMapping("/getHello")
public String getHello(){
return feignService.getHello();
}
}
@FeignClient("nacos-provider")
public interface FeignService {
@GetMapping("/getHello")
String getHello();
}
如上Service表示需要請求注冊中心中服務名稱為nacos-provider的/getHello接口。
最后,我們需要在啟動類上加上啟動注解。
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class DiscoveryConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryConsumerApplication.class, args);
}
}
到此,消費者Consumer也創建好了,在localhost:8092提供調用服務。我們訪問Consumer的/getHello接口,獲得的返回內容為:
hello from nacos provider!
此時登錄nacos服務端,服務管理,也能看到剛剛注冊上來的消費者和服務提供者。
二、Nacos作為配置中心
我們以如上provider項目作為示例項目進行如下配置中心功能的演示。
2.1 入門案例
首先我們需要引入必要的依賴包:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2021.1</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
其次,我們在啟動配置文件bootstrap.properties
中配置如下的內容:
spring.application.name=nacos-provider
spring.cloud.nacos.server-addr=127.0.0.1:8848
然后我們創建一個Controller就可以演示從遠端獲取配置內容了:
@RefreshScope
@RestController
public class ConfigController {
@Value("${provider.name}")
private String providerName;
@GetMapping("/getDevConfig")
public String getDevConfig(){
return this.providerName;
}
}
代碼層面的示例都已經寫好了,我們在遠端nacos服務端,切換到配置管理的配置列表界面,需要點擊+號新建一個:
- DataID,該字段的取名是有規則的,一般而言分為三個部分,
{1}-{2}.{3}
,其中第一部分應該和剛才本地bootstrap.properties中配置的spring.application.name完全一樣;第二部分表示生效的環境名稱,比如dev、stg等;第三部分表示配置文件后綴,只支持properties或者yaml類型。在這里,我們的值應該為nacos-provider.properties
; - Group,這里先設置默認的
DEFAULT_GROUP
即可; - 配置內容,把需要保存在遠端Nacos的配置內容寫在里面即可,這里為
provider.name=nacos123
;
配置點擊發布后,我們啟動本地的nacos-provider服務,訪問Controller,就會發現讀取到了nacos123的配置內容。
2.2 配置文件的環境區分
在實際使用時,我們一般都是區分dev、stg、prd三套環境來維護各個環境的配置文件內容的。在這樣的情況下,我們的應用程序如何讀取不同環境下的配置內容呢?
2.2.1 通過profile區分
首先我們在Nacos配置中心再增加兩個DataID,分別如下:
# nacos-provider-dev.properties
# DEFAULT_GROUP
provider.name=nacos-dev
# nacos-provider-stg.properties
# DEFAULT_GROUP
provider.name=nacos-stg
為了讓這兩個配置文件生效,我們在本地應用端的bootstrap.properties
中指定生效配置文件的環境名稱即可:
spring.application.name=nacos-provider
spring.cloud.nacos.server-addr=127.0.0.1:8848
spring.profiles.active=dev
# spring.profiles.active=stg
如此,再重啟我們的應用,就能讀取到各自環境的配置文件了。
2.2.2 通過namespace區分
默認我們會到public這個命名空間下去讀取配置文件,此時我們新建兩個命名空間,分別命名為dev和stg,然后將public命名空間下的nacos-provider.properties
克隆到dev和stg命名空間下,并修改provider.name的配置內容:
# namespace dev
provider.name=nacos-dev-123
# namespace stg
provider.name=nacos-stg-123
然后我們在本地的應用中增加一個配置項,表明想要引用的namespace:
spring.cloud.nacos.config.namespace=0a6be74a-426e-45eb-8531-6d7230f26af6
然后重啟應用,就能讀取到對應namespace下面的配置內容了。
2.3 加載多配置文件
默認情況下,本地應用會去nacos服務端讀取對應namespace下面的以應用名稱開頭的配置文件,在本例子中就是nacos-provider.properties
,因為我們本地應用配置的spring.application.name=nacos-provider
,在實際開發中,往往會有多個配置文件,那么如何同時加載多個配置文件中的配置內容呢?
首先,我們在public命名空間下再新建兩個配置文件:
# redis.properties
redis.server=127.0.0.1
# mq.properties
mq.nameserver=localhost
同時,我們需要在本地項目的bootstrap.properties
配置文件中增加如下的配置內容:
spring.cloud.nacos.config.ext-config[0].data-id=redis.properties
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.ext-config[0].data-id=mq.properties
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[0].refresh=true
對應的yml配置形式為:
spring:
cloud:
nacos:
config:
extension-configs:
- refresh: true
group: DEFAULT_GROUP
data-id: redis.properties
- refresh: true
group: DEFAULT_GROUP
data-id: mq.properties
然后,修改我們的controller,引用nacos服務器上的不同配置文件里面的配置項:
@RefreshScope
@RestController
public class ConfigController {
@Value("${provider.name}")
private String providerName;
@Value("${redis.server}")
private String redisServer;
@Value("${mq.nameserver}")
private String mqServer;
@GetMapping("/getDevConfig")
public String getDevConfig() {
return this.providerName + "/" + this.redisServer + "/" + this.mqServer;
}
}
重啟應用后,就能成功訪問不同配置文件里面的配置項了。
2.4 配置文件的分組區分
如上我們注意到,分組Group一直都是DEFAULT_GROUP,其實我們可以在不同的Group里面創建相同名稱的配置文件。比如在微服務環境中,多個微服務組件都有redis.properties的配置文件,那么如何區分哪個微服務該使用哪個Group下面的配置文件呢,其實也很簡單,只要在配置文件中指定Group即可。
本實例比較簡單,就不演示了,其實對于同一個應用也可以讀取不同Group下面的配置文件配置內容,我們完全也可以用Group來作為dev、stg和prd的區分。
總之,Nacos為我們提供了三個維度來做區分,即profile、namespace和Group,開發者可以靈活應用來做自己想要的區分。
2.5 共享配置
很多時候,多個微服務中有相同的配置內容,比如大家連結的是同一個redis服務,同一個mq服務,那么就需要在各自的配置文件中都寫上相同的配置內容,顯得比較繁瑣,我們完全可以將這些共同的配置內容抽取出來,形成另一個配置文件,然后大家共享它。
比如,我們在public命名空間下新建DEFAULT_GROUP的配置文件share.properties
:
provider.share=share123
然后本地配置文件中新增如下配置內容:
# 如果有多個共享配置文件,相互之間用逗號分隔即可
spring.cloud.nacos.config.shared_dataids: share.properties
spring.cloud.nacos.config.refreshable-dataids: share.properties
然后在Controller中增加共享配置的讀取內容,此處就省略了,重啟應用就可以生效了。
注意,如果共享配置不是DEFAULT_GROUP下面的,就不能使用如上的方式,而是采用2.3節中講述的方式。
2.6 配置內容的優先級
有些時候,我們在加載的配置文件中都配置了同一個配置項的值,而且相互之間都不相同,那么本地應用最終以哪個配置文件中的內容為準呢?
- A:使用
spring.cloud.nacos.config.prefix
、spring.cloud.nacos.config.file-extension
、spring.cloud.nacos.config.group
這幾個參數拼接出來的配置文件; - B:使用2.3節中extension-configs指定的配置間件;
- C:使用2.5節中共享配置指定的配置文件;
- D:本地配置的配置內容;
優先級順序為:D>A>B>C