Nacos 1.3.0 全新內核構建
經過一年多發展,1.2.0版本已經從安全上解決上生產的最後疑慮,解決用戶主要訴求。經過社區討論,從1.3.0版本開始修煉內功,聚焦“簡單”、“性能”、“高可用”這核心的三個點進一步提升Nacos核心競爭力。今天很高興能代表社區向大家介紹1.3.0的核心特性
- 內嵌關係型分佈式數據庫,簡化集羣部署模式
- 集羣管理下沉統一,提供全新集羣管理能力
- 一致性協議抽象升級,提供更高的性能
- 安全升級,解決Fastjson和越權風險
下面我們逐個介紹一下這些能力
輕量級的內嵌關係型分佈式數據庫
爲什麼只是用服務發現模塊也要我部署MySQL?MySQL集羣搭建的成本有多高?不能把集羣部署簡單一點,像Consul、Etcd那樣子?
這不,爲了解決這個問題,Nacos 1.3.0 借鑑了 Etcd 的通過Raft協議將單機KV存儲轉變爲分佈式的KV存儲的設計思想,基於SOFA-JRaft以及Apache Derby構建了一個輕量級的分佈式關係型數據庫,同時保留了使用外置數據源的能力,用戶可以根據自己的實際業務情況選擇其中一種數據存儲方案。
從nacos 1.3.0版本開始集羣部署可以不依賴MySQL的這個特性,不僅降低中小用戶的集羣運維部署成本,也簡化了其集羣部署的操作以及省去了部署一套數據庫集羣的操作。
新特性的開啓命令爲
#啓動命令(standalone代表着單機模式運行,非集羣模式):
#新特性的開啓命令-p embedded
sh startup.sh -m standalone -p embedded
#查看啓動日誌信息
cat /Users/honglei/dev/alibaba/Nacos/nacos-server-1.3.0/logs/start.out
然後查看啓動日誌是否有出現以下信息:
2020-06-15 14:18:31,035 INFO Nacos started successfully in stand alone mode. use embedded storage
同時,爲了方便用戶查詢本機節點的數據同步情況,Nacos 1.3.0 配置模塊開放了新的運維 Open-API,供其查詢當前節點本地數據存儲情況,並且該Open-API只能執行select語句,其他DML語句一概不支持,其使用方式如下
GET /nacos/v1/cs/ops/derby?sql=select * from config_info
使用該命令時,最好加上分頁查詢,避免一次查處大量的數據影響Nacos的正常對外業務工作,如果沒有加上分頁查詢,則會自動添加分頁查詢語句,默認查詢最開始的1k條數據。其分頁查詢的SQL的例子如下。
select * from config_info OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY
注意:sql參數需要urlencode編碼一下,下面有個網址工具
#urlencode後的sql 拼接好的結構,可以直接執行
curl -X GET http://127.0.0.1:8848/nacos/v1/cs/ops/derby\?sql\=select%20\*%20from%20config_info%20OFFSET%200%20ROWS%20FETCH%20NEXT%202%20ROWS%20ONLY
其數據返回結果如下
{
"code": 200,
"message": null,
"data": [
{
"ID": 244271244847878140,
"DATA_ID": "gateway-uat.json",
"GROUP_ID": "DEFAULT_GROUP",
"TENANT_ID": "",
"APP_NAME": "",
"CONTENT": "此處省略",
"MD5": "4fe4bbf76036944e226a1827c7b1fa48",
"GMT_CREATE": "2020-06-09T02:00:43.110+0000",
"GMT_MODIFIED": "2020-06-09T02:00:43.110+0000",
"SRC_USER": null,
"SRC_IP": "10.100.123.172",
"C_DESC": null,
"C_USE": null,
"EFFECT": null,
"TYPE": "json",
"C_SCHEMA": null
},
{
"ID": 244271245057593340,
"DATA_ID": "activiti-nacos-config-uat.yaml",
"GROUP_ID": "DEFAULT_GROUP",
"TENANT_ID": "",
"APP_NAME": "",
"CONTENT": "此處省略",
"MD5": "7837a03614168870dc8ad9cbe7c6150e",
"GMT_CREATE": "2020-06-09T02:00:43.110+0000",
"GMT_MODIFIED": "2020-06-09T02:00:43.110+0000",
"SRC_USER": null,
"SRC_IP": "10.100.123.172",
"C_DESC": null,
"C_USE": null,
"EFFECT": null,
"TYPE": "yaml",
"C_SCHEMA": null
}
]
}
Nacos 1.3.0 構建的輕量級的分佈式關係型存儲,其已滿足事務ACID性質。後面我們會在這基礎之上進一步優化該存儲的性能。
注意事項
分佈式ID——Snowflake
Nacos 1.3.0的分佈式存儲,其數據的主鍵依賴雪花ID算法進行生成,雪花算法ID需要DataCenterId、WorkerId,默認情況下,WorkerId不需要進行設置,會根據InetAddress.getLocalHost()進行計算生成。如果需要自己指定,則在application.properties進行如下配置設置
目錄:/Users/honglei/dev/alibaba/Nacos/nacos-server-1.3.0/conf
###*************** Add from 1.3.0 ***************###
#*************** Core Related Configurations ***************#
### set the WorkerID manually
# nacos.core.snowflake.worker-id=
數據遷移
由於Nacos 1.3.0新增的內嵌存儲模式是全新的數據存儲模式,因此在進行Nacos-Server升級時,如果是需要使用這種新能力,需要另外部署一個Nacos 1.3.0集羣,然後進行數據遷移,由於Nacos 1.3.0 新增的內嵌存儲模式,還無法自動的將原本MySQL的數據直接一鍵進行數據遷移,因此用戶只能使用控制檯的數據導出導入的方式進行(會丟失配置歷史數據),更加完備的數據遷移功能會在後面的版本進行開放。
全新的集羣管理
提供全新集羣管理頁面
Nacos 1.3.0版本開始,對集羣節點管理進行了統一,將原有配置模塊以及服務模塊的集羣節點管理統一下沉到內核模塊,並且優化了集羣節點信息展示,使得其更貼近Nacos集羣節點的數據信息展示,其顯示的內容包括如下幾個方面
- 服務發現模塊舊的Raft協議的元數據數據
- 配置管理模塊使用新Raft協議的元數據
- Nacos節點自身的元數據信息
a. 新Raft協議的RPC端口
b. 節點的版本信息
c. 節點的權重信息(該權重的功能暫未提供,以後服務端節點的負載均衡使用)
d. 節點元數據信息上次刷新時間
新的集羣尋址模式設置
Nacos 1.3.0版本開始,對集羣節點的尋址模式做了統一,將原本分散的節點尋址模式整合並抽象,方便將來可以擴寬Nacos的集羣發現機制,用戶可以通過如下設置自己選擇需要使用哪一種尋址模式作爲集羣節點的管理
文件尋址模式
nacos.core.member.lookup.type=file(默認值)
地址服務尋址模式
nacos.core.member.lookup.type=address-server
全新的一致性協議
Nacos 1.3.0版本開始,將對現有的一致性協議層進行統一抽象以及下沉。在Raft的選型上,使用了SOFA-JRaf作爲CP協議的Backend,並且將其與配置管理模塊進行了對接。用戶可以通過調整下面的參數對Raft協議進行調整
# Sets the Raft cluster election timeout, default value is 5 second
# 設置Raft羣集選舉超時,默認值爲5秒
nacos.core.protocol.raft.data.election_timeout_ms=5000
# Sets the amount of time the Raft snapshot will execute periodically, default is 30 minute
# 設置Raft快照定期執行的時間,默認值爲30分鐘
nacos.core.protocol.raft.data.snapshot_interval_secs=30
# Raft internal worker threads
# Raft 內部工作線程數量
nacos.core.protocol.raft.data.core_thread_num=8
# Number of threads required for raft business request processing
# Raft 業務請求處理所需的線程數
nacos.core.protocol.raft.data.cli_service_thread_num=4
# raft 線性讀取策略,默認爲ReadOnlySafe,可以選擇ReadOnlyLeaseBased
nacos.core.protocol.raft.data.read_index_type=ReadOnlySafe
### rpc請求超時,默認5秒
nacos.core.protocol.raft.data.rpc_request_timeout_ms=5000
線性讀參數解析
ReadOnlySafe
該線性讀模式,每次Follower進行讀請求時,需要和Leader同步日誌提交位點信息,而Leader,需要向過半的Follower發起證明自己是Leader的輕量的RPC請求,相當於一個Follower讀,至少需要1 + (n/2)+ 1 次的RPC請求。
ReadOnlyLeaseBased
該線性讀模式,每次Follower進行讀請求時,Leader只需要判斷自己的Leader租約是否過期了,如果沒有過期,直接可以回覆Follower自己是Leader,但是該機制對於機器時鐘要求很嚴格,如果有做時鐘同步的話,可以考慮使用該線性讀模式。
如果說對於配置的發佈、修改操作比較頻繁,可以將Raft快照的時間適當的進行調整,避免新節點加入或者節點重啓時,由於Raft日誌回放操作數太多導致節點可開始對外服務的時間過長。
JRaft
同時,爲了方便運維對新的Raft協議能夠進行一些簡單的運維操作,Nacos 1.3.0 內核模塊開放了相關一致性協議運維的 Open-API,供其對Raft進行一些運維操作,其相關的運維操作如下
切換某一個Raft Group的Leader節點
POST /nacos/v1/core/ops/raft
{
"groupId": "xxx",
"command": "transferLeader"
"value": "ip:{raft_port} or ip:{raft_port},ip:{raft_port},ip:{raft_port}"
}
重置某一個Raft Group的集羣成員
POST /nacos/v1/core/ops/raft
{
"groupId": "xxx",
"command": "resetRaftCluster",
"value": "ip:{raft_port},ip:{raft_port},ip:{raft_port},ip:{raft_port}"
}
注意,該操作是一個高危操作,僅僅當Raft集羣的 n/2 + 1節點crash之後無法滿足過半投票的要求才可以使用該運維命令,用於快速讓當前剩餘的節點重組Raft集羣,對外提供服務,但是這個操作很大程度會造成數據的丟失
觸發某一個Raft Group執行快照操作
POST /nacos/v1/core/ops/raft
{
"groupId": "xxx",
"command": "doSnapshot",
"value": "ip:{raft_port}"
}
移除某一個Raft Group中的某一成員
POST /nacos/v1/core/ops/raft
{
"groupId": "xxx",
"command": "removePeer",
"value": "ip:{raft_port}"
}
批量移除某一個Raft Group中的多個成員
POST /nacos/v1/core/ops/raft
{
"groupId": "xxx",
"command": "removePeers",
"value": "ip:{raft_port},ip:{raft_port},ip:{raft_port},..."
}
後續
目前一致性協議層只是將CP協議具體實現了,後面會再將AP協議——Distro下沉到一致性協議層中,並且調整Distro的實現,其協議內部的通信將使用gRPC,以配合Nacos對於整個通信通道的規劃。同時真正實現對整個一致性協議使用方式的收攏。
安全升級
- 修復fastjson安全漏洞
- 修復tenant越權漏洞
貢獻者
Nacos 1.3.0 版本的開發中,社區同學貢獻了很大的力量,在此表示感謝,他們是(排序不分先後):
@KomachiSion @zongtanghu @wangweizZZ @Maijh97 @jintonghuoya @jzdayz @yfh0918
@wolfgangzhu @ObserverYu @langghaha @jiangcaijun @wfnuser @TsingLiang @showkawa @yanlinly
@chuntaojun
轉載 廖春濤(春少)並結合自己實際環境進行些驗證操作