愈來愈多的讀者在和我交流關於Spring Cloud Alibaba的種種事宜,甚至於在一次面試中,一半時間都在聊這個話題。因此,本着對技術鑽研的熱情,對Spring Cloud Alibaba進行了一番研究。html
在這裏,並不想高談闊論,也不想預言將來,只是挑選了幾個從阿里巴巴中間件團隊內脫胎出來的開源組件,對於解決實際業務問題有所裨益。java
先來講說大背景。mysql
如今,很明顯的一個趨勢就是:微服務。git
這個趨勢的底層驅動力就來源於分佈式系統的普及,而微服務的各個特性是現在大大小小的企業沒法拒絕的誘惑。github
而後,用上了微服務的架構風格,用Spring Cloud,或者Dubbo搭了一套腳手架,就開始幹起來了。面試
接下來,一衆小公司畫完了大餅以後,發現本身根本吃不下。這就是典型的落後勞動力與先進生產力的尖銳矛盾。這個時候,返璞歸真的想法是不能有了,重構代價太大。spring
固然,哪裏有問題,哪裏就有商機。各大XX雲廠商通過一系列包裝以後,用「雲原生(Cloud Native)」的新概念粉墨登場。sql
Spring Cloud Alibaba就是其中之一。shell
這個概念的一個核心價值就是:平滑上雲,賦能運維。最明顯的業務表象就是,會提供一套Open API,甚至是貼心的提供一個可視化控制檯,傻瓜式的那種。數據庫
這是一顆耀眼的掌上明珠,迅速引發了個人注意。
按照套路,分爲兩講。其一講述NACOS的功能特性,及其使用,再者就是更深刻一步,看看大廠的攻城獅們寫的代碼。
本文所使用的版本是NACOS 1.0.0,因爲此版本仍是第一個NACOS正式版,NACOS正處在飛速發展階段,本文的一些內容可能會不適用於之後的版本,請讀者自行辨別。
NACOS解決兩個核心問題:動態配置管理,服務註冊發現。
兼容性方面,除了支持自家的Dubbo,還對Spring Cloud,Kubernetes,Istio有所兼容。
至此,不說道說道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中迷失自我,有必要先闡述幾個重要的概念。
NACOS給的最佳實踐代表,最外層的namespace是能夠用於區分部署環境的,好比test,uat,product等。同時,也有一個商業利用價值:多租戶。以namespace爲單位,給用戶開闢使用空間。
其它兩個領域模型不用多解釋了,見名知意。其目的也很是明顯,就是爲了可以邏輯上區分兩個目標對象。
默認狀況下,namespace=public,group=DEFAULT_GROUP。
明白了這個數據模型後,能夠稍微玩轉一下Console了,好比新建若干個namespace:
在進行下一章節以前,強烈建議先建立一個Spring Boot樣板工程,能夠不作任何配置,不添加任何一段代碼。
固然,爲了讓這一講的內容更具實戰意義,我不會照搬官網的Demo,本文所做的Demo工程也能夠從GitHub上克隆獲得。請提早準備好,接下來的內容只會挑重點講解,側重點不會在如何搭建工程。
工程名稱爲:nacos-example,在各個pom.xml文件中相關依賴管理就再也不贅述了。
如今來介紹一下,這個demo工程幹了一件什麼事:用戶在下單的時候,須要校驗用戶的狀態,商品是否上架以及購買的數量上限。
爲了體現動態配置,用戶狀態和購買的數量上限作成配置項。而這二者的配置在不一樣的namespace下是有所不一樣的。
爲了體現服務間的調用,下單入口在order模塊,經由user模塊進行校驗。
這樣的配置規則會存在很大的爭議,本文不作討論。
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 類型。
NACOS會記錄配置文件的歷史版本,保留30天,同時還貼心的提供了一鍵回滾功能,回滾操做將會觸發配置更新。
最後就是優雅上/下線功能,算是NACOS的一大亮點。在每一個服務詳情裏面,能夠有多個實例(instance),經過Console能夠控制每一個實例的上/下線。若是是從新上線的話,會有一段時間的註冊過程,並非點擊「上線」按鈕以後就能立馬訪問到該實例。
若是決定要將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中修改端口號便可。
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的官網並無就安全性進行詳細的介紹。惟一看到的accessKey和secretKey兩項疑似安全的配置項,倒是爲了配合阿里雲的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的一個最佳實踐,而且給出了環境隔離的有效手段。
本文是對Spring Cloud Alibaba Nacos的功能性介紹。
若是研發能力強勁的隊伍,能夠如今嚐嚐這隻「螃蟹」,順帶還能貢獻很多的PR。
我的建議先觀望一段時間,大概在v1.2.0版本以後,就能夠逐漸引入到公司的技術棧內了。
掃描下方二維碼,進入原創乾貨,搞「技」聖地。