Spring Cloud Alibaba Nacos(功能篇)

愈來愈多的讀者在和我交流關於Spring Cloud Alibaba的種種事宜,甚至於在一次面試中,一半時間都在聊這個話題。因此,本着對技術鑽研的熱情,對Spring Cloud Alibaba進行了一番研究。html

在這裏,並不想高談闊論,也不想預言將來,只是挑選了幾個從阿里巴巴中間件團隊內脫胎出來的開源組件,對於解決實際業務問題有所裨益。java

1、背景

先來講說大背景。mysql

如今,很明顯的一個趨勢就是:微服務git

這個趨勢的底層驅動力就來源於分佈式系統的普及,而微服務的各個特性是現在大大小小的企業沒法拒絕的誘惑。github

而後,用上了微服務的架構風格,用Spring Cloud,或者Dubbo搭了一套腳手架,就開始幹起來了。面試

接下來,一衆小公司畫完了大餅以後,發現本身根本吃不下。這就是典型的落後勞動力與先進生產力的尖銳矛盾。這個時候,返璞歸真的想法是不能有了,重構代價太大。spring

固然,哪裏有問題,哪裏就有商機。各大XX雲廠商通過一系列包裝以後,用「雲原生(Cloud Native)」的新概念粉墨登場。sql

Spring Cloud Alibaba就是其中之一。shell

這個概念的一個核心價值就是:平滑上雲,賦能運維。最明顯的業務表象就是,會提供一套Open API,甚至是貼心的提供一個可視化控制檯,傻瓜式的那種。數據庫

2、從NACOS提及

這是一顆耀眼的掌上明珠,迅速引發了個人注意。

按照套路,分爲兩講。其一講述NACOS的功能特性,及其使用,再者就是更深刻一步,看看大廠的攻城獅們寫的代碼。

本文所使用的版本是NACOS 1.0.0,因爲此版本仍是第一個NACOS正式版,NACOS正處在飛速發展階段,本文的一些內容可能會不適用於之後的版本,請讀者自行辨別。

NACOS解決兩個核心問題:動態配置管理,服務註冊發現。

兼容性方面,除了支持自家的Dubbo,還對Spring Cloud,Kubernetes,Istio有所兼容。

野心勃勃的生態圈
對照以上的全景圖,如今的NACOS還有一段距離,可是並不遙遠。

至此,不說道說道Eureka,都有點過意不去了。

我用下來的體驗是:NACOS徹底能夠替代Eureka了。

江山代有才人出,這是必然的結果。

在「雲原生」的大背景之下,NACOS順利成章的推出了Console,將觸角進一步延伸至服務的精細化管理。

固然,不排除Eureka也在憋大招。

再說說動態配置的特性。

固然,NACOS略勝一籌,可替代Spring Cloud Config了。

原先在Git/SVN上託管的配置項,均可以在Console上統一管理了。

若是想先睹爲快,能夠接下着往下讀。若是想再多瞭解一些,能夠直接跳過這部分,閱讀下一個小節。

能夠把NACOS理解成是一箇中心化的服務,這在阿里系的架構中家常便飯。因此,必須得先啓動這個服務。

有兩個辦法:其一是直接clone源碼,使用maven打包。第二個辦法是直接下載GitHub release出來的壓縮包。

推薦後者。

方法1:主要運行如下命令:

git clone https://github.com/alibaba/nacos.git 
cd nacos/ 
mvn -Prelease-nacos clean install -U
複製代碼

通過一段時間的構建過程,在./distribution/target目錄下有咱們想要的壓縮包。

方法2:進入github.com/alibaba/nac…,找到壓縮包,下載。

爲了演示,咱們先用單機模式啓動。

Windows環境下:

startup.cmd -m standalone
複製代碼

一切就緒的話,訪問http://127.0.0.1:8848/nacos/index.html,使用nacos/nacos登陸。

接下來,隨便逛逛。

Console預覽

3、重要的概念

爲了不在Console中迷失自我,有必要先闡述幾個重要的概念。

數據模型
這張圖很重要。表述了namespace、group和service/dataId的包含關係。

NACOS給的最佳實踐代表,最外層的namespace是能夠用於區分部署環境的,好比test,uat,product等。同時,也有一個商業利用價值:多租戶。以namespace爲單位,給用戶開闢使用空間。

其它兩個領域模型不用多解釋了,見名知意。其目的也很是明顯,就是爲了可以邏輯上區分兩個目標對象。

默認狀況下,namespace=public,group=DEFAULT_GROUP。

明白了這個數據模型後,能夠稍微玩轉一下Console了,好比新建若干個namespace:

namespace列表
namespace順利建立成功後,會在每一個一級頁面看到由namespace組成的TAB,能夠任意切換namespace,對其下的數據進行操做。好比下圖的配置列表:
配置列表
固然,還有衆多的領域模型,可是跟這一講的關係不大了,下一講深刻源碼的時候再進行剖析。接下來會建立一個Demo工程,用於構建基於NACOS的config server和discovery server。

在進行下一章節以前,強烈建議先建立一個Spring Boot樣板工程,能夠不作任何配置,不添加任何一段代碼。

固然,爲了讓這一講的內容更具實戰意義,我不會照搬官網的Demo,本文所做的Demo工程也能夠從GitHub上克隆獲得。請提早準備好,接下來的內容只會挑重點講解,側重點不會在如何搭建工程。

4、使用NACOS的搭建工程

工程名稱爲:nacos-example,在各個pom.xml文件中相關依賴管理就再也不贅述了。

如今來介紹一下,這個demo工程幹了一件什麼事:用戶在下單的時候,須要校驗用戶的狀態,商品是否上架以及購買的數量上限。

爲了體現動態配置,用戶狀態和購買的數量上限作成配置項。而這二者的配置在不一樣的namespace下是有所不一樣的。

爲了體現服務間的調用,下單入口在order模塊,經由user模塊進行校驗。

工程結構
根據上述,NACOS服務啓動好了後,咱們分別建立dev,product兩個namespace,在寫spring boot配置的時候,填寫的不是test,product這些namespace名稱,而是ID,此ID會在namespace成功建立後,由系統自動分配,目前的生成規則就是隨機的UUID函數。

這樣的配置規則會存在很大的爭議,本文不作討論。

user模塊須要動態配置,因此能夠看做是一個config client。又由於須要接受order模塊的調用,因此也是一個service provider。

一樣的,order模塊須要動態配置,因此也是一個config client。

至此,讀者會發現一些NACOS帶來的「弊病」,最顯現的問題就是「多重角色」帶來的侵入性。由於是中心化的架構,若是沒有作到很好的解耦,出現這個問題也不足爲奇了。

特別是在遠程調用的角色分配上,NACOS嚴格聽從了「生產者-消費者」模型,在實際業務場景下,不免會有服務既是生產者,又是消費者,而Eureka是沒有這種區分的。

接下來把目光轉向配置。

阿里系的開源產品大多建議是用properties文件,因爲我的習慣,我使用的是yml,達到的效果是同樣的。

值得注意的是,由於須要更高優先級的加載順序,因此配置文件必須使用bootstrap.yml。

user模塊的配置文件,區分了環境,爲了增長辨識度,也定義了group進行隔離。以下:

server:
 port: 8100
spring:
 application:
 name: user
 cloud:
 nacos:
 config:
 server-addr: 127.0.0.1:8848
 file-extension: yaml
 namespace: 7d3e5f19-a102-471a-b6e0-67bd7d1d35f3
 group: USER_GROUP
 discovery:
 server-addr: 127.0.0.1:8848
 namespace: 7d3e5f19-a102-471a-b6e0-67bd7d1d35f3
---
spring:
 profiles: prod
 cloud:
 nacos:
 config:
 server-addr: 11.162.196.16:8848
 namespace: c4c81555-91e1-4ef5-8b57-77c5407b3481
 discovery:
 server-addr: 11.162.196.16:8848
 namespace: c4c81555-91e1-4ef5-8b57-77c5407b3481
---
spring:
 profiles:
 active: dev
複製代碼

order模塊的配置文件相似,再也不贅述。

而後對自定義配置參數進行封裝。若是隻有單個參數,能夠不用JavaBean的形式,可是絕大多數狀況下都是多參數配置的,本文給出了JavaBean形式的封裝。

user模塊使用到的配置參數:

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Getter
@Setter
@ConfigurationProperties(prefix = "user")
public class UserConfig {

    /** * 用戶狀態:enable-啓用,disable-禁用 */
    private String status;
}
複製代碼

order模塊使用到的配置參數:

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Getter
@Setter
@ConfigurationProperties(prefix = "order")
public class OrderConfig {

    /** * 最大購買數量 */
    private int maxNum = Integer.MAX_VALUE;

    /** * 是否上架 */
    private boolean onSale = true;
}
複製代碼

而後就是編寫功能實現代碼,主要入口在order模塊中的OrderController:

@RefreshScope
@RestController
@RequestMapping
public class OrderController {

    @Autowired
    private OrderConfig config;

    @Autowired
    private UserRpcService userRpcService;

    @PostMapping(value = "/order")
    public String placeOrder(@RequestParam(name = "num", defaultValue = "1") Integer num) {
        if (!"enable".equals(userRpcService.getUserStatus())) return "該用戶已被禁用,暫不能下單";
        if (num <= 0) return "購買數量有誤";
        if (!config.isOnSale()) return "商品未上架";
        if (num > config.getMaxNum()) return "購買數量超限";
        return "OK";
    }
}
複製代碼

一些列的下單校驗,第一個校驗是判斷用戶狀態,使用了基於Feign的遠程調用。固然,必須在user模塊中提供對應的Controller實現:

@RefreshScope
@RestController
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private UserConfig config;

    @GetMapping(value = "/status")
    public String getUserStatus() {
        return config.getStatus();
    }
}
複製代碼

Controller中的@RefreshScope註解就是用來實現配置自動更新的。

整個工程準備就緒以後,先別急着run,還須要在Console中添加配置,用以測試動態配置是否生效。

添加配置的過程再也不贅述,須要注意的是Data Id的填寫規範。dataId的完整格式由三部分組成:

${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 類型。

Demo工程的配置列表
接下來就是分別啓動order和user兩個模塊,隨便玩玩。

5、其餘功能簡介

NACOS會記錄配置文件的歷史版本,保留30天,同時還貼心的提供了一鍵回滾功能,回滾操做將會觸發配置更新。

配置歷史版本
NACOS提供了配置監聽的Open-API。註冊監聽採用的是異步 Servlet 技術。註冊監聽本質就是帶着配置和配置值的 MD5 值和後臺對比。若是 MD5 值不一致,就當即返回不一致的配置。若是值一致,就等待必定時間段,返回空值。

最後就是優雅上/下線功能,算是NACOS的一大亮點。在每一個服務詳情裏面,能夠有多個實例(instance),經過Console能夠控制每一個實例的上/下線。若是是從新上線的話,會有一段時間的註冊過程,並非點擊「上線」按鈕以後就能立馬訪問到該實例。

6、NACOS的進階功能

若是決定要將NACOS大規模投產,上述功能還遠遠知足不了條件。在這一章節,將會講解若干個進階功能,爲你的NACOS服務保駕護航。

一、集羣模式

只啓動一個NACOS服務實例未免有些勢單力薄了,前述內容都是在單機部署的前提下,這一小節教你如何部署一個NACOS集羣。

找到conf/cluster.conf文件,若是沒有,就新建。編輯裏面的內容,僅需指定機器的ip和port,最好是3個或者3個以上。若是沒有這麼多機器資源,能夠直接在一臺機器上部署,區分端口號便可。以下:

# ip:port
192.168.0.88:8848
192.168.0.88:8849
192.168.0.88:8840
複製代碼

請注意,在集羣模式下就不能用127.0.0.1或者localhost了,當前版本對於網卡解析存在bug。

這個問題是由於Nacos獲取本機IP時,沒有獲取到正確的外部IP,須要保證InetAddress.getLocalHost().getHostAddress()或者hostname -i的結果是與cluster.conf裏配置的IP是一致的。

找到conf/application.properties,若是沒有,說明有問題。編輯裏面的內容,主要目的是啓用MySQL做爲存儲層(目前僅支持MySQL)。在該文件末尾追加:

spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456
複製代碼

而後新建一個名爲nacos的數據庫,運行conf/nacos-mysql.sql腳本文件。

以上,就是運行NACOS集羣模式所需的配置內容。

由於要在一臺機器上模擬多個NACOS服務,能夠將配置好的工程複製出兩份,而後在conf/application.properties中修改端口號便可。

目錄
而後,分別在三個命令窗口啓動NACOS:

startup -m cluster
複製代碼

分別使用對應的端口號訪問Console,若是能順利打開,說明部署成功了。

最後,在上述搭建的demo工程中,修改server-addr的值,把其餘NACOS訪問地址也加上去:

server:
 port: 8200
spring:
 application:
 name: order
 cloud:
 nacos:
 config:
 server-addr: 192.168.0.88:8848,192.168.0.88:8849,192.168.0.88:8840
 file-extension: yaml
 namespace: 7d3e5f19-a102-471a-b6e0-67bd7d1d35f3
 group: ORDER_GROUP
 discovery:
 server-addr: 192.168.0.88:8848,192.168.0.88:8849,192.168.0.88:8840
 namespace: 7d3e5f19-a102-471a-b6e0-67bd7d1d35f3
複製代碼

二、安全措施

很遺憾,NACOS的官網並無就安全性進行詳細的介紹。惟一看到的accessKeysecretKey兩項疑似安全的配置項,倒是爲了配合阿里雲的ACM而設立的。

讓我最爲關注的配置文件加密功能也暫未release出來,如下是官方原話:

Nacos計劃在1.X版本提供加密的能力,目前還不支持加密,只能靠sdk作好了加密再存到nacos中。 NACOS Console的安全性一樣很糟糕,密碼沒法修改,用戶不能建立,也沒有角色、權限的概念。

NACOS的服務註冊與發現基於HttpURLConnection進行遠程調用,這個地方是提供了HTTPS的啓用開關,JVM參數名是:com.alibaba.nacos.client.naming.tls.enable

除此以外,目前只能在NACOS的外圍作一些安全措施了。

三、一些有用的配置

nacos.home,這個是NACOS服務的啓動參數,以JVM參數的形式傳入。可是很遺憾,使用這個參數並非很方便,須要修改啓動腳本,大概是在startup.sh文件中的104行:

JAVA_OPT="${JAVA_OPT} -Dnacos.home=${BASE_DIR}"
複製代碼

更爲完全的方法是修改BASE_DIR的值(默認爲startup.sh文件的父目錄),大概在startup.sh文件中的71行:

export BASE_DIR=`cd $(dirname $0)/..; pwd`
複製代碼

nacos.logging.path,日誌是一個系統運行最寶貴的附加產物,有的時候爲了便於管理,須要自定義日誌目錄。若是須要指定,一樣須要修改startup.sh腳本。大概在104行後追加一行:

JAVA_OPT="${JAVA_OPT} -Dnacos.logging.path=指定的目錄"
複製代碼

固然,日誌級別也能指定,分別經過com.alibaba.nacos.naming.log.level和com.alibaba.nacos.config.log.level這兩個JVM參數指定。

不過,還須要特別說明一下,並不是全部日誌都是有價值的,能夠根據實際狀況進行刪減,不然會對服務器形成沒必要要的負擔,相關日誌配置能夠在conf/nacos-logback.xml文件中修改。

四、endpoint

在上述配置文件中所涉及的serverAddr參數是窮舉了全部可用的NACOS服務,在大規模應用場景下,這種配置方式顯然是不合理的。endpoint至關於一個DNS服務,能夠代理全部NACOS服務,只須要指定一個訪問域名。

這篇文章是對endpoint的一個最佳實踐,而且給出了環境隔離的有效手段。

7、總結

本文是對Spring Cloud Alibaba Nacos的功能性介紹。

若是研發能力強勁的隊伍,能夠如今嚐嚐這隻「螃蟹」,順帶還能貢獻很多的PR。

我的建議先觀望一段時間,大概在v1.2.0版本以後,就能夠逐漸引入到公司的技術棧內了。

掃描下方二維碼,進入原創乾貨,搞「技」聖地。

相關文章
相關標籤/搜索