在上一篇中,我們已經把Nacos的叢集搭建好了,那麼既然已經搭建好了,就要在我們們的專案中去使用。Nacos既可以做配置中心,也可以做註冊中心。我們先來看看在專案中如何使用Nacos做配置中心。
Nacos配置中心
在專案中使用Nacos做配置中心還是比較簡單的,我們先建立SpringBoot專案,然後引入nacos-config的jar包,具體如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
如果你不想使用SpringBoot預設的nacos-config版本,也可以指定版本號。
首先,我們進入到nacos的管理後臺,第一步要建立名稱空間,如圖:
我們建立了user的服務配置,以後user相關的微服務都在這個名稱空間中拉取配置。我們點選儲存,名稱空間的id會自動生成,這個id是十分重要的,我們要在專案中配置這個id。名稱空間建立好以後,我們再建立配置檔案,
在配置列表中,我們先選中剛才新建的名稱空間:user服務配置。然後再點選新建,我的截圖中已經把user-provider的配置檔案建立好了。我們可以看一下如何新建,如圖:
其中Data ID我們叫做user-provider,group我們用來區分本地環境、測試環境、生產環境。配置格式我們選擇yaml,內容我們先配置一個username看看能不能生效。
然後在resources目錄下建立bootstrap.yml,這個bootstrap.yml和application.yml是不一樣的,它優先載入於application.yml,大家一定要注意他們的區別。我們要在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,這個不用說了,就是你應用的名稱,我們叫做user-provider,使用者服務的提供者。
- 再看上面的部分server-addr,這個是nacos的地址,我們配置為nacos-host:80。其中nacos-host需要配置host,指向nacos的ip,而埠80也是需要指定的,如果不指定埠,會預設8848埠。
- 再看config的部分,file-extension,檔案的副檔名,這裡我們使用yml,相應的,在nacos配置中心中,配置格式選擇yaml。
- config.name對應著nacos管理後臺的Data ID。
- group,在這裡是分組,我們用作區分不同環境的標識,通過專案啟動時傳入的引數${spring.profiles.active}獲得。
- namespace,名稱空間,這裡要填寫名稱空間的id,這個id在nacos後臺中獲取。這裡我們填寫的是user配置服務的名稱空間id。
到這裡,在專案中使用nacos做配置中心就搭建好了。我們在專案當中寫個屬性類,測試一下,看看能不能取到值。
@RefreshScope
@Setter@Getter
@Configuration
public class DatabaseConfig {
@Value("${username}")
private String username;
@Value("${server.port}")
private String port;
}
- 我們寫了個DatabaseConfig類,先注意一下類上面的註解,@RefreshScope這個註解可以使我們在nacos管理後臺修改配置以後,專案不用重啟,就可以更改變數的值。
- @Setter@Getter這個是Lombok的註解,可以省去setget方法。
- @Configuration標識這個類是一個配置類,專案啟動時會例項化。
- 在類裡邊,我們定義了兩個變數,username和port,兩個變數上面的註解@Value,可以取到對應的,屬性的值。${username}這個我們在nacos管理後臺已經設定了,${server.port}這個我們可以通過專案啟動引數獲取到,一會帶著大家試一下。
我們在寫個controller,把變數的值列印出來,如下:
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private DatabaseConfig databaseConfig;
@RequestMapping("config")
public String config() {
return databaseConfig.getUsername()+":"+databaseConfig.getPort();
}
}
我們將username和port兩個變數列印出來。好了,程式相關的部分就都寫好了,然後,我們新增專案啟動引數,如圖:
- spring.profiles.active=local,這個引數很重要,專案要用這個local值去nacos管理後臺找對應的分組group是local的配置。
- server.port=8080,這個是專案的啟動埠,同時,我們也將這個值列印出來了。
好了,我們現在啟動專案,並且在瀏覽器中訪問我們剛才寫的controller,瀏覽器返回的結果如下:
user:8080
- user,是我們在nacos中配置的值,8080是我們新增的啟動引數。
返回結果沒有問題。然後我們再去nacos管理後臺將user改成tom,專案不重啟,再看看返回的結果,如圖:
確認釋出以後,我們重新整理一下瀏覽器,
tom:8080
我們並沒有重啟專案,但是返回的結果變成了tom。怎麼樣?使用nacos做配置中心還是比較好用的吧~
Nacos註冊中心
通常情況下,我們一般會選擇Zookeeper、Eureka做註冊中心,其實Nacos也是可以做註冊中心的。既然我們專案使用了Nacos做配置中心,那麼使用Nacos做註冊中心也是非常好的選擇。下面讓我們看看在專案中如何使用Nacos做註冊中心。
首先,還是在專案中引入Nacos註冊中心的jar包,如下:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
我們引入了nacos-discovery的jar包,如果您不想使用預設的版本,可以指定需要引入的版本。
然後,我們就要配置Nacos註冊中心的地址了,通常情況下,我們是在application.yml檔案中進行配置。但是,這次我們使用了Nacos做配置中心,就可以在Nacos的管理後臺進行配置了,如下:
username: tom
spring:
cloud:
nacos:
discovery:
server-addr: nacos-host:80
namespace: e5aebd28-1c15-4991-a36e-0865bb5af930
group: ${spring.profiles.active}
- 我們需要在nacos.discovery節點下進行配置,server-addr,這個屬性和前面的配置是一樣的,nacos-host是配置了HOST,指向Nacos的ip,80埠也是需要指定的,預設埠是8848。
- namespace,名稱空間,我們複用前面的就可以了。
- group,同樣,我們用來區分不同的環境,它的值也是從啟動引數中獲取。
最後,我們在專案的啟動類中新增@EnableDiscoveryClient的註解,如下:
@SpringBootApplication
@EnableDiscoveryClient
public class UserProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserProviderApplication.class, args);
}
}
好了,到這裡,服務提供者的配置以及程式碼上的改動都調整完畢了,我們啟動一下專案,然後去Nacos管理後臺看看服務是否已經註冊到Nacos當中。
我們在Nacos管理後臺選擇服務列表選單,可以看到我們啟動的專案已經註冊到nacos中了。如果我們再啟動一個服務提供者會是什麼樣子呢?我們剛啟動的專案指定的埠是8080,我們再啟動一個專案,將埠指定為8081,看看服務列表是什麼樣子。
我們看到例項數由原來的1變為了2。說明我們的user-provider服務有了兩個,我們再點右邊的詳情看一下,
服務的詳情以及具體的例項都給我們列了出來,我們還可以編輯和下線具體的例項,這個我們後面再介紹。
好了,到這裡,服務提供者的就搭建好了,我們分別訪問兩個服務提供者的具體連線得到的結果如下:
# http://localhost:8080/user/config
tom:8080
# http://localhost:8081/user/config
tom:8081
接下來,我們再看看服務的消費者如何搭建。我們新建一個SpringBoot專案user-consumer,這個專案我們同樣使用Nacos作為配置中心,而且要從Nacos這個註冊中心獲取服務列表,所以引入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配置中心的相關配置,這個和前面的配置的差不多的,只需要改一下相應的檔名稱就可以了。
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。並且應用的名稱改為了user-consumer。
然後,我們再去Nacos管理後臺新增user-consumer的配置,如圖:
- DataID就是我們配置的user-consumer,group我們同樣配置為local,標識著本地。
- 具體的配置內容是nacos服務的地址,如圖。這樣我們的服務消費者專案user-consumer就可以從nacos配置中心獲取到註冊中心的地址和名稱空間,並且可以從名稱空間獲取服務的地址。
配置的部分就到這裡了,然後再去啟動類中,新增@EnableDiscoveryClient註解,如下:
@SpringBootApplication
@EnableDiscoveryClient
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class, args);
}
}
最後,我們寫個Controller,從Nacos獲取服務提供者的地址,並呼叫服務提供者,如下:
@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;
}
}
- 這個是SpringCloud Alibaba官網給出的呼叫示例,使用的是LoadBalancerClient,我們先將其注入。
- 在方法裡邊,我們呼叫choose方法,選擇user-provider服務,這個是我們服務提供者的名稱,在nacos管理後臺的服務列表中可以檢視到的,這個方法會返回具體的服務例項,我們的服務例項有2個,分別是8080埠和8081埠的兩個服務,在這裡,預設是輪詢的負載均衡策略。
- 選擇了具體的服務例項,我們就來拼裝請求地址,從服務例項中獲取地址和埠。
- 最後使用RestTemplate完成呼叫。
最後,我們配置專案啟動,設定spring.profiles.active=local,並且指定埠為9090,如圖:
最後,我們啟動專案,訪問http://localhost:9090/user/consumer,訪問結果如下:
tom:8080
很明顯,我們呼叫到了8080埠的服務提供者,我們再重新整理一下,看看返回結果,
tom:8081
這次又呼叫到了8081埠的服務提供者,我們多次重新整理,發現它會在8080和8081之間切換,這說明我們的負載均衡策略應該是輪詢。
使用Feign完成服務的呼叫
上面的例子中,我們使用的是LoadBalancerClient完成服務的呼叫,接下來,我們分別看看Feign和Ribbon怎麼呼叫服務。我們先來看看Feign,要使用Feign完成服務的呼叫,先要引入Feign的jar包,如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
然後再啟動類上新增@EnableFeignClients的註解,如下:
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class, args);
}
}
接下來,我們寫一個interface來完成feign的服務呼叫和熔斷,如下:
@FeignClient(name = "user-provider",fallback = UserServiceFallback.class)
public interface UserService {
@RequestMapping("/user/config")
String config();
}
- 我們寫了一個UserService的介面,在介面上新增@FeignClient的註解,註解裡有兩個屬性,name指定服務的名稱,這裡我們指定為user-provider,這是我們前面服務提供者的名稱,fallback指定發生熔斷時,呼叫的類。當我們的服務提供者不能正常提供服務時,就會觸發熔斷機制,會呼叫熔斷服務類的邏輯,返回結果。
- 在介面中,我們寫了一個config()方法,方法上新增@RequestMapping的註解,並配置具體的路徑。這樣,我們在呼叫服務的時候,通過Feign呼叫到具體的服務提供者了。
我們再來看看熔斷實現類UserServiceFallback的具體內容,如下:
@Service
public class UserServiceFallback implements UserService {
@Override
public String config() {
return "user-fallback";
}
}
- 首先,它是UserService介面,也就是Feign介面的實現類,然後實現介面中的方法,我們直接返回user-fallback字串。
Feign的介面和熔斷的實現類都寫好了,但是這還不算完,要使熔斷生效,還要新增額外的配置,我們直接去nacos管理後臺去配置,進入到user-consumer的配置中,新增如下配置:
feign:
hystrix:
enabled: true
- 這個就是feign的熔斷開關,預設是關閉的,現在開啟。
最後,我們在controller中,呼叫UserService介面,如下:
@Autowired
private UserService userService;
@RequestMapping("consumer-feign")
public String userService() {
String result = userService.config();
return result;
}
- 將UserService,注入進來,然後直接呼叫方法即可。
我們訪問一下http://localhost:9090/user/consumer-feign,看看返回的結果。如下:
tom:8080
tom:8081
返回的結果和前面是一樣的,我們不斷的重新整理,它也會在8080和8081之間輪詢。
使用Ribbon完成服務的呼叫
同樣,我們也可以使用Ribbon完成服務的呼叫,Ribbon和RestTemplate在內部是緊密結合的。我們只需要將RestTemplate例項化,並新增@LoadBalanced註解就可以了,如下:
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
然後在,controller中,我們使用這個例項化好的RestTemplate,就可以了,具體實現如下:
@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注入進來。
- 在具體方法中,url的地址,我們直接寫服務名稱user-provider加路徑的方式,大家可以參照第一種呼叫方式,看看區別。
我們重啟專案,訪問http://localhost:9090/user/consumer-ribbon,結果如下:
tom:8080
tom:8081
返回的結果和前面是一樣的,我們不斷的重新整理,它也會在8080和8081之間輪詢。
使用Nacos權重負載均衡
三種服務的呼叫方法都給大家介紹完了,但是,他們的負載均衡策略都是輪詢,這有點不符合我們的要求,我們進入到Nacos的管理後臺,調節一下服務的權重,如圖:
我們將8080介面的服務權重由1改為10,點選確認,再多次重新整理一下我們的訪問地址,發現服務的呼叫還是在8080和8081之間輪詢。這是什麼情況?這裡就不和大家賣關子了,這是因為LoadBalancerClient、Feign和Ribbon3種方式,它們的底層都是使用Ribbon做負載均衡的,而Ribbon負載均衡預設使用的策略是ZoneAvoidanceRule,我們要修改Ribbon的預設策略,讓它使用nacos的權重,那麼該如何配置呢?
我們進入到nacos管理後臺,修改user-consumer的配置,新增如下配置:
user-provider:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
- user-provider是我們服務的名稱,你配置哪個服務的負載均衡策略,就寫哪個服務的名字。
- 後面ribbon.NFLoadBalancerRuleClassName需要配置負載均衡策略的具體實現,這個實現類要實現IRule介面,在這裡,我們指定實現類為com.alibaba.cloud.nacos.ribbon.NacosRule。這是nacos的負載均衡規則,它是實現了IRule介面的。
我們重啟專案,呼叫我們之前的3個連結,呼叫哪個效果都是一樣的,我們發現返回tom:8080的次數明顯增多,說明Nacos服務的權重配置生效了。小夥伴們還可以將權重改成其他的值試一下。這裡就不給大家演示了。
總結
Nacos的配置中心和服務註冊中心就給大家介紹完了,還是很好用的,這為我們搭建微服務提供了另外一種選擇。當然消費端的呼叫還是首推Feign+hystrix熔斷的,功能很強大,小夥伴們在專案中多實踐吧~