天天看點

Nacos配置中心和服務的注冊發現

在上一篇中,我們已經把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的管理背景,第一步要建立命名空間,如圖:

Nacos配置中心和服務的注冊發現

我們建立了user的服務配置,以後user相關的微服務都在這個命名空間中拉取配置。我們點選儲存,命名空間的id會自動生成,這個id是十分重要的,我們要在項目中配置這個id。命名空間建立好以後,我們再建立配置檔案,

Nacos配置中心和服務的注冊發現

在配置清單中,我們先選中剛才建立的命名空間:user服務配置。然後再點選建立,我的截圖中已經把user-provider的配置檔案建立好了。我們可以看一下如何建立,如圖:

Nacos配置中心和服務的注冊發現

其中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兩個變量列印出來。好了,程式相關的部分就都寫好了,然後,我們添加項目啟動參數,如圖:

Nacos配置中心和服務的注冊發現
  • spring.profiles.active=local,這個參數很重要,項目要用這個local值去nacos管理背景找對應的分組group是local的配置。
  • server.port=8080,這個是項目的啟動端口,同時,我們也将這個值列印出來了。

好了,我們現在啟動項目,并且在浏覽器中通路我們剛才寫的controller,浏覽器傳回的結果如下:

user:8080           
  • user,是我們在nacos中配置的值,8080是我們添加的啟動參數。

傳回結果沒有問題。然後我們再去nacos管理背景将user改成tom,項目不重新開機,再看看傳回的結果,如圖:

Nacos配置中心和服務的注冊發現

确認釋出以後,我們重新整理一下浏覽器,

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管理背景選擇服務清單菜單,可以看到我們啟動的項目已經注冊到nacos中了。如果我們再啟動一個服務提供者會是什麼樣子呢?我們剛啟動的項目指定的端口是8080,我們再啟動一個項目,将端口指定為8081,看看服務清單是什麼樣子。

Nacos配置中心和服務的注冊發現

我們看到執行個體數由原來的1變為了2。說明我們的user-provider服務有了兩個,我們再點右邊的詳情看一下,

Nacos配置中心和服務的注冊發現

服務的詳情以及具體的執行個體都給我們列了出來,我們還可以編輯和下線具體的執行個體,這個我們後面再介紹。

好了,到這裡,服務提供者的就搭建好了,我們分别通路兩個服務提供者的具體連接配接得到的結果如下:

# 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的配置,如圖:

Nacos配置中心和服務的注冊發現
  • 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,如圖:

Nacos配置中心和服務的注冊發現

最後,我們啟動項目,通路

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           

使用Nacos權重負載均衡

三種服務的調用方法都給大家介紹完了,但是,他們的負載均衡政策都是輪詢,這有點不符合我們的要求,我們進入到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熔斷的,功能很強大,小夥伴們在項目中多實踐吧~