摘要:本文我們就如何使用阿里云ACM這樣的配置管理產(chǎn)品在Spring Cloud中替代Spring Cloud Config幫助簡化環(huán)境配置管理做一個簡單的示例,幫助你理解基于ACM來簡化微服務(wù)環(huán)境配置管理的方案,并會簡單比較一下ACM與Spring Cloud Config方案的優(yōu)劣。
1. 配置的環(huán)境屬性
毫無疑問,在系統(tǒng)持續(xù)交付的過程中,系統(tǒng)最終運行環(huán)境的多樣性及復(fù)雜性毫無疑問增加了我們在配置管理工作上的負擔,有時候,甚至不夸張的說,配置就是因環(huán)境而生。
這在Eugen Paraschiv的博文Configuration Must Be Environment Specific里有簡單的闡述,在我的博文《現(xiàn)代應(yīng)用架構(gòu)中的配置管理面臨的挑戰(zhàn)》的容器化、調(diào)度與配置管理小節(jié)也有深入的闡述。
如果要問,是什么導(dǎo)致了我們應(yīng)用的構(gòu)建物(artifact)在各個環(huán)境不能保持一樣,有時候Docker無法輕易達成“Build Once, Run Anywhere!"的承諾,其答案往往就是環(huán)境配置的差異,為幫助你理解,舉一些簡單的例子:
在開發(fā)環(huán)境中將logLevel設(shè)置為DEBUG,在預(yù)發(fā)環(huán)境logLevel設(shè)置為INFO,生產(chǎn)環(huán)境里logLevel設(shè)置為WARNING
在開發(fā)環(huán)境中使用4核8G的機器跑數(shù)據(jù)庫,而在生產(chǎn)中用32核96G機器跑數(shù)據(jù)庫
在日常環(huán)境執(zhí)行線程池的最大線程數(shù)應(yīng)該設(shè)置為15,而生產(chǎn)環(huán)境上這個值應(yīng)該大一點,默認設(shè)為150
在線上環(huán)境中,中心機房,應(yīng)用數(shù)據(jù)源需要連接A庫,而深圳機房,應(yīng)用應(yīng)該就近連接使用B庫
只有在小淘寶環(huán)境,雙向同步開關(guān)才應(yīng)該關(guān)閉
這次的改動有點大,新的特性僅在線上的杭州單元把該特性開放出來,其它的單元環(huán)境先不要開放出來
本文我們就如何使用阿里云ACM這樣的配置管理產(chǎn)品在Spring Cloud中替代Spring Cloud Config幫助簡化環(huán)境配置管理做一個簡單的示例,幫助你理解基于ACM來簡化微服務(wù)環(huán)境配置管理的方案,并會簡單比較一下ACM與Spring Cloud Config方案的優(yōu)劣。
2. 場景故事
為了幫助理解需求和場景,在日常工程實踐中,我們一般會用用戶故事(User Story)的方式,預(yù)設(shè)一個簡單的場景,以此來做闡釋和交流,熟悉微服務(wù)歷史的兄弟一定熟悉下面這張早期的布道圖:

本文中我們就以Movie Service為例,假設(shè)我們需要從關(guān)系數(shù)據(jù)庫MySQL(RDS)檢索所有電影信息列表,但是在測試環(huán)境、預(yù)發(fā)和生產(chǎn)環(huán)境我們需要使用不同的數(shù)據(jù)庫,因為只有生產(chǎn)庫才需要頂配的機器。這樣我們的應(yīng)用需要在不同的環(huán)境配置不同的數(shù)據(jù)源配置、連接池配置、數(shù)據(jù)庫安全配置等等,我們會介紹如何基于阿里云ACM的Namespace映射不同環(huán)境的能力,為movie service在不同運行環(huán)境設(shè)置不同的數(shù)據(jù)源配置。
如下圖所示:

3. 創(chuàng)建微服務(wù) Movie Service
新建Spring Boot Starter 微服務(wù)應(yīng)用 movie service
movie service的業(yè)務(wù)邏輯很簡單,從MySQL(RDS)里列出所有的movie列表,如下簡圖所示:

這里我們創(chuàng)建了一個標準的jpa應(yīng)用(類似Spring官網(wǎng)的樣例工程Accessing data with MySQL,我們的工程結(jié)構(gòu)如下圖所示:

引入JPA、MySQL、連接池HikariCP以及WEB依賴
org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-data-jpamysqlmysql-connector-javaruntimecom.zaxxerHikariCP2.7.6
創(chuàng)建 MySQL(RDS) 數(shù)據(jù)庫及用戶
mysql> create database db_example; -- Create the new databasemysql>create user'springuser'@'localhost'identified by'ThePassword'; -- Creates the usermysql>grant all on db_example.* to'springuser'@'localhost'; -- Gives all the privileges to the new user on the newly created database
具體可參考Accessing data with MySQL中的 'Create the database'小節(jié)
創(chuàng)建 WEB Controller
package com.alibaba.demo.microsvc.controller;
import org.springframework.beans.factory.annotation.Autowired;
org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
importcom.alibaba.demo.microsvc.dao.MovieRepository;
import com.alibaba.demo.microsvc.model.Movie;
@RestController
public class MovieController {
@AutowiredMovieRepository movieRepository;@RequestMapping("/list-movies")public @ResponseBody Iterable listMovies() {returnmovieRepository.findAll();? }}
4. 在ACM中使用Namespace創(chuàng)建隔離的環(huán)境配置
注: 在阿里云上使用ACM的前提是開通了該項服務(wù),具體開通流程可以參考文檔ACM快速入門,開通服務(wù)并登陸之后,即可進入ACM 控制臺創(chuàng)建命名空間及配置
在ACM中創(chuàng)建3個環(huán)境 (dev,stage,prod)

為 dev,stage,prod 不同環(huán)境分別創(chuàng)建配置

注意 我們完成了什么?
在上一步中,我們?yōu)橄嗤渲庙椺槍Σ煌h(huán)境的設(shè)置了不同的值,例如 'spring.datasource.url'這個配置項,我們通過設(shè)置不同的url來為各環(huán)境連接不同的數(shù)據(jù)庫,并且僅在生產(chǎn)環(huán)境開啟SSL (useSSL=true)
dev:? ? ? ? spring.datasource.url=jdbc:mysql://localhost:3306/db_example?useSSL=false>? ? ? ? prod:? ? ? ? spring.datasource.url=jdbc:mysql://30.5.101.169:3306/db_example?useSSL=true>? ?
同時,我們也為生產(chǎn)環(huán)境(prod)設(shè)置了更大的數(shù)據(jù)庫連接池和更小的連接超時時間
dev:? ? ? ? spring.datasource.hikari.connection-timeout=60000? ? ? ? spring.datasource.hikari.maximum-pool-size=10>? ? ? ? prod:? ? ? ? spring.datasource.hikari.connection-timeout=15000? ? ? ? spring.datasource.hikari.maximum-pool-size=200>? ?
而為了方便開發(fā)調(diào)試,我們僅在開發(fā)環(huán)境打開了SQL Trace
dev:? ? ? ? spring.jpa.show-sql=true
5. Movie Service與配置中心ACM集成
現(xiàn)在我們將集成Movie Service與ACM以便從ACM中獲取對應(yīng)環(huán)境的配置. 關(guān)于如何在Spring Cloud中使用ACM,具體可以參考ACM官方文檔開發(fā)指南 > SDK 參考 > Spring Cloud ACM
為movie service引入ACM依賴
com.alibaba.cloudspring-cloud-starter-acm1.0.1
在application.properties配置ACM連接信息、namespace、accessKey、secretKey等信息
spring.application.name=movie-servicespring.application.group=com.alibaba.cloud.acm? alibaba.acm.endpoint=acm.aliyun.comalibaba.acm.namespace=alibaba.acm.accessKey=alibaba.acm.secretKey=
注意: 你可以在ACM的'命名空間詳情'或者'配置的示例代碼'里找到你的namespace_id,accessKey,secretKey等信息,如下圖所示:

6. 在瀏覽器里訪問Movie Service

7. 查看ACM配置推送刷新信息
如果在movie service引入了spring-boot-starter-actuator依賴并且在application.properties設(shè)置了management.security.enabled=false,可以通過端點http://<>/acm看到應(yīng)用的配置消費及刷新情況,如下圖:

也可以在ACM控制臺上查看配置的推送軌跡、配置版本等信息,具體使用方法可參考ACM官方文檔,在此不再贅述。
8. ACM與Spring Cloud Config簡單對比
對比項Spring Cloud Config阿里云ACM
Spring Cloud 無縫集成支持支持
源碼分發(fā)方式開源即將開源
收費模式免費免費
大規(guī)模(超10萬配置)生產(chǎn)驗證無公開的大規(guī)模生產(chǎn)驗證案例阿里巴巴數(shù)據(jù)中心生產(chǎn)環(huán)境超百萬級配置,每天超億級配置變更推送,雙11等嚴苛場景驗證
配置管控UI控制臺無控制臺,依賴IDE,GIT等三方工具專業(yè)的配置管理UI控制臺
多語言支持主要支持java生態(tài),無其它語言的原生客戶端支持nodejs,c++等原生多語言客戶端
多機房、同城雙活、異地多活、多可用區(qū)等架構(gòu)依賴GIT 等能力支持,官方無明確說明支持
配置變更推送依賴RabbitMQ/KAFKA內(nèi)置的推送機制,無外部依賴
大規(guī)模推送時效依賴GIT Web Hook等SLA,WEB HOOK在企業(yè)級大規(guī)模生產(chǎn)能力待驗證工業(yè)級、毫秒級
配置變更審計能力弱內(nèi)置的審計機制(審計能力符合國家安全等保三級標準)
推送軌跡無法查看配置推送到客戶端的實時監(jiān)測有配置變更推送軌跡幫助監(jiān)控配置變更推送狀況
數(shù)據(jù)隔離application,profile,label,git repo等隔離策略除Spring Cloud提供的隔離級別,還提供多租戶,app,data_id,group等多級隔離策略
生產(chǎn)運維成本高(必須對GIT/RabbitMQ等有足夠的知識儲備和人才儲備)低(無三方組件依賴)
高可用N/A(客戶自己兜底)99.99%(阿里云兜底)
安全通信支持SSL支持SSL
容災(zāi)2級(存儲,server緩存)3級,多了客戶端本地容災(zāi)能力
9. 擴展思考 - 為什么不把配置放到應(yīng)用自身的jar包里?
在我的博文《現(xiàn)代應(yīng)用架構(gòu)中的配置管理面臨的挑戰(zhàn)》里有長篇幅的側(cè)面論述。
如果測試、生產(chǎn)因為配置打出來的包不一樣,如何保證你的測試是有效的?
關(guān)注微服務(wù)的開發(fā)者一定拜讀過下面這本微服務(wù)圣經(jīng)在上書中的第6.7及6.8小節(jié)對于環(huán)境和配置有非常精彩的闡述,這里將原文引用在此> **6.8 服務(wù)配置**>
>服務(wù)需要一些配置。理想情況下,這些配置的工作量應(yīng)該很小,而且僅僅局限于環(huán)境間配置的差異。如果你的配置修改了很多服務(wù)的基本行為,或者不同環(huán)境之間的配置差異很大,那么你可能就只能在一套環(huán)境中發(fā)現(xiàn)某個特定的問題,這是極其痛苦的事情。>所以,如果存在不同環(huán)境之間的配置差異,應(yīng)該如何在部署流程中對其進行處理呢?一種方法是對每個環(huán)境創(chuàng)建不同的構(gòu)建物,并把配置內(nèi)建在該構(gòu)建物中。剛開始看這種方法好像挺有道理。配置已經(jīng)被內(nèi)建了,只需要簡單的部署,它應(yīng)該就能夠正常工作了,對吧?其實這是有問題的。還記得持續(xù)交付的概念嗎?我們想要創(chuàng)建一個構(gòu)建物作為候選發(fā)布版本,并使其沿著流水線向前移動,最終確認它能夠被發(fā)布到生產(chǎn)環(huán)境。想象一下,我構(gòu)建了一個Customer-Service-Test構(gòu)建物和Customer-Service-Prod構(gòu)建物。如果Customer-Service-Test構(gòu)建物通過了測試,但我真正要部署的構(gòu)建物卻是Customer-Service-Prod,又要如何驗證這個軟件最終會真正運行在生產(chǎn)環(huán)境中呢?>還有一些其他的挑戰(zhàn)。首先,創(chuàng)建這些構(gòu)建物比較耗時。其次,你需要在構(gòu)建的時候知道存在哪些環(huán)境。你要如何處理敏感的配置數(shù)據(jù)?我可不想把生產(chǎn)環(huán)境的數(shù)據(jù)庫密碼提交到源代碼中,但是如果在創(chuàng)建這些構(gòu)建物時需要的話,通常這也是難以避免的。>一個更好的方法是只創(chuàng)建一個構(gòu)建物,并將其配置單獨管理。從形式上來說,這針對的可能是每個環(huán)境一個屬性文件,或者是傳入到安裝過程中的一些參數(shù)。還有一個在應(yīng)對大量微服務(wù)時比較流行的方法是,使用專用系統(tǒng)來提供配置,第11章會詳細討論這個話題。
配置漂移
當應(yīng)用部署之后運行過程中,尤其是部署在多臺服務(wù)器上之后,如果使用開發(fā)人員或者運維人員手工維護配置文件的方式,日積月累之后,會產(chǎn)生我們所謂的"配置飄移"問題,即由于應(yīng)用以及依賴的組件的版本變更帶來的配置差異,以及不同的團隊或者人的多次不同時間點做的不同的修改會導(dǎo)致數(shù)據(jù)中心中每臺機器上的相同的應(yīng)用的配置在各臺機器上或多或少都有細微的差別,而這往往是bug和重大故障隱藏之所。
10. 總結(jié)
在本文中,我們以一個測試和生產(chǎn)連接不同的數(shù)據(jù)庫,配置不同的數(shù)據(jù)源(包括連接池)參數(shù)為例,介紹了如何將阿里云配置中心ACM與Spring Cloud一起使用,幫助你在微服務(wù)架構(gòu)中簡化你的環(huán)境配置管理。