如何在細粒度的架構中更好的微服務。這裏會從持續集成和持續交付提及。linux
1.持續集成簡介安全
CI(Continuous Integration , 持續集成)服務器
CI可以保證新提交的代碼與已有的代碼進行集成,從而保證全部人保持同步。CI服務器會檢測到網絡
代碼已提交併簽出,而後花些時間來驗證代碼是否經過編譯以及測試可否經過。架構
做爲這個流程的一部分,咱們常常會生成一些構建物(artifact)以供後續驗證使用。微服務
理想狀況下,這些構建物應該只生成一次,而後在本次提交所對應的全部部署環節中使用。工具
CI的好處不少。經過它,咱們可以獲得關於代碼質量的某種程度的快速反饋。測試
CI能夠自動化生成二進制文件。用於生成這些構建物的全部代碼都在版本的控制之下,spa
因此若是須要的話,能夠從新生成這個版本的構建物。經過CI咱們可以從已部署的構建物回溯到操作系統
相應的代碼,有些CI工具,還可使這些代碼和構建物上運行過的測試可視化。
持續集成容許咱們更快速,更容易的修改代碼。
有人任務使用了CI工具就算採用了CI這個實踐,事實上,只有工具是遠遠不夠的。
測試別人是否真正理解CI的三個問題?
你應該保證代碼可以與已有代碼進行集成
若是沒有測試,咱們只能知道集成後沒有語法錯誤,但沒法知道系統的行爲是否已經被破壞。
沒有對代碼行爲進行驗證的CI不是真正的CI。
綠色的構建意味着,咱們的修改已經安全地和已有代碼集成在了一塊兒。紅色的構建意味着,最後一次修改極可能有問題,
這時只能提交修復構建的代碼。
2.把持續集成映射到微服務
前面已經提到過,每一個微服務應該可以獨立於其餘服務進行部署。
因此如何在微服務、CI構建及源代碼三者之間,創建起合適的映射呢?
最簡單的作法,以下
圖 6-1 把全部微服務放在同一個代碼庫中,而且只有一個構建
這種方法從表面上看比其餘方法要簡單的多:由於你須要關心的代碼庫比較少,
並且從概念上來說,這種構建也比較簡單。開發者的工做也獲得了簡化:
咱們只須要提交代碼便可,若是須要同時在多個服務上工做的話,一個提交就能搞定。
在同步發佈(lock - step release)中,你須要一次性部署多個服務。
通常來說,咱們絕對應該避免這個模式,可是在項目初期是個例外。
當僅有一個團隊在全部的服務上工做時,這種模式在短期內是可接受的。
這種模式存在不少明顯的缺點。
若是我僅修改了圖6-1中用戶服務中的一行代碼,全部其餘服務都須要進行驗證和構建,
而事實上它們或許並不須要從新進行驗證和構建,因此這裏咱們花費了沒必要要的時間。
更糟糕的是,我不知道那些構建物應該被從新部署,哪些不該該。
使用這種方式的組織,每每都會退回到同時部署全部代碼的模式,而這也正是咱們很是不想看到的。
很不幸,若是這一行的修改致使構建失敗,那麼在構建獲得修復以前,其餘服務相關的代碼也沒法提交。
這種方法的一個變體是保留一個代碼庫,可是存在多個CI會分別映射到代碼庫的不一樣部分。
如圖 6-2
這種模式是個雙刃劍。
一方面它會簡化檢出/檢入的流程,可是另外一方面,它會讓你以爲同時提交對多個服務的修改
是一件簡單的事情,從而作出將多個服務耦合在一塊兒的修改。
可是相對於只有一個構建的多個服務來講,這個方式已經好不少了。
還有一種比較好的方式,每一個微服務都有本身的CI,這樣就能夠將該微服務部署到生產環境以前作一個快速的驗證。
如圖6-3
這裏的每一個微服務都有本身的代碼庫,分別於相應的CI綁定。
當對代碼庫進行修改時,能夠只運行相關的構建以及其中的測試。
每一個微服務都有本身的代碼庫和構建流程。
咱們也會使用CI構建流程,全自動話的建立出用於部署的構建物。
3. 構建流水線和持續交付
把一個構建分紅多個階段是頗有價值的。
由於有的測試運行快,涉及範圍小,有的測試運行耗時,涉及範圍廣,
若是放一塊兒,快速若是失敗,還會接着運行耗時的測試,這樣就不合理。
解決這個問題的一個方案是,將構建分解成爲多個階段,從而獲得咱們熟知的構建流水線。
在第一個階段運行快速測試,在第二個階段運行耗時測試。
構建流水線能夠很好的跟蹤軟件構建進度:每完成一個階段,就離終點更近一步。
流水線也可以可視化本次構建物的軟件質量。構建物會在整個構建的第一個環節生成,
而後會被用在整個流水線中。
CD(Continuous Delivery, 持續交付)基於上述概念,並在此之上有所發展。
CD可以檢查每次提交是否達到了部署生成環境的要求,並持續地把這些信息反饋給咱們,
它會把每次提交當成候選發佈版原本對待。
爲了更好的理解這些概念,咱們須要對從代碼提交及部署到生產環境這個過程當中,所須要經歷的流程進行建模,
並知道哪些版本的軟件時可發佈的。
UAT(User Acceptance Testing, 用戶驗收測試)流程。
經過對整個軟件上線過程進行建模,軟件質量的可視化獲得了極大改善,這能夠大大減小發布之間的間隔,
由於能夠在一個集中的地方看到構建和發佈流程,這也是能夠引入改進的一個焦點。
在微服務的世界,咱們想要保證服務之間能夠獨立於彼此進行部署,因此每一個服務都有本身獨立的CI.
不可避免的例外
全部好的規則都須要考慮例外。
當一個團隊剛開始啓動一個新項目時,尤爲是什麼都沒有的狀況下,你可能會花不少時間來識別出服務的邊界。
因此在你識別出穩定的領域以前,能夠把初始服務都放在一塊兒。
在最開始的階段,常常會發生跨服務邊界的修改,因此時常會有些內容移入或者移出某個服務。
在這個階段,把全部的服務都放在一個單獨的構建中,能夠減輕跨服務修改所帶來的代價。
固然,在這個階段你必須把全部服務打包發佈,但這應該是一個過渡步驟。
4.平臺特定的構建物
大多數技術棧都有相應的構建物類型,同時也有相關的工具來建立和安裝這些構建物。
Ruby中有gem,Java中有JAR包和WAR包,Python中有egg。
可是,從微服務部署的角度來看,在有些技術棧中只有構建物自己是不夠的。
因此爲了部署和啓動這些構建物,須要安裝和配置一些其餘軟件,再啓動這些構建物。
自動化能夠對不一樣構建物的底層部署機制進行屏蔽。
5.操做系統構建物
有一種方法能夠避免多種技術棧下的構建物所帶來的問題,那就是使用操做系統支持的構建物。
舉個例子,對基於RedHat或者CentOS的系統來講,可使用RPM;對於Ubuntu來講,可使用deb包;
對於Windows來講,可使用MSI。
使用OS特定構建物的好處是,在作部署時不須要考慮底層使用的是什麼技術。只須要簡單使用內置的工具就能夠完成軟件的安裝。
OS包管理工具,能夠幫你完成不少本來須要使用Chef或者Puppet來完成的工做。
其缺點是,剛開始編寫構建腳本的過程可能會比較困難。
固然,還有另外一個缺點,即若是你須要部署到多個操做系統的話,維護不一樣版本構建物的開銷就會很大。
但若是軟件時部署在你可控的機器上,那麼建議,儘可能減小須要維護的操做系統的數量,最好只維護一種。
它能夠大大減小不一樣機器之間可能存在的不一樣之處,並減少部署和維護的工做量。
特別是若是你在linux上工做,並且採用多種技術棧來部署微服務,那麼這種方法就很合適。
6.定製化鏡像
使用相似Puppet、Chef及Ansible這些自動化配置管理工具的一個問題是,須要花費大量時間在機器上運行這些腳本。
什麼是藍綠部署?
藍綠部署容許咱們在老版本服務不下線的同時,去部署新版本的服務。能夠減小在部署時,服務中止的時間增長。
一種減小啓動時間的方法是建立一個虛擬機鏡像,其中包含一些經常使用的依賴。
如今你能夠把公共的工具安裝在鏡像上,而後在部署軟件時,只須要根據該鏡像建立一個實例,
以後在其上安裝最新的服務版本便可。
你只須要構建一次鏡像,而後根據這些鏡像啓動虛擬機,不須要再花費時間來安裝相應的依賴,
由於它們已經在鏡像中安裝好了,這樣就能夠節省不少時間。若是你的核心依賴沒有改變,
那麼新版本的服務就能夠繼續使用相同的基礎鏡像。
這個方法也有些缺點。
首先,構建鏡像會花費大量的時間。
其次,產生的鏡像可能會很大。例如,當你建立VMWare鏡像時,在網絡上傳送一個20GB的鏡像文件會怎麼樣。
因爲歷史緣由,構建不一樣平臺上的鏡像所需的工具是不同的。
6.1 將鏡像做爲構建物
我們能夠把服務自己也包含在鏡像中,這樣就把鏡像變成了構建物。
就像使用OS特定軟件包那樣,能夠認爲這些VM鏡像時對不一樣技術棧的一層抽象。
咱們不須要關心運行在鏡像中的服務,所使用的語言是Ruby仍是Java,最終構建物是gem仍是JAR包,
咱們惟一須要關心的就是它可否工做。
這個簡潔的方法有助於咱們實現另外一個部署概念:不可變服務器。
6.2 不可變服務器
經過把配置都存到版本控制中,咱們能夠自動化重建服務,甚至重建整個環境。
可是若是部署完成後,有人登錄到機器上修改了一些東西呢?
這就會致使機器上的實際配置和源代碼管理中的配置再也不一致,這個問題叫作配置漂移。
爲了不這個問題,能夠禁止對任何運行的服務器作手動修改。
相反,不管修改多麼小,都須要通過構建流水線來建立新的機器。
7.環境