摘要: 本文咱們就如何使用阿里雲ACM這樣的配置管理產品在Spring Cloud中替代Spring Cloud Config幫助簡化環境配置管理作一個簡單的示例,幫助你理解基於ACM來簡化微服務環境配置管理的方案,並會簡單比較一下ACM與Spring Cloud Config方案的優劣。html
點此查看原文:http://click.aliyun.com/m/41595/java
配置的環境屬性mysql
毫無疑問,在系統持續交付的過程當中,系統最終運行環境的多樣性及複雜性毫無疑問增長了咱們在配置管理工做上的負擔,有時候,甚至不誇張的說,配置就是因環境而生.web
這在Eugen Paraschiv的博文 Configuration Must Be Environment Specific裏有簡單的闡述,在個人博文《現代應用架構中的配置管理面臨的挑戰》 的容器化、調度與配置管理小節也有深刻的闡述。spring
若是要問,是什麼致使了咱們應用的構建物(artifact)在各個環境不能保持同樣,有時候Docker沒法輕易達成「Build Once, Run Anywhere!"的承諾,其答案每每就是環境配置的差別,爲幫助你理解,舉一些簡單的例子:sql
在開發環境中將logLevel設置爲DEBUG,在預發環境logLevel設置爲INFO,生產環境裏logLevel設置爲WARNING
在開發環境中使用4核8G的機器跑數據庫,而在生產中用32核96G機器跑數據庫
在平常環境執行線程池的最大線程數應該設置爲15,而生產環境上這個值應該大一點,默認設爲150
在線上環境中,中心機房,應用數據源須要鏈接A庫,而深圳機房,應用應該就近鏈接使用B庫
只有在小淘寶環境,雙向同步開關才應該關閉
此次的改動有點大,新的特性僅在線上的杭州單元把該特性開放出來,其它的單元環境先不要開放出來
本文咱們就如何使用阿里雲ACM這樣的配置管理產品在Spring Cloud中替代Spring Cloud Config幫助簡化環境配置管理作一個簡單的示例,幫助你理解基於ACM來簡化微服務環境配置管理的方案,並會簡單比較一下ACM與Spring Cloud Config方案的優劣。數據庫
場景故事
爲了幫助理解需求和場景,在平常工程實踐中,咱們通常會用用戶故事(User Story)的方式,預設一個簡單的場景,以此來作闡釋和交流,熟悉微服務歷史的兄弟必定熟悉下面這張早期的佈道圖:瀏覽器
本文中咱們就以Movie Service爲例,假設咱們須要從關係數據庫MySQL(RDS)檢索全部電影信息列表,可是在測試環境、預發和生產環境咱們須要使用不一樣的數據庫,由於只有生產庫才須要頂配的機器。這樣咱們的應用須要在不一樣的環境配置不一樣的數據源配置、鏈接池配置、數據庫安全配置等等,咱們會介紹如何基於阿里雲ACM的Namespace映射不一樣環境的能力,爲movie service在不一樣運行環境設置不一樣的數據源配置。安全
以下圖所示:服務器
建立微服務 Movie Service
新建Spring Boot Starter 微服務應用 movie service
movie service的業務邏輯很簡單,從MySQL(RDS)裏列出全部的movie列表,以下簡圖所示:
這裏咱們建立了一個標準的jpa應用(相似Spring官網的樣例工程 Accessing data with MySQL,咱們的工程結構以下圖所示:
引入JPA、MySQL、鏈接池HikariCP以及WEB依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>2.7.6</version> </dependency>
建立 MySQL(RDS) 數據庫及用戶
mysql> create database db_example; -- Create the new database mysql> create user 'springuser'@'localhost' identified by 'ThePassword'; -- Creates the user mysql> 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'小節
建立 WEB Controller
package com.alibaba.demo.microsvc.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.alibaba.demo.microsvc.dao.MovieRepository; import com.alibaba.demo.microsvc.model.Movie; @RestController public class MovieController { @Autowired MovieRepository movieRepository; @RequestMapping("/list-movies") public @ResponseBody Iterable<Movie> listMovies() { return movieRepository.findAll(); } }
在ACM中使用Namespace建立隔離的環境配置
注: 在阿里雲上使用ACM的前提是開通了該項服務,具體開通流程能夠參考文檔ACM 快速入門,開通服務並登錄以後,便可進入 ACM 控制檯 建立命名空間及配置
在ACM中建立3個環境 (dev,stage,prod)
爲 dev,stage,prod 不一樣環境分別建立配置
注意 咱們完成了什麼?
在上一步中,咱們爲相同配置項針對不一樣環境的設置了不一樣的值,例如 'spring.datasource.url'這個配置項,咱們經過設置不一樣的url來爲各環境鏈接不一樣的數據庫,而且僅在生產環境開啓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 >
同時,咱們也爲生產環境(prod)設置了更大的數據庫鏈接池和更小的鏈接超時時間
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 >
而爲了方便開發調試,咱們僅在開發環境打開了SQL Trace
dev: spring.jpa.show-sql=true
Movie Service與配置中心ACM集成
如今咱們將集成Movie Service與ACM以便從ACM中獲取對應環境的配置. 關於如何在Spring Cloud中使用ACM,具體能夠參考ACM官方文檔 開發指南 > SDK 參考 > Spring Cloud ACM
爲movie service引入ACM依賴
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-acm</artifactId> <version>1.0.1</version> </dependency>
在application.properties配置ACM鏈接信息、namespace、accessKey、secretKey等信息
spring.application.name=movie-service spring.application.group=com.alibaba.cloud.acm alibaba.acm.endpoint=acm.aliyun.com alibaba.acm.namespace=<your_namespace_id> alibaba.acm.accessKey=<your_ak> alibaba.acm.secretKey=<your_sk>
注意: 你能夠在ACM的'命名空間詳情'或者'配置的示例代碼'裏找到你的namespace_id,accessKey,secretKey等信息,以下圖所示:
在瀏覽器裏訪問Movie Service
查看ACM配置推送刷新信息
若是在movie service引入了spring-boot-starter-actuator依賴而且在application.properties設置了management.security.enabled=false,能夠經過端點 http://<>/acm 看到應用的配置消費及刷新狀況,以下圖:
也能夠在ACM控制檯上查看配置的推送軌跡、配置版本等信息,具體使用方法可參考ACM官方文檔,在此再也不贅述。
ACM與Spring Cloud Config簡單對比
擴展思考 - 爲何不把配置放到應用自身的jar包裏?
在個人博文《現代應用架構中的配置管理面臨的挑戰》 裏有長篇幅的側面論述。
若是測試、生產由於配置打出來的包不同,如何保證你的測試是有效的?
關注微服務的開發者必定拜讀過下面這本微服務聖經
在上書中的第6.7及6.8小節對於環境和配置有很是精彩的闡述,這裏將原文引用在此
6.8 服務配置
服務須要一些配置。理想狀況下,這些配置的工做量應該很小,並且僅僅侷限於環境間配置的差別。若是你的配置修改了不少服務的基本行爲,或者不一樣環境之間的配置差別很大,那麼你可能就只能在一套環境中發現某個特定的問題,這是極其痛苦的事情。
因此,若是存在不一樣環境之間的配置差別,應該如何在部署流程中對其進行處理呢?一種方法是對每一個環境建立不一樣的構建物,並把配置內建在該構建物中。剛開始看這種方法好像挺有道理。配置已經被內建了,只須要簡單的部署,它應該就可以正常工做了,對吧?其實這是有問題的。還記得持續交付的概念嗎?咱們想要建立一個構建物做爲候選發佈版本,並使其沿着流水線向前移動,最終確認它可以被髮布到生產環境。想象一下,我構建了一個Customer-Service-Test構建物和Customer-Service-Prod構建物。若是Customer-Service-Test構建物經過了測試,但我真正要部署的構建物倒是Customer-Service-Prod,又要如何驗證這個軟件最終會真正運行在生產環境中呢?
還有一些其餘的挑戰。首先,建立這些構建物比較耗時。其次,你須要在構建的時候知道存在哪些環境。你要如何處理敏感的配置數據?我可不想把生產環境的數據庫密碼提交到源代碼中,可是若是在建立這些構建物時須要的話,一般這也是難以免的。
一個更好的方法是隻建立一個構建物,並將其配置單獨管理。從形式上來講,這針對的多是每一個環境一個屬性文件,或者是傳入到安裝過程當中的一些參數。還有一個在應對大量微服務時比較流行的方法是,使用專用系統來提供配置,第11章會詳細討論這個話題。
配置漂移
當應用部署以後運行過程當中,尤爲是部署在多臺服務器上以後,若是使用開發人員或者運維人員手工維護配置文件的方式,日積月累以後,會產生咱們所謂的"配置飄移"問題,即因爲應用以及依賴的組件的版本變動帶來的配置差別,以及不一樣的團隊或者人的屢次不一樣時間點作的不一樣的修改會致使數據中心中每臺機器上的相同的應用的配置在各臺機器上或多或少都有細微的差異,而這每每是bug和重大故障隱藏之所。
總結在本文中,咱們以一個測試和生產鏈接不一樣的數據庫,配置不一樣的數據源(包括鏈接池)參數爲例,介紹瞭如何將阿里雲配置中心ACM與Spring Cloud一塊兒使用,幫助你在微服務架構中簡化你的環境配置管理。