高效能配置中心 duic - 設計&實現
什麼是配置?
配置(Configuration)對於技術人員來說應該都不陌生,通常配置都是以 key-value
的形式存在於配置檔案當中。例如執行緒池大小、資料庫連線、邏輯開關及業務引數等等。
那麼為什麼我們需要提供各種各樣的配置呢?其本質原因是我們無法在開發時決定軟體在執行時的一切,為保證程式的靈活性我們需要在開發過程中提供各種配置,以便軟體在執行時能動態調整程式的行為。
配置即程式在執行時動態調整行為的能力!
靈感
之前我們一直是使用 spring-cloud-config
來管理服務端配置,但是 spring-cloud-config
並不支援熱載入,按需獲取配置,且因為是 spring
體系中的專案對於其它語言或非 spring
體系的專案支援較弱。
建立在這種基礎之上,我們借鑑了 spring-cloud-config
的配置管理方式以及應用環境管理方式開發了全新的分散式配置中心 duic。
簡介
duic 的誕生從來都不只是為了解決服務端的配置問題,你同樣可以使用它對 APP、WEB 應用的配置進行管理。因採用 HTTP 的方式拉取配置資料,對於多語言,多應用型別的配置支援非常的好。
如果你的 APP、WEB、Server 有一部分公共配置,你也可以完全使用 duic 來解決,而不需要在每個應用單獨配置(冗餘),修改一處配置對於所有應用都有效。並且 duic 支援多配置合併功能,你可以將公共配置與私有配置分開管理,在拉取配置時進行合併,能有效的進行配置許可權管理。同時 duic 支援按需獲取配置,這個功能對於 WEB、APP 非常有用,有時你可能只需要某個配置引數,而不是拉取整個配置資料。
設計目標是統一不同應用的配置管理方式,打造更人性化的配置編輯方式,提供更靈活的配置獲取方式。
duic 配置管理方式與其它配置中心是完全不一樣的,我們放棄採用 key-value
兩個輸入框來編輯配置的方式。轉而採用 YAML 語法 + 線上編輯器的方式來管理編輯配置。這樣可以輕鬆支援結構化配置並且你可以得到高度視覺化配置編輯方式,如下圖:
這種管理方式所帶來的好處是:
配置可讀性高
支援語法高亮
支援資料型別
支援文件註釋
結構化配置為按需獲取配置提供了基礎
通常配置都是以 key-value
的形式存在,比如 VIP 的價格 vip.price=100
,是否啟用某個功能 game.enabled=true
。大多數情況是如此,但是實際情況中還是有很多場景需要結構化的配置支援,目前使用較多來處理這種場景的方法是使用 key=json string
來解決。 例:將圖示和點選的 URL 採用 JSON 的方式配置,可以在資料結構中維持配置的關係且配置易於理解。
{ "logo": { "top": { "icon": "icon url", "url": "link url"
}, "special": { "icon": "icon url", "url": "link url"
}, "goddess": { "icon": "icon url", "url": "link url"
}
}
}
但是這種方式的缺點依然很明顯,使用時必須要手動呼叫 JSON 解析 API 將字串轉換為 JSON 物件,其次是無法按需取值,比如我只想要 logo.top
的配置,但是也必須要將整個 logo
轉換為 JSON 之後才能獲取 top
的配置。而 duic 提供了按需獲取配置介面,可以直接獲取 logo.top
的配置項。
特性
集中配置管理,多應用多環境配置
配置實時更新
支援配置資料型別/資料格式
HTTP 方式拉取配置
配置狀態檢查
配置狀態監控
多配置合併
按需獲取配置
配置許可權管理
支援配置 IP 訪問限制
支援配置 TOKEN 校驗
支援 MySQL 儲存配置
支援 Oracle 儲存配置
支援 PostgreSQL 儲存配置
支援 MongoDB 儲存配置
支援 Docker 部署
完美支援 Spring Boot
如果你的專案是採用 spring-boot 開發,那 duic 不僅能管理你業務的配置,還能管理所有 spring-boot 相關的配置,配置方式與
application.yml
檔案編輯無差異。比如你可以像下圖一樣設定應用日誌級別資訊,當你修改日誌級別後在應用中能實時反應。
系統架構
部署
基本部署方案
duic 支援 MySQL、PostgreSQL、Oracle、MongoDB 儲存配置資訊,你可以靈活的選擇配置儲存方式。依照上圖部署 duic 就能使用配置中心的全部功能,部署的方式和網路組織架構都非常的簡單。
在設計時為了能簡化部署,將 Admin 與獲取配置相關的 API 整合在一個服務當中,降低部署的複雜性。
高可用部署架構方案
duic 對於資料庫的壓力非常的小,所以基本上資料庫你只需要 master/salve 部署模式即可實現服務高可用。duic 服務你可以根據自身業務的壓力情況部署 N 個。前面可以採用 nginx 做負載均衡利用 keepalived 避免單點問題。這是我們目前使用 duic 高可用的部署方案(僅供參考)。
實現
duic 是完全採用 Reactive Programming 實現。使用技術主要有 kotlin、spring-webflux、spring-boot、vue.js、gradle。
配置實時更新
客戶端啟動時獲取配置及配置狀態。
使用
/apps/watches/{name}/{profiles}
介面監控服務端配置狀態變化。
呼叫
watches
介面時需要傳入客戶端當前狀態,服務端根據客戶端傳入的狀態判斷。如果與服務端的配置狀態不一致會立即響應最新的狀態。
如果狀態一致請求則會延遲返回(最長30秒)。在30秒內配置狀態發生變化,服務端會立即響應。在30秒配置狀態未發生變化,服務端也會響應當前最新狀態給客戶端。
接收到服務端的狀態響應時客戶端需要判斷狀態是否與客戶端當前的一致,如果一致則繼續
watch
配置狀態,如果不一致則過載配置
配置過載完全是由客戶端發起的,這是長輪詢(Long Polling)實現,利用 HTTP 長連線無需擔心重複建立連結問題,帶來的好處就是實現簡單可用性高。
配置&記憶體
在 duic 服務啟動時會將資料庫儲存的配置資料全部載入在 JVM 記憶體中,當你通過 HTTP 介面訪問配置資料時,duic 會直接將記憶體中的配置返回,中間不會有任何查詢資料庫的操作,所以你使用 duic 獲取配置時響應速度非常的快(具體請看後面的效能測試報告)。
叢集管理
在 duic 服務啟動時會將啟動服務的主機名與埠註冊到資料庫的 DUIC_SERVER
表中。當有人在控制檯修改配置時,duic 會通知 DUIC_SERVER
表中的所有服務過載最新配置。同時 duic 內部還會輪詢機制保證 JVM 記憶體永遠都是最新的配置資料。
RESTful API
OpenAPI 3.0 文件
獲取配置狀態
GET /apps/states/{name}/{profiles}
監控配置狀態
GET /apps/watches/{name}/{profiles}
獲取配置
GET /apps/{name}/{profiles}
按需獲取配置
GET /apps/{name}/{profiles}/{key}
效能報告
伺服器配置:E5-2620V3(12核24執行緒 主頻2.4GHz) / 16G
作業系統:Ubuntu 16.04
測試工具: wrk
Java 版本:1.8.0_161
JVM 引數
java -server -XX:+UseG1GC -Xms8g -Xmx8g -XX:MetaspaceSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs/ -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:logs/gc.log
測試結果,每秒 duic 可達到 24760tps,服務的每個工作執行緒 CPU 已經達到 97% 以上,在這臺裝置中效能已經無法在繼續提高了,這是我目前手上最好的伺服器。
Running 1m test @ http://192.168.31.164:7777/api/v1/apps/meme/test-public
12 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.91ms 1.01ms 38.21ms 93.70%
Req/Sec 2.07k 92.01 2.71k 83.65%
1486594 requests in 1.00m, 4.52GB read
Requests/sec: 24760.93
Transfer/sec: 77.10MB
CPU 報告
GC 報告
結語
duic 配置中心原始碼倉庫 https://github.com/zhudyos/duic 歡迎大家提供任何意見,建議和吐槽。
公眾號推薦:
相關文章
- 高效能配置管理中心 duicUI
- DuiC 統一配置管理 2UI
- Apollo配置中心-配置熱釋出如何實現
- 鬥魚 Juno 監控中心的設計與實現
- 高效能 Go 日誌庫 zap 設計與實現Go
- IoT平臺如何實現業務配置中心
- 聊聊訊息中心的設計與實現邏輯
- 仿微博訊息中心的系統設計與實現
- 高效能JavaScript 程式設計實踐JavaScript程式設計
- Spring Cloud Config 實現配置中心SpringCloud
- 基於zookeeper實現分散式配置中心(二)分散式
- .net5+nacos+ocelot 配置中心和服務發現實現
- 利用Spring Boot實現微服務的配置中心Spring Boot微服務
- SpringCloud+Nacos實現服務配置中心(Hoxton版本)SpringGCCloud
- 程式設計實戰篇——Spring Boot 自動配置實現程式設計Spring Boot
- GPU高效能程式設計CUDA實戰(二)GPU程式設計
- 【架構師視角系列】風控場景下配置中心的設計實戰架構
- Spring Cloud Alibaba 整合 Nacos 實現服務配置中心SpringCloud
- 實現高效能高併發的計數器功能
- 高效能佇列設計佇列
- 基於Apache Zookeeper手寫實現動態配置中心(純程式碼實踐)Apache
- 億級使用者中心的設計與實踐
- 詳解Nacos 配置中心客戶端配置快取動態更新的原始碼實現客戶端快取原始碼
- Java中的動態配置更新:從配置中心到應用熱載入的實現Java
- 高效能JavaScript DOM程式設計JavaScript程式設計
- Swoole PHP高效能程式設計PHP程式設計
- Redis設計與實現Redis
- 《redis設計與實現》Redis
- 遊戲架構設計——高效能並行程式設計遊戲架構並行行程程式設計
- Dubbo使用Apollo作為配置中心實戰
- Android Binder設計與實現 - 設計篇Android
- rnacos——用rust重新實現的nacos開源配置、註冊中心服務Rust
- 解鎖新姿勢 | 如何用配置中心實現全域性動態流控?
- 微服務註冊發現配置中心-consul微服務
- 實現Java集合迭代的高效能Java
- 實現高效能微信朋友圈
- 使用Cahce實現高效能系統
- 高效能javascript程式設計筆記JavaScript程式設計筆記