Nacos配置中心
在項(xiàng)目中使用Nacos做配置中心還是比較簡(jiǎn)單的,我們先創(chuàng)建SpringBoot項(xiàng)目,然后引入nacos-config的jar包,具體如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
如果你不想使用SpringBoot默認(rèn)的nacos-config版本,也可以指定版本號(hào)。
首先,我們進(jìn)入到nacos的管理后臺(tái),第一步要?jiǎng)?chuàng)建命名空間,如圖:

我們創(chuàng)建了user的服務(wù)配置,以后user相關(guān)的微服務(wù)都在這個(gè)命名空間中拉取配置。我們點(diǎn)擊保存,命名空間的id會(huì)自動(dòng)生成,這個(gè)id是十分重要的,我們要在項(xiàng)目中配置這個(gè)id。命名空間創(chuàng)建好以后,我們?cè)賱?chuàng)建配置文件,

在配置列表中,我們先選中剛才新建的命名空間:user服務(wù)配置。然后再點(diǎn)擊新建,我的截圖中已經(jīng)把user-provider的配置文件創(chuàng)建好了。我們可以看一下如何新建,如圖:

其中Data ID我們叫做user-provider,group我們用來區(qū)分本地環(huán)境、測(cè)試環(huán)境、生產(chǎn)環(huán)境。配置格式我們選擇yaml,內(nèi)容我們先配置一個(gè)username看看能不能生效。
然后在resources目錄下創(chuàng)建bootstrap.yml,這個(gè)bootstrap.yml和application.yml是不一樣的,它優(yōu)先加載于application.yml,大家一定要注意他們的區(qū)別。我們要在bootstrap.yml文件中,要配置nacos的地址、命名空間、文件名等信息,具體如下:
spring:
cloud:
nacos:
server-addr: nacos-host:80
config:
file-extension: yml
name: user-provider
group: ${spring.profiles.active}
namespace: e5aebd28-1c15-4991-a36e-0865bb5af930
application:
name: user-provider
- spring.application.name,這個(gè)不用說了,就是你應(yīng)用的名稱,我們叫做user-provider,用戶服務(wù)的提供者。
- 再看上面的部分server-addr,這個(gè)是nacos的地址,我們配置為nacos-host:80。其中nacos-host需要配置host,指向nacos的ip,而端口80也是需要指定的,如果不指定端口,會(huì)默認(rèn)8848端口。
- 再看config的部分,file-extension,文件的擴(kuò)展名,這里我們使用yml,相應(yīng)的,在nacos配置中心中,配置格式選擇yaml。
- config.name對(duì)應(yīng)著nacos管理后臺(tái)的Data ID。
- group,在這里是分組,我們用作區(qū)分不同環(huán)境的標(biāo)識(shí),通過項(xiàng)目啟動(dòng)時(shí)傳入的參數(shù)${spring.profiles.active}獲得。
- namespace,命名空間,這里要填寫命名空間的id,這個(gè)id在nacos后臺(tái)中獲取。這里我們填寫的是user配置服務(wù)的命名空間id。
到這里,在項(xiàng)目中使用nacos做配置中心就搭建好了。我們?cè)陧?xiàng)目當(dāng)中寫個(gè)屬性類,測(cè)試一下,看看能不能取到值。
@RefreshScope
@Setter@Getter
@Configuration
public class DatabaseConfig {
@Value("${username}")
private String username;
@Value("${server.port}")
private String port;
}
- 我們寫了個(gè)DatabaseConfig類,先注意一下類上面的注解,@RefreshScope這個(gè)注解可以使我們?cè)趎acos管理后臺(tái)修改配置以后,項(xiàng)目不用重啟,就可以更改變量的值。
- @Setter@Getter這個(gè)是Lombok的注解,可以省去setget方法。
- @Configuration標(biāo)識(shí)這個(gè)類是一個(gè)配置類,項(xiàng)目啟動(dòng)時(shí)會(huì)實(shí)例化。
- 在類里邊,我們定義了兩個(gè)變量,username和port,兩個(gè)變量上面的注解@Value,可以取到對(duì)應(yīng)的,屬性的值。
{server.port}這個(gè)我們可以通過項(xiàng)目啟動(dòng)參數(shù)獲取到,一會(huì)帶著大家試一下。
我們?cè)趯憘€(gè)controller,把變量的值打印出來,如下:
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private DatabaseConfig databaseConfig;
@RequestMapping("config")
public String config() {
return databaseConfig.getUsername()+":"+databaseConfig.getPort();
}
}
我們將username和port兩個(gè)變量打印出來。好了,程序相關(guān)的部分就都寫好了,然后,我們添加項(xiàng)目啟動(dòng)參數(shù),如圖:

- spring.profiles.active=local,這個(gè)參數(shù)很重要,項(xiàng)目要用這個(gè)local值去nacos管理后臺(tái)找對(duì)應(yīng)的分組group是local的配置。
- server.port=8080,這個(gè)是項(xiàng)目的啟動(dòng)端口,同時(shí),我們也將這個(gè)值打印出來了。
好了,我們現(xiàn)在啟動(dòng)項(xiàng)目,并且在瀏覽器中訪問我們剛才寫的controller,瀏覽器返回的結(jié)果如下:
user:8080
- user,是我們?cè)趎acos中配置的值,8080是我們添加的啟動(dòng)參數(shù)。
返回結(jié)果沒有問題。然后我們?cè)偃acos管理后臺(tái)將user改成tom,項(xiàng)目不重啟,再看看返回的結(jié)果,如圖:

確認(rèn)發(fā)布以后,我們刷新一下瀏覽器,
tom:8080
我們并沒有重啟項(xiàng)目,但是返回的結(jié)果變成了tom。怎么樣?使用nacos做配置中心還是比較好用的吧~
Nacos注冊(cè)中心
通常情況下,我們一般會(huì)選擇Zookeeper、Eureka做注冊(cè)中心,其實(shí)Nacos也是可以做注冊(cè)中心的。既然我們項(xiàng)目使用了Nacos做配置中心,那么使用Nacos做注冊(cè)中心也是非常好的選擇。下面讓我們看看在項(xiàng)目中如何使用Nacos做注冊(cè)中心。
首先,還是在項(xiàng)目中引入Nacos注冊(cè)中心的jar包,如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
我們引入了nacos-discovery的jar包,如果您不想使用默認(rèn)的版本,可以指定需要引入的版本。
然后,我們就要配置Nacos注冊(cè)中心的地址了,通常情況下,我們是在application.yml文件中進(jìn)行配置。但是,這次我們使用了Nacos做配置中心,就可以在Nacos的管理后臺(tái)進(jìn)行配置了,如下:
username: tom
spring:
cloud:
nacos:
discovery:
server-addr: nacos-host:80
namespace: e5aebd28-1c15-4991-a36e-0865bb5af930
group: ${spring.profiles.active}
- 我們需要在nacos.discovery節(jié)點(diǎn)下進(jìn)行配置,server-addr,這個(gè)屬性和前面的配置是一樣的,nacos-host是配置了HOST,指向Nacos的ip,80端口也是需要指定的,默認(rèn)端口是8848。
- namespace,命名空間,我們復(fù)用前面的就可以了。
- group,同樣,我們用來區(qū)分不同的環(huán)境,它的值也是從啟動(dòng)參數(shù)中獲取。
最后,我們?cè)陧?xiàng)目的啟動(dòng)類中添加@EnableDiscoveryClient的注解,如下:
@SpringBootApplication
@EnableDiscoveryClient
public class UserProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserProviderApplication.class, args);
}
}
好了,到這里,服務(wù)提供者的配置以及代碼上的改動(dòng)都調(diào)整完畢了,我們啟動(dòng)一下項(xiàng)目,然后去Nacos管理后臺(tái)看看服務(wù)是否已經(jīng)注冊(cè)到Nacos當(dāng)中。

我們?cè)贜acos管理后臺(tái)選擇服務(wù)列表菜單,可以看到我們啟動(dòng)的項(xiàng)目已經(jīng)注冊(cè)到nacos中了。如果我們?cè)賳?dòng)一個(gè)服務(wù)提供者會(huì)是什么樣子呢?我們剛啟動(dòng)的項(xiàng)目指定的端口是8080,我們?cè)賳?dòng)一個(gè)項(xiàng)目,將端口指定為8081,看看服務(wù)列表是什么樣子。

我們看到實(shí)例數(shù)由原來的1變?yōu)榱?。說明我們的user-provider服務(wù)有了兩個(gè),我們?cè)冱c(diǎn)右邊的詳情看一下,

服務(wù)的詳情以及具體的實(shí)例都給我們列了出來,我們還可以編輯和下線具體的實(shí)例,這個(gè)我們后面再介紹。
好了,到這里,服務(wù)提供者的就搭建好了,我們分別訪問兩個(gè)服務(wù)提供者的具體連接得到的結(jié)果如下:
# http://localhost:8080/user/config
tom:8080
# http://localhost:8081/user/config
tom:8081
接下來,我們?cè)倏纯捶?wù)的消費(fèi)者如何搭建。我們新建一個(gè)SpringBoot項(xiàng)目user-consumer,這個(gè)項(xiàng)目我們同樣使用Nacos作為配置中心,而且要從Nacos這個(gè)注冊(cè)中心獲取服務(wù)列表,所以引入jar包如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
然后在bootstrap.yml中,填寫nacos配置中心的相關(guān)配置,這個(gè)和前面的配置的差不多的,只需要改一下相應(yīng)的文件名稱就可以了。
spring:
cloud:
nacos:
server-addr: nacos-host:80
config:
file-extension: yml
name: user-consumer
group: ${spring.profiles.active}
namespace: e5aebd28-1c15-4991-a36e-0865bb5af930
application:
name: user-consumer
- 注意config.name,我們改為了user-consumer。并且應(yīng)用的名稱改為了user-consumer。
然后,我們?cè)偃acos管理后臺(tái)添加user-consumer的配置,如圖:

- DataID就是我們配置的user-consumer,group我們同樣配置為local,標(biāo)識(shí)著本地。
- 具體的配置內(nèi)容是nacos服務(wù)的地址,如圖。這樣我們的服務(wù)消費(fèi)者項(xiàng)目user-consumer就可以從nacos配置中心獲取到注冊(cè)中心的地址和命名空間,并且可以從命名空間獲取服務(wù)的地址。
配置的部分就到這里了,然后再去啟動(dòng)類中,添加@EnableDiscoveryClient注解,如下:
@SpringBootApplication
@EnableDiscoveryClient
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class, args);
}
}
最后,我們寫個(gè)Controller,從Nacos獲取服務(wù)提供者的地址,并調(diào)用服務(wù)提供者,如下:
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@RequestMapping("consumer")
public String consumer() {
ServiceInstance provider = loadBalancerClient.choose("user-provider");
String url = "http://"+provider.getHost()+":"+provider.getPort()+"/user/config";
RestTemplate restTemp = new RestTemplate();
String result = restTemp.getForObject(url, String.class);
return result;
}
}
- 這個(gè)是SpringCloud Alibaba官網(wǎng)給出的調(diào)用示例,使用的是LoadBalancerClient,我們先將其注入。
- 在方法里邊,我們調(diào)用choose方法,選擇user-provider服務(wù),這個(gè)是我們服務(wù)提供者的名稱,在nacos管理后臺(tái)的服務(wù)列表中可以查看到的,這個(gè)方法會(huì)返回具體的服務(wù)實(shí)例,我們的服務(wù)實(shí)例有2個(gè),分別是8080端口和8081端口的兩個(gè)服務(wù),在這里,默認(rèn)是輪詢的負(fù)載均衡策略。
- 選擇了具體的服務(wù)實(shí)例,我們就來拼裝請(qǐng)求地址,從服務(wù)實(shí)例中獲取地址和端口。
- 最后使用RestTemplate完成調(diào)用。
最后,我們配置項(xiàng)目啟動(dòng),設(shè)置spring.profiles.active=local,并且指定端口為9090,如圖:

最后,我們啟動(dòng)項(xiàng)目,訪問http://localhost:9090/user/consumer,訪問結(jié)果如下:
tom:8080
很明顯,我們調(diào)用到了8080端口的服務(wù)提供者,我們?cè)偎⑿乱幌?,看看返回結(jié)果,
tom:8081
這次又調(diào)用到了8081端口的服務(wù)提供者,我們多次刷新,發(fā)現(xiàn)它會(huì)在8080和8081之間切換,這說明我們的負(fù)載均衡策略應(yīng)該是輪詢。
使用Feign完成服務(wù)的調(diào)用
上面的例子中,我們使用的是LoadBalancerClient完成服務(wù)的調(diào)用,接下來,我們分別看看Feign和Ribbon怎么調(diào)用服務(wù)。我們先來看看Feign,要使用Feign完成服務(wù)的調(diào)用,先要引入Feign的jar包,如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
然后再啟動(dòng)類上添加@EnableFeignClients的注解,如下:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class, args);
}
}
接下來,我們寫一個(gè)interface來完成feign的服務(wù)調(diào)用和熔斷,如下:
@FeignClient(name = "user-provider",fallback = UserServiceFallback.class)
public interface UserService {
@RequestMapping("/user/config")
String config();
}
- 我們寫了一個(gè)UserService的接口,在接口上添加@FeignClient的注解,注解里有兩個(gè)屬性,name指定服務(wù)的名稱,這里我們指定為user-provider,這是我們前面服務(wù)提供者的名稱,fallback指定發(fā)生熔斷時(shí),調(diào)用的類。當(dāng)我們的服務(wù)提供者不能正常提供服務(wù)時(shí),就會(huì)觸發(fā)熔斷機(jī)制,會(huì)調(diào)用熔斷服務(wù)類的邏輯,返回結(jié)果。
- 在接口中,我們寫了一個(gè)config()方法,方法上添加@RequestMapping的注解,并配置具體的路徑。這樣,我們?cè)谡{(diào)用服務(wù)的時(shí)候,通過Feign調(diào)用到具體的服務(wù)提供者了。
我們?cè)賮砜纯慈蹟鄬?shí)現(xiàn)類UserServiceFallback的具體內(nèi)容,如下:
@Service
public class UserServiceFallback implements UserService {
@Override
public String config() {
return "user-fallback";
}
}
- 首先,它是UserService接口,也就是Feign接口的實(shí)現(xiàn)類,然后實(shí)現(xiàn)接口中的方法,我們直接返回user-fallback字符串。
Feign的接口和熔斷的實(shí)現(xiàn)類都寫好了,但是這還不算完,要使熔斷生效,還要添加額外的配置,我們直接去nacos管理后臺(tái)去配置,進(jìn)入到user-consumer的配置中,添加如下配置:
feign:
hystrix:
enabled: true
- 這個(gè)就是feign的熔斷開關(guān),默認(rèn)是關(guān)閉的,現(xiàn)在打開。
最后,我們?cè)赾ontroller中,調(diào)用UserService接口,如下:
@Autowired
private UserService userService;
@RequestMapping("consumer-feign")
public String userService() {
String result = userService.config();
return result;
}
- 將UserService,注入進(jìn)來,然后直接調(diào)用方法即可。
我們?cè)L問一下http://localhost:9090/user/consumer-feign,看看返回的結(jié)果。如下:
tom:8080
tom:8081
返回的結(jié)果和前面是一樣的,我們不斷的刷新,它也會(huì)在8080和8081之間輪詢。
使用Ribbon完成服務(wù)的調(diào)用
同樣,我們也可以使用Ribbon完成服務(wù)的調(diào)用,Ribbon和RestTemplate在內(nèi)部是緊密結(jié)合的。我們只需要將RestTemplate實(shí)例化,并添加@LoadBalanced注解就可以了,如下:
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
然后在,controller中,我們使用這個(gè)實(shí)例化好的RestTemplate,就可以了,具體實(shí)現(xiàn)如下:
@Autowired
private RestTemplate restTemplate;
@RequestMapping("consumer-ribbon")
public String consumerribbon() {
String url = "http://user-provider/user/config";
String result = restTemplate.getForObject(url, String.class);
return result;
}
- 我們將restTemplate注入進(jìn)來。
- 在具體方法中,url的地址,我們直接寫服務(wù)名稱user-provider加路徑的方式,大家可以參照第一種調(diào)用方式,看看區(qū)別。
我們重啟項(xiàng)目,訪問http://localhost:9090/user/consumer-ribbon,結(jié)果如下:
tom:8080
tom:8081
返回的結(jié)果和前面是一樣的,我們不斷的刷新,它也會(huì)在8080和8081之間輪詢。
使用Nacos權(quán)重負(fù)載均衡
三種服務(wù)的調(diào)用方法都給大家介紹完了,但是,他們的負(fù)載均衡策略都是輪詢,這有點(diǎn)不符合我們的要求,我們進(jìn)入到Nacos的管理后臺(tái),調(diào)節(jié)一下服務(wù)的權(quán)重,如圖:

我們將8080接口的服務(wù)權(quán)重由1改為10,點(diǎn)擊確認(rèn),再多次刷新一下我們的訪問地址,發(fā)現(xiàn)服務(wù)的調(diào)用還是在8080和8081之間輪詢。這是什么情況?這里就不和大家賣關(guān)子了,這是因?yàn)長(zhǎng)oadBalancerClient、Feign和Ribbon3種方式,它們的底層都是使用Ribbon做負(fù)載均衡的,而Ribbon負(fù)載均衡默認(rèn)使用的策略是ZoneAvoidanceRule,我們要修改Ribbon的默認(rèn)策略,讓它使用nacos的權(quán)重,那么該如何配置呢?
我們進(jìn)入到nacos管理后臺(tái),修改user-consumer的配置,添加如下配置:
user-provider:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
- user-provider是我們服務(wù)的名稱,你配置哪個(gè)服務(wù)的負(fù)載均衡策略,就寫哪個(gè)服務(wù)的名字。
- 后面ribbon.NFLoadBalancerRuleClassName需要配置負(fù)載均衡策略的具體實(shí)現(xiàn),這個(gè)實(shí)現(xiàn)類要實(shí)現(xiàn)IRule接口,在這里,我們指定實(shí)現(xiàn)類為com.alibaba.cloud.nacos.ribbon.NacosRule。這是nacos的負(fù)載均衡規(guī)則,它是實(shí)現(xiàn)了IRule接口的。
我們重啟項(xiàng)目,調(diào)用我們之前的3個(gè)鏈接,調(diào)用哪個(gè)效果都是一樣的,我們發(fā)現(xiàn)返回tom:8080的次數(shù)明顯增多,說明Nacos服務(wù)的權(quán)重配置生效了。小伙伴們還可以將權(quán)重改成其他的值試一下。這里就不給大家演示了。
總結(jié)
Nacos的配置中心和服務(wù)注冊(cè)中心就給大家介紹完了,還是很好用的,這為我們搭建微服務(wù)提供了另外一種選擇。當(dāng)然消費(fèi)端的調(diào)用還是首推Feign+hystrix熔斷的,功能很強(qiáng)大,小伙伴們?cè)陧?xiàng)目中多實(shí)踐吧~
最后
感謝大家看到這里,如果本文有什么不足之處,歡迎多多指教;如果你覺得對(duì)你有幫助,請(qǐng)給我點(diǎn)個(gè)贊。
也歡迎大家關(guān)注我的公眾號(hào):程序員麥冬,每天更新行業(yè)資訊!