Nacos高可用集群搭建與使用


一、Nacos 簡介

Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平台。 Nacos 是構建以“服務”為中心的現代應用架構 (例如微服務范式、雲原生范式) 的服務基礎設施。

nacos官網:https://nacos.io/zh-cn/docs/what-is-nacos.html

二、Nacos 安裝

2.1     Nacos 環境依賴

Nacos 基於 java 開發的,運行依賴於64 bit JDK 1.8+環境。

前往官網下載JDK: https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

2.2     Nacos 服務端安裝

由於Nacos是開源的,可以從github下載源碼編譯后安裝,也可以直接從github下載官方編譯好的安裝包進行安裝,本文直接使用官方編譯好的包進行安裝,基於目前官方最新release2.0.3版本。請勿使用2.x以下的版本,之前爆出過漏洞。2.x版本相對於1.x版本,性能也提升了10倍。

下載地址:https://github.com/alibaba/nacos/releases

 

三、Nacos 部署

3.1     單實例部署

單實例部署不適合生產環境,單點故障是致命的。

Linux 單實例非集群模式啟動命令:

startup.sh -m standalone

Linux 單實例非集群模式關閉命令:

shutdown.sh

訪問 nacos 管理頁面,初始化用戶名密碼均為 nacos

訪問地址:http://127.0.0.1:8848/nacos/index.html

端口默認為8848,ip需要替換為部署服務器實例的ip

3.2     集群部署

3.2.1   集群架構

 

  • 高可用 Nginx 集群
  • Nacos 集群(至少三個實例)
  • 高可用數據庫集群(取代 Nacos 內嵌數據庫)

 

3.2.2   模擬部署

環境信息:

系統版本

機器IP

部署應用

應用版本

CentOS8.5

192.168.230.1

Nginx

nginx-1.18.0

CentOS8.5

192.168.230.129

Nacos

2.0.3

CentOS8.5

192.168.230.130

Nacos

2.0.3

CentOS8.5

192.168.230.131

Nacos

2.0.3

CentOS8.5

192.168.230.1

MySQL

5.7.32

使用vmware虛擬機模擬以上不同機器環境。

 

搭建步驟:

1)初始化 nacos數據庫

解壓下載的安裝包nacos-server-2.0.3.tar.gz至/usr/local目錄,找到/nacos/conf下的nacos-mysql.sql腳本

 

 在MySQL實例創建 nacos庫並執行sql腳本

 

 修改修改 Nacos 配置文件,指向MySQL實例,替換其內嵌數據庫

 

在application.properties中找到如下配置,該配置默認為注釋掉的,取消注釋即可,修改數據庫信息為實際的數據庫信息后保存。其他nacos服務實例也需要做同樣的修改

 

為了達到高可用,通常會有多個MySQL數據庫實例,nacos的配置文件也需要指定每一個MySQL實例的信息,例如:

 

2)集群配置

在/nacos/conf下找到cluster.conf.example文件,將其重命名為cluster.conf

 修改cluster.conf文件,將其中的默認的ip信息刪除,將nacos集群中每一台nacos實例的ip添加進去。集群中所有nacos實例都需要做以上集群配置,至此關於 nacos 的配置結束了,可以嘗試以集群模式啟動三個nacos實例了。

 切換到/nacos/bin目錄下,執行./startup.sh & tail -f /usr/local/nacos/logs/start.out

啟動nacos,並查看啟動日志,出現下面提示說明啟動成功

此時可以通過瀏覽器訪問每個nacos實例的控制台,例如:http://192.168.230.131:8848/nacos

說明:如果三個實例以集群模式正常啟動,那么分別訪問三個實例的管理頁就是展示以上登錄頁了。如果不能訪問,則可能防火牆未開放 nacos 服務的端口,可執行如下命令。

[root@localhost bin]# firewall-cmd --add-port=8848/tcp --permanent

success

[root@localhost bin]# firewall-cmd --reload

success

如果nacos啟動時報已下異常,有以下三種原因:

原因一:連不上MySQL數據庫,通常是由於MySQL數據庫所在的宿主機沒有開放3306端口導致的,在MySQL宿主機執行以下命令即可

[root@localhost bin]# firewall-cmd --add-port=3306/tcp --permanent
success
[root@localhost bin]# firewall-cmd --reload
Success

原因二:由於nacos配置文件application.properties中默認的數據庫連接超時時間設置較短,如下圖,因為網絡延時等原因,MySQL可能會連接超時導致nacos啟動報錯,因此只需要將超時時間適當設置長一些即可

原因三:虛擬機內存不足,由於在vmvare創建虛擬機時,只給每個虛擬分配了1G的內存,從nacos的啟動腳本startup.sh中可知,nacos以集群模式啟動時,默認分配的java堆內存空間為2G,因此可判斷是由於虛擬機內存不足導致nacos啟動報錯,修改虛擬機內存為2G后可以正常啟動。

3)Nginx 配置

修改 Nginx 配置文件 nginx.conf如下:

http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  65;

    #nacos集群負載均衡
    upstream nacos-cluster {
        server 192.168.230.129:8848;
        server 192.168.230.130:8848;
        server 192.168.230.131:8848;
    }

    server {
        listen       80;
        server_name  192.168.230.1;
        location / {
            #root   html;
            #index  index.html index.htm;
            proxy_pass http://nacos-cluster;
        }

        error_page   500 502 503 504  /50x.html;

        location = /50x.html {
            root   html;
        }
    }
}

 

4)訪問控制台

在瀏覽器輸入Nginx服務所在宿主機的ip即可訪問:

http://192.168.230.1/nacos/#/login

默認用戶名/密碼:nacos/nacos

切換至【集群管理】-【節點列表】,可查看nacos集群節點信息:

四、微服務集成Nacos

4.1     依賴組件版本選型

由於Spring Cloud Alibaba與Spring Boot 及Spring Cloud版本的兼容性要求非常嚴格,如果依賴選錯版本,很可能會導致服務啟動報錯從而導致啟動失敗。不過alibaba官方已經給我們整理出了推薦的版本依賴關系:

由於我們使用的nacos是最新的2.0.3版本,從以上表格可以查詢到依賴的Spring Cloud Alibaba的版本為2.2.7.RELEASE。繼續根據Spring Cloud Alibaba的版本查詢畢業版本依賴關系表,如下圖,可以找到依賴的Spring Cloud版本為Hoxton.SR12,依賴的Spring Boot版本為2.3.12.RELEASE

因此,通過上述查詢,最終確定微服務依賴版本選型如下:

Spring Cloud Version

Spring Cloud Alibaba Version

Spring Boot Version

Nacos Version

Hoxton.SR12

2.2.7.RELEASE

2.3.12.RELEASE

2.0.3

 

官方版本說明:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

4.2     注冊中心

首先新建demo-project-parent父工程,根據4.1 依賴組件版本選型選型確定的版本,在父pom文件統一定義好依賴的組件以及版本,如下:

<properties>
  <java.version>1.8</java.version>
  <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
  <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
  <spring-cloud-alibaba.version>2.2.7.RELEASE</spring-cloud-alibaba.version>
</properties>

<dependencyManagement>
  <dependencies>
    <!-- spring boot 依賴 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>${spring-boot.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    
    <!-- spring cloud 依賴 -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>${spring-cloud.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>

    <!-- spring cloud alibaba 依賴 -->
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>${spring-cloud-alibaba.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

4.2.1   服務提供者

在父工程下新建服務提供者子模塊micro-service-provider,並在pom文件引入依賴:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

修改provider配置文件application.yml:

server:
  port: 8081

spring:
  application:
    name: service-provider
  cloud:
    nacos:
      discovery:
	#nacos集群配置(Nginx)
        server-addr: 192.168.230.1:80

provider啟動類:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }

}

Provider測試Controller類:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProviderController {

    @Value("${server.port}")
    String port;

    @GetMapping("/hi")
    public String hi(@RequestParam(value = "name", defaultValue = "zmx",required = false) String name) {
        return "hello " + name + ", i'm provider, my port:" + port;
    }

}

4.2.2   服務消費者

在父工程下新建服務消費者子模塊micro-service-consumer,並在pom文件引入以下依賴:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<!-- 需要注意的是引入openfeign,必須要引入loadbalancer,否則無法啟動。-->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

修改consumer配置文件:

server:
  port: 8082

spring:
  application:
    name: service-consumer
  cloud:
    nacos:
      discovery:
        #nacos集群配置(Nginx)
        server-addr: 192.168.230.1:80

在工程的啟動類加上@EnableFeignClient注解,以開啟FeignClient的功能:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

}

寫一個feign客戶端FeignClient,去調用provider服務的接口:

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

//此處的value值對應於provider服務application配置文件中的spring.application.name
@FeignClient(value = "service-provider" )
public interface ProviderClient {

    @GetMapping("/hi")
    String hi(@RequestParam(value = "name", defaultValue = "zmx", required = false) String name);

}

寫一個測試接口,讓consumer去調用provider服務的接口:

import net.myibc.client.ProviderClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConsumerController {

    @Autowired
    ProviderClient providerClient;

    @GetMapping("/hi-feign")
    public String hiFeign(){
        return providerClient.hi("feign");
    }
}

啟動provider和consumer兩個工程,在nacos的【服務管理】-【服務列表】頁面查看,可見2個服務都已經注冊成功:

注意:這里啟動所有服務后,可能在控制台只能查看到某一個服務,或者查不到注冊的服務,查看nacos.log日志,發現報如下異常:

出現該異常的原因:當nacos客戶端升級為2.x版本后,新增了gRPC的通信方式,新增了兩個端口。這兩個端口在nacos原先的端口上(默認8848),進行一定偏移量自動生成。

端口與主端口的偏移量描述:

9848:客戶端gRPC請求服務端端口,用於客戶端向服務端發起連接和請求

9849:服務端gRPC請求服務端端口,用於服務間同步等

7848:Nacos 集群通信端口,用於Nacos 集群間進行選舉,檢測等

因此,不難猜出,出現該問題的原因是由於nacos2.x版本新增的這兩個端口沒有在宿主機開啟防火牆白名單,導致nacos實例之間無法進行服務間數據同步,因而在控制台無法查看到所有的服務注冊實例信息。只需要在nacos宿主機執行以下命令即可:

[root@localhost bin]# firewall-cmd --add-port=9848/tcp --permanent
success
[root@localhost bin]# firewall-cmd --add-port=9849/tcp --permanent
success
[root@localhost bin]# firewall-cmd --add-port=7848/tcp --permanent
success
[root@localhost bin]# firewall-cmd --reload
Success

注意:如果是采用VIP/nginx代理集群的話,需要在nginx配置9848和9849這兩個端口的TCP請求轉發,否則客戶端服務在啟動時因為無法連接到服務端這兩個端口,從而導致啟動失敗。如果不使用任何代理,在宿主機執行以上開啟端口白名單命令后,只需要在客戶端服務application配置文件里配置naocs集群的節點的ip和端口即可,配置如下:

Nginx配置nacos TCP轉發配置:

#配置nacos TCP轉發
stream {
    upstream nacos1 {
        server 192.168.230.129:9848;
        server 192.168.230.130:9848;
        server 192.168.230.131:9848;
    }

    server {
        listen 9848;
        proxy_pass nacos1;
    }

    upstream nacos2 {
        server 192.168.230.129:9849;
        server 192.168.230.130:9849;
        server 192.168.230.131:9849;
    }

    server {
        listen 9849;
        proxy_pass nacos2;
    }
}

4.2.3   服務調用

在瀏覽器上輸入http://127.0.0.1:8082/hi-feign,瀏覽器返回響應:

hello feign, i'm provider ,my port:8081

可見瀏覽器的請求成功調用了consumer服務的接口,consumer服務也成功地通過feign成功的調用了provider服務的接口。

4.2.4   負載均衡

Feign使用了Spring Cloud Loadbanlancer作為負載均衡器。可以通過修改provider的端口,再在本地啟動一個新的provider服務,那么本地有2個provider 服務,端口分別為8081 和8083。在瀏覽器上多次調用http://127.0.0.1:8082/hi-feign,瀏覽器會交替顯示:

hello feign, i'm provider ,my port:8081
hello feign, i'm provider ,my port:8083

此時控制台provider的實例數會變為2:

4.3     配置中心

4.3.1   配置中心客戶端

在父工程下新建nacos配置客戶端子模塊nacos-config-client,並在pom文件引入以下依賴:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

在bootstrap.yml(一定是bootstrap.yml文件,不是application.yml文件)文件配置以下內容:

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      config:
        server-addr: 192.168.230.1:80
        file-extension: yaml
        prefix: nacos-config-client
  profiles:
    active: dev

在上面的配置中,配置了nacos config server的地址,配置的擴展名是ymal(目前僅支持ymal和properties)。注意是沒有配置server.port的,sever.port的屬性在nacos中配置。上面的配置是和Nacos中的dataId 的格式是對應的,nacos的完整格式如下:

${prefix}-${spring.profile.active}.${file-extension}

  • prefix 默認為 spring.application.name 的值,也可以通過配置項 spring.cloud.nacos.config.prefix來配置。
  • spring.profile.active 即為當前環境對應的 profile,詳情可以參考 Spring Boot文檔。 注意:當 spring.profile.active 為空時,對應的連接符 - 也將不存在,dataId 的拼接格式變成 ${prefix}.${file-extension}
  • file-exetension 為配置內容的數據格式,可以通過配置項 spring.cloud.nacos.config.file-extension 來配置。目前只支持 properties 和 yaml 類型。

啟動nacos,登陸控制台http://192.168.230.1/nacos,創建一個Data ID ,完整的配置如圖所示:

 

寫一個RestController,在Controller上添加@RefreshScope注解實現配置的熱加載。該注解只有加載需要動態更新配置的類上才會生效,如果將該注解加在啟動類上,其他類中的動態更新是不會生效的,代碼如下:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope
public class ConfigController {

    @Value("${username:lily}")
    private String username;

    @RequestMapping("/username")
    public String get() {
        return username;
    }
}

啟動工程nacos-provider,在瀏覽器上訪問http://127.0.0.1:8084/username,可以返回在nacos控制台上配置的username的值zhangsan3。在nacos 控制台上更改username的配置為lisi,在不重啟nacos-provider工程的情況下,重新訪問http://127.0.0.1:8084/username,返回的是修改后的值lisi,可見nacos作為配置中心實現了熱加載功能。

修改nacos中username配置前返回:

將nacos中username的值修改為lisi后重新請求返回:

注意:使用某些高版本的SpringCloud組件時,在啟動nacos配置客戶端服務的時候,可能會找不到bootstrap.yml配置文件,會報如下錯誤,只需要在系統環境變量中配置一下環境變量即可:spring.cloud.bootstrap.enabled=true

4.3.2   開啟權限認證

通常情況下,為了安全起見,客戶端服務在訪問nacos的時候都需要通過用戶名和密碼認證,nacos默認是沒有開啟認證的,如果需要開啟認證,首先需要編輯/nacos/conf/application.properties配置文件,找到nacos.core.auth.enabled=false配置項,如下圖,默認是false,表示權限認證是關閉的,修改為true即可開啟認證。修改完成后需要重啟所有nacos實例。

在application配置文件中配置nacos的用戶名和密碼,如下圖,首先將服務用戶名和密碼配置為一個不存在的用戶,啟動服務驗證權限配置是否生效:

啟動服務,發現報了以下異常,code=403和unknown user,說明權限驗證失敗:

將用戶名和密碼修改為正確的之后,再次啟動服務,可發現服務啟動正常:

至此,說明nacos的權限認證配置已生效。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM