乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      阿里技術(shù)專家:持續(xù)交付與微服務(wù)背后的實(shí)踐邏輯 – 運(yùn)維派

       quasiceo 2016-07-25

      阿里技術(shù)專家:持續(xù)交付與微服務(wù)背后的實(shí)踐邏輯

      發(fā)表在 運(yùn)維經(jīng)驗(yàn)

      崔力強(qiáng)

      崔力強(qiáng)

      阿里巴巴技術(shù)專家

      • 《微服務(wù)設(shè)計(jì)》中文譯者之一;曾在ThoughtWorks任職軟件交付和敏捷顧問;
      • 對(duì)持續(xù)集成、自動(dòng)化測(cè)試有豐富經(jīng)驗(yàn);目前專注于持續(xù)交付SaaS產(chǎn)品的開發(fā),提供精益需求管理、軟件設(shè)計(jì)、敏捷轉(zhuǎn)型相關(guān)咨詢服務(wù)。

      前言

      大家好,我是崔力強(qiáng)。目前在阿里巴巴任職。負(fù)責(zé)一款持續(xù)交付領(lǐng)域的SaaS產(chǎn)品的開發(fā)。非常高興能夠和大家分享持續(xù)交付和微服務(wù)的話題。

      本次分享的重點(diǎn)是持續(xù)交付。也會(huì)提到一些微服務(wù)的概念,以及持續(xù)交付和微服務(wù)之間的關(guān)系。今天會(huì)涉及的一些實(shí)踐可能大家或多或少有所耳聞。我會(huì)著重講述這些實(shí)踐背后的邏輯,及它們之間的關(guān)系。

      先看一看提綱:

      • 持續(xù)交付的概念
      • 持續(xù)交付會(huì)遇到的問題及解決方案
      • 微服務(wù)與持續(xù)交付的相互作用

      持續(xù)交付的概念

      關(guān)于持續(xù)交付的概念。從《持續(xù)交付》這本書的副標(biāo)題可見一斑:“發(fā)布可靠軟件的系統(tǒng)方法”。可以看到這本書中講的“持續(xù)交付”主要是技術(shù)相關(guān)的實(shí)踐,雖然近年有些朋友把持續(xù)交付的概念進(jìn)行了延伸,把精益需求管理和精益創(chuàng)業(yè)也包含了進(jìn)來,不過今天我還是會(huì)按照它最初的內(nèi)涵,只講技術(shù)相關(guān)的實(shí)踐。

      這里其實(shí)有兩個(gè)概念,第一個(gè)是,怎么樣才算持續(xù)交付,也就是目標(biāo);第二個(gè)是,如何做到持續(xù)交付,也就是一些技術(shù)實(shí)踐。

      為了了解“怎么樣才算持續(xù)交付”,讓我們先解剖一下軟件開發(fā)的過程。

      針對(duì)單個(gè)需求來說,我們會(huì)先進(jìn)行需求分析、細(xì)化。然后開發(fā)和測(cè)試。部署時(shí),需要拷貝一些文件到一些機(jī)器,運(yùn)行一些腳本,有時(shí)候還需要改一些配置文件或者做一些數(shù)據(jù)遷移等。

      持續(xù)交付

      然而在實(shí)際的項(xiàng)目中,肯定不會(huì)只有一個(gè)需求。需求會(huì)源源不斷地輸入到開發(fā)團(tuán)隊(duì)。下面是一個(gè)開發(fā)團(tuán)隊(duì)隨著時(shí)間進(jìn)行需求開發(fā)的示意圖。藍(lán)色的條是開發(fā)某個(gè)功能的開始時(shí)間和結(jié)束時(shí)間點(diǎn)。有的需求占用時(shí)間長(zhǎng),有的需求占用時(shí)間短。

      微服務(wù)

      在每個(gè)功能的完成時(shí)刻,對(duì)于業(yè)務(wù)方來說,都可能是一個(gè)可以發(fā)布的狀態(tài)(也有可能不是,比如業(yè)務(wù)方認(rèn)為相關(guān)的幾個(gè)需求必須都做完了才能一起上,或者需要等到某個(gè)特定的時(shí)間點(diǎn)才能上)。那么如果立馬就能夠進(jìn)行一次發(fā)布,并且能夠快速并且安全的完成這次發(fā)布,則能夠?qū)I(yè)務(wù)的發(fā)展具有非常積極的作用。也就是在下圖的這些時(shí)刻。

      持續(xù)交付

      這些時(shí)刻,不一定每個(gè)都需要發(fā)布。但作為開發(fā)團(tuán)隊(duì),要給業(yè)務(wù)方足夠的靈活度。所以持續(xù)交付的目標(biāo),并不是每次提交都進(jìn)行發(fā)布,而是每次提交都是可發(fā)布的狀態(tài)。這就回答了“怎么樣才算持續(xù)交付”這個(gè)問題。再換一種方式來說,持續(xù)交付是對(duì)業(yè)務(wù)方友好的一種,開發(fā)團(tuán)隊(duì)的開發(fā)節(jié)奏。

      接下來就要討論使用什么樣的技術(shù)實(shí)踐來達(dá)到這種開發(fā)節(jié)奏。為了討論具體的技術(shù)實(shí)踐,首先來看看在軟件開發(fā)中有什么因素會(huì)阻礙我們達(dá)到這種節(jié)奏。

      持續(xù)交付會(huì)遇到的問題及解決方案

      測(cè)試

      第一個(gè)問題是:上線前總還是要做測(cè)試的吧,至少做一遍重要功能的回歸測(cè)試(手工回歸本身其實(shí)也是有章可循的,推薦我同事的一篇文章:https://yq.aliyun.com/articles/6898)。隨著一個(gè)系統(tǒng)上的功能越來越多,每次上線前需要測(cè)試的東西就越來越多。慢慢的,發(fā)布就慢下來了。我曾經(jīng)工作過的一個(gè)系統(tǒng),上面承載了三塊業(yè)務(wù),有將近40多個(gè)人在上面工作。每次發(fā)布前都要先進(jìn)行幾天的回歸測(cè)試,順利的話,從確定要發(fā)布的版本到驗(yàn)證完該版本,確定可以發(fā)布,也要差不多一周的時(shí)間。

      另一個(gè)我工作過的項(xiàng)目規(guī)模要小一些,做一次發(fā)布也需要一天的時(shí)間來回歸,通常都會(huì)發(fā)現(xiàn)一些問題。順利的話,可以在當(dāng)天把所有的問題修復(fù)掉,進(jìn)行發(fā)布。不過因?yàn)閎ug沒修完而不能當(dāng)天發(fā)布,拖到第二天的這種情況也時(shí)常發(fā)生。

      甚至有一次,到了晚上九點(diǎn)多的時(shí)候還沒有修完bug,但當(dāng)時(shí)大家都憋著一口氣,硬是要發(fā),結(jié)果發(fā)到了晚上一點(diǎn)多。

      因?yàn)槌杀靖?,所以不敢做的太頻繁;做的不頻繁的話,就會(huì)在發(fā)布中積累更多的功能,從而進(jìn)一步增加出問題的可能性,從而形成一個(gè)惡性循環(huán)。

      作為一個(gè)妥協(xié),人們不得不使用瀑布或者迭代內(nèi)小瀑布的開發(fā)模式。

      迭代內(nèi)小瀑布

      把開發(fā)的周期分解為一個(gè)一個(gè)的迭代,比如兩周到四周的時(shí)間。在迭代開始前,保證該迭代內(nèi)計(jì)劃的需求分析完畢。然后在迭代內(nèi)部開發(fā)。順利的話,會(huì)在接近迭代末尾時(shí)完成迭代內(nèi)計(jì)劃的所有任務(wù),然后拉一個(gè)發(fā)布分支出來,開始測(cè)試,然后發(fā)布。

      做出上述妥協(xié)的直接原因就是“測(cè)試和部署”花費(fèi)的時(shí)間過長(zhǎng)。如果只花費(fèi)一個(gè)人一個(gè)小時(shí)就能夠完成回歸和發(fā)布,那顯然團(tuán)隊(duì)就更愿意去頻繁的發(fā)布。

      一個(gè)行之有效的方法就是進(jìn)行自動(dòng)化測(cè)試。

      測(cè)試金字塔

      自動(dòng)化測(cè)試大致可以分為幾種:?jiǎn)卧獪y(cè)試、API測(cè)試、驗(yàn)收測(cè)試/功能測(cè)試/端到端測(cè)試。在不同的技術(shù)棧下,分類可能會(huì)略有不同的,但本質(zhì)上來講是類似的。不同層次的測(cè)試有自己的側(cè)重點(diǎn),組要組合使用來達(dá)到一個(gè)比較好的效果。如上圖所示:

      這里以Java Spring項(xiàng)目為例來列舉不同層次的測(cè)試工具:?jiǎn)卧獪y(cè)試使用Junit;集成測(cè)試使用Spring Test + Junit;功能測(cè)試使用cucumber+ capybara+selinium或者robotframework+ selinium。

      如果使用了前端框架,比如Angular、ReactJS等,它們本身也提供了相應(yīng)的測(cè)試框架。

      底層的單元測(cè)試,測(cè)試的范圍較小,一般只涉及一個(gè)或者幾個(gè)類,不會(huì)調(diào)用網(wǎng)絡(luò)或者數(shù)據(jù)庫(kù)。所以編寫和運(yùn)行起來都比較快。在這個(gè)級(jí)別應(yīng)該覆蓋盡量多的分支和邏輯。這個(gè)級(jí)別的測(cè)試能夠達(dá)到比較高的覆蓋率,所以在它的保護(hù)下,可以放心大膽的做重構(gòu)或者添加新代碼,只需要花上幾秒鐘的時(shí)間運(yùn)行一遍單元測(cè)試,就能夠知道這次修改是否引入了問題。前陣子做了很長(zhǎng)時(shí)間的nodejs開發(fā),單元測(cè)試對(duì)這種弱類型的語言尤其重要。因?yàn)橄褡兞课炊x,傳參數(shù)的個(gè)數(shù)錯(cuò)誤等很低級(jí)的問題IDE都無法給出有效的提示。

      因?yàn)閱卧獪y(cè)試需要隔離被測(cè)類和系統(tǒng)的其它代碼,所以需要有一些測(cè)試替身來代替真實(shí)的類。有很多工具可以做這樣的事情,比如Java中的mockito。

      單元測(cè)試與測(cè)試替身

      如上圖所示,它會(huì)創(chuàng)造一個(gè)假的ClassB的實(shí)例出來,并傳給ClassA的實(shí)例。然后對(duì)ClassB的行為做出一些假設(shè),在此假設(shè)的基礎(chǔ)上對(duì)ClassA的行為進(jìn)行測(cè)試。

      但是一個(gè)類或者幾個(gè)類的正確,并不能讓你對(duì)系統(tǒng)的正確性有足夠的信心。因?yàn)閱卧獪y(cè)試中充滿了對(duì)其它類行為的假設(shè)。所以一旦這個(gè)假設(shè)錯(cuò)誤,就會(huì)出現(xiàn)測(cè)試依然能通過,但整個(gè)系統(tǒng)的行為已經(jīng)錯(cuò)了的尷尬情況。所以我們還需要覆蓋面更大的集成測(cè)試。這種測(cè)試在服務(wù)內(nèi)部不使用任何的測(cè)試替身。但對(duì)外部的服務(wù)進(jìn)行打樁。對(duì)基于HTTP的服務(wù)進(jìn)行打樁的工具包括moco(https://github.com/dreamhead/moco)和pact(https://github.com/realestate-com-au/pact,其實(shí)pact能做的事情不止打樁,更多的是做“契約測(cè)試”)。這種測(cè)試更真實(shí),但運(yùn)行起來會(huì)慢,所以這個(gè)層面的測(cè)試主要保證的是連通性。不需要100%的覆蓋率。

      集成測(cè)試

      集成測(cè)試覆蓋面很大,但它仍然是白盒測(cè)試,因?yàn)樗苯诱{(diào)用了函數(shù)(比如上頁(yè)的controller)。如果這個(gè)服務(wù)只提供API,那么這種測(cè)試就夠了。但如果這個(gè)服務(wù)是提供頁(yè)面的,也就是一個(gè)web應(yīng)用,那么就還需要一層直接操作網(wǎng)頁(yè)來進(jìn)行基于用戶行為的測(cè)試,我們一般稱之為驗(yàn)收測(cè)試,或者功能測(cè)試。上面列舉的cucumber和robotframework是非常流行的兩款功能測(cè)試工具。他們是通用的測(cè)試框架,與具體的被測(cè)系統(tǒng)是無關(guān)的。我也另一位前同事都對(duì)這兩種工具比較熟悉,并且寫了文章作總結(jié):http://www./cn/articles/cucumber-robotframework-comparison

      如果要測(cè)試web系統(tǒng)的話,就需要能夠驅(qū)動(dòng)網(wǎng)頁(yè)的驅(qū)動(dòng)程序?,F(xiàn)在非常主流的驅(qū)動(dòng)是selinium(https://github.com/SeleniumHQ/selenium

      ),當(dāng)然我更喜歡的是在其上包了一層的capybara(https://github.com/jnicklas/capybara),它是用ruby編寫的,封裝的API更好用。

      建議至少對(duì)核心的流程編寫功能測(cè)試,以保證上線不要出現(xiàn)嚴(yán)重的故障。前段時(shí)間我們的功能測(cè)試發(fā)現(xiàn)了一個(gè)bug。這個(gè)bug對(duì)于老用戶都不會(huì)有問題,但是用戶首次登錄就會(huì)500。而用戶首次登錄的場(chǎng)景恰恰是平時(shí)自測(cè)的時(shí)候很容易忽略的,因?yàn)闇?zhǔn)備數(shù)據(jù)還是有點(diǎn)麻煩的。當(dāng)時(shí)發(fā)現(xiàn)這個(gè)問題的時(shí)候大家并沒有什么感覺,因?yàn)橐呀?jīng)習(xí)慣有測(cè)試保護(hù)的軟件了。但如果跳出來想想,這個(gè)問題要是在一周后的“迭代末尾”才發(fā)現(xiàn),會(huì)多么的打擊氣勢(shì)。如果上線才發(fā)現(xiàn),那么產(chǎn)品的新用戶增長(zhǎng)量一定會(huì)直線下降。

      端到端測(cè)試其實(shí)也就是使用功能測(cè)試的工具在更大的范圍進(jìn)行測(cè)試,也就是包含所有的服務(wù)。

      下面總結(jié)一下各個(gè)層次測(cè)試的特點(diǎn)。

      測(cè)試金字塔

      回歸測(cè)試是迭代開發(fā)中必不可少的一個(gè)步驟。我們能做的就是通過自動(dòng)化測(cè)試去盡量減小這個(gè)時(shí)間。

      很多人對(duì)于測(cè)試有一些顧慮,覺得會(huì)花費(fèi)很多時(shí)間。而且當(dāng)代碼結(jié)構(gòu)調(diào)整時(shí),測(cè)試也要跟著改。

      我的看法是,測(cè)試代碼也是代碼,維護(hù)測(cè)試代碼的代價(jià)跟測(cè)試代碼本身的質(zhì)量是直接相關(guān)的。所以對(duì)測(cè)試代碼也需要及時(shí)重構(gòu),提高可維護(hù)和可重用性。具體一點(diǎn)對(duì)于測(cè)試來說,提高可維護(hù)性和看重用性,無非就是要在數(shù)據(jù)準(zhǔn)備、斷言工具方面去抽取一些庫(kù)。比如Ruby的factory girl就是一個(gè)極好的基于ActiveRecord的數(shù)據(jù)準(zhǔn)備庫(kù)。有了它,寫測(cè)試的代價(jià)大大降低。那如果你不用Ruby怎么辦,那只好自己實(shí)現(xiàn)一個(gè)其它語言版本的factory girl嘍。我上一個(gè)項(xiàng)目用的是nodejs,就寫了一個(gè)nodejs版本的factory girl。

      而單元測(cè)試能夠給你帶來的好處不僅僅是回歸這么簡(jiǎn)單。有了完備的單元測(cè)試,你才有信心,有動(dòng)力去做一些重構(gòu)。只要測(cè)試通過,我就知道我的重構(gòu)是正確的,你才敢不斷的去重構(gòu),優(yōu)化代碼,才能使得代碼更易維護(hù)。所以可以說寫測(cè)試是保證你代碼可維護(hù)性的必由之路。不要考慮寫不寫測(cè)試,而是考慮,如何低成本的寫測(cè)試。

      當(dāng)我開發(fā)新功能時(shí)候,編寫好測(cè)試運(yùn)行一下,就知道功能正確與否,這樣就不用把服務(wù)器啟起來,減小反饋的周期。在這個(gè)場(chǎng)景下,它會(huì)直接節(jié)省你的時(shí)間,雖然你寫了更多的代碼。

      關(guān)于代碼改動(dòng),測(cè)試也要跟著改的問題,我想說兩點(diǎn):

      第一,項(xiàng)目的初期,一般代碼的架構(gòu)會(huì)不太穩(wěn)定,那么在不影響運(yùn)行和編寫速度的前提下,盡量測(cè)試的范圍大一些,也就是包含的類多一些。這樣改動(dòng)一個(gè)類,引起測(cè)試變化的可能性就會(huì)降低,并且可以在測(cè)試的保護(hù)下放心大膽的做架構(gòu)調(diào)整。

      第二,要善用IDE幫你做改動(dòng)。測(cè)試代碼也是代碼,當(dāng)你修改一個(gè)函數(shù)簽名時(shí),IDE會(huì)幫你把所有的調(diào)用處都改掉,包括測(cè)試代碼。所以IDE用得好,修改代碼也不是那么痛苦的事情。

      那么有了這些測(cè)試之后,我應(yīng)該什么時(shí)候運(yùn)行它們呢。是迭代結(jié)束時(shí)嗎?不!我們應(yīng)該在每次提交時(shí)都完整的運(yùn)行一遍這些測(cè)試。這樣一旦出了問題我就可以第一時(shí)間知道。這就是持續(xù)集成的基本概念。

      持續(xù)集成

      每次提交代碼觸發(fā)編譯、測(cè)試、靜態(tài)檢查、打包歸檔、然后再運(yùn)行驗(yàn)收測(cè)試(AT),然后再部署到類生產(chǎn)環(huán)境進(jìn)行性能測(cè)試,再部署到端到端測(cè)試環(huán)境運(yùn)行端到端測(cè)試。并且把每一步的結(jié)果反饋給開發(fā)團(tuán)隊(duì)。

      我們把上圖稱為持續(xù)集成流水線??梢允褂煤芏喙ぞ邅韺?shí)現(xiàn),比如最常見的開源工具Jenkins?;蛘呶夷壳八?fù)責(zé)產(chǎn)品:crp.aliyun.com。

      關(guān)于更多的持續(xù)集成的實(shí)踐和流水線設(shè)計(jì),因?yàn)閮?nèi)容很多,這里只討論幾個(gè)要點(diǎn)。

      1. 代碼倉(cāng)庫(kù): 每個(gè)開發(fā)要及時(shí)的提交代碼,不要把代碼長(zhǎng)期留在本地,一天至少提交一次。不要開長(zhǎng)時(shí)間的分支。越頻繁的提交代碼,就能得到越及時(shí)的反饋。
      2. 構(gòu)建腳本: 構(gòu)建腳本必須要放在代碼庫(kù),切忌把它們放在只要少數(shù)人能夠訪問的神秘的地方。
      3. 軟件包服務(wù)器: 每次構(gòu)建的產(chǎn)出物,必須要按照一定的版本規(guī)則存放起來,以供后續(xù)的步驟使用,比如做測(cè)試和部署。軟件包的形式是多種多樣的,比如Java的jar、war,Ruby的gem,操作系統(tǒng)的rpm等等。甚至是最通用的tar,也可以成為你的軟件包形態(tài)。
      4. 分stage: 大家可以看到上面這個(gè)流水線是分stage的,每個(gè)stage是順序執(zhí)行的。越往前的 stage檢測(cè)越快,并越簡(jiǎn)單。越往后的stage檢測(cè)越耗時(shí)。任何一個(gè)stage運(yùn)行失敗,后續(xù)的stage都不會(huì)再繼續(xù)進(jìn)行,本次流水線的進(jìn)行就失敗了。所以流水線運(yùn)行到越往后的階段,我們對(duì)于本次構(gòu)建是可以上線的信心就越強(qiáng)。

      我們使用自動(dòng)化測(cè)試加持續(xù)集成解決了第一個(gè)發(fā)布前回歸測(cè)試耗時(shí)的問題。

      持續(xù)集成

      第二個(gè)問題就是:“別人的功能還沒做完”。假設(shè)現(xiàn)在團(tuán)隊(duì)正在進(jìn)行單分支開發(fā)(也就是說所有的功能都提交在一個(gè)分支上,不會(huì)為了一個(gè)功能單獨(dú) 開出一個(gè)長(zhǎng)期存在分支)。就拿圖中紅色線這個(gè)時(shí)間點(diǎn)來講,第三個(gè)需求完成了,業(yè)務(wù)人員也認(rèn)為可以做一次發(fā)布。但是同時(shí)還有另外三個(gè)需求正在開發(fā)。如果做發(fā)布的話,就會(huì)把做了一半的東西也給發(fā)上去。這是不可以接受的。

      解決這個(gè)問題有兩個(gè)思路:那就是功能分支和功能開關(guān)。

      微服務(wù)

      先看看功能分支:

      每開一個(gè)新功能,就開一個(gè)分支。這個(gè)分支存活的時(shí)間通常是“周”這個(gè)數(shù)量級(jí)的。哪個(gè)功能開發(fā)完成了就合入到主干,進(jìn)行一次發(fā)布。這樣,其它未完成的功能還沒有合入到主干,就不會(huì)造成影響。但功能分支有很多的問題,最嚴(yán)重的一個(gè)問題是:它和持續(xù)集成的理念是沖突的。持續(xù)集成是希望你每次提交都能夠放在一起進(jìn)行驗(yàn)證。但使用了分支的話,就只能在合并的時(shí)刻,才能真正把所有的東西放在一起進(jìn)行驗(yàn)證。而這時(shí)發(fā)現(xiàn)的問題可能一周前已經(jīng)發(fā)生了。

      另一個(gè)方法,功能開關(guān),會(huì)給任何一個(gè)新開發(fā)的功能在代碼級(jí)別加上一個(gè)開關(guān),使得可以簡(jiǎn)單的修改一個(gè)配置就把一個(gè)功能完全隱藏掉。默認(rèn)所有的開關(guān)都是關(guān)閉的,如果一個(gè)功能做完了,想上,則修改配置,打開開關(guān),進(jìn)行一次發(fā)布即可。聽起來很理想,但事實(shí)上也需要花費(fèi)不少的代碼來把這件事情真正做好。

      關(guān)于功能分支和功能開關(guān)今天不展開細(xì)講了。有興趣的朋友可以參看我之前寫的一篇文章:http://www./cn/articles/function-switch-realize-better-continuous-implementations

      接下來我們聊一聊發(fā)布。因?yàn)槲覀兿Ml(fā)布也是快速并安全可靠的。

      發(fā)布

      發(fā)布是一件麻煩事。一次發(fā)布可能會(huì)需要部署多個(gè)應(yīng)用,每個(gè)應(yīng)用都要部署多臺(tái)機(jī)器,有時(shí)候除了改代碼之外,還需要修改配置,比如nginx配置等。大多運(yùn)維團(tuán)隊(duì)都會(huì)有一些腳本來做這些變更。但這些腳本通常都藏在某些只有運(yùn)維團(tuán)隊(duì)才知道(并有權(quán)限)的機(jī)器上,開發(fā)和業(yè)務(wù)團(tuán)隊(duì)都已經(jīng)就緒之后,還需要等待運(yùn)維團(tuán)隊(duì)抽出時(shí)間來做些變更,這就無形中增加的時(shí)間成本。還是在前面提到的那個(gè)項(xiàng)目中,作部署就是有專門的運(yùn)維團(tuán)隊(duì), 排期來對(duì)該應(yīng)用進(jìn)行部署。通常又會(huì)再多等一兩天。

      Devops

      DevOps是一種團(tuán)隊(duì)合作的模式,即開發(fā)人員自己可以按需進(jìn)行部署,不需要等待一個(gè)專門的發(fā)布團(tuán)隊(duì)的時(shí)間。DevOps其實(shí)現(xiàn)在還是沒有一個(gè)標(biāo)準(zhǔn)的翻譯,我的一個(gè)前同事將它翻譯為“開發(fā)自運(yùn)維”,我覺得還是挺貼切的。

      在這種模式下,原先的運(yùn)維團(tuán)隊(duì)?wèi)?yīng)該轉(zhuǎn)換自己的職責(zé),從負(fù)責(zé)具體業(yè)務(wù)的變更,變成基礎(chǔ)資源的提供者。比如當(dāng)開發(fā)團(tuán)隊(duì)需要一臺(tái)虛擬機(jī),或者一個(gè)Docker集群時(shí),能夠通過簡(jiǎn)單的調(diào)用API,在很快的時(shí)間得到它,而不需要繁雜冗長(zhǎng)的審批流程。運(yùn)維團(tuán)隊(duì)還可以提供有效的監(jiān)控、告警工具等,同樣把他們以基礎(chǔ)服務(wù)的形式提供給開發(fā)團(tuán)隊(duì)。就像現(xiàn)在AWS和阿里云做的事情。

      其實(shí)很多小團(tuán)隊(duì),包括我自己所在的團(tuán)隊(duì),都采用了DevOps的合作模式。但是做歸做,如何能做好呢?如何能夠保證每個(gè)開發(fā)(甚至是入職不久的開發(fā))能夠安全快速的完成一次發(fā)布呢?

      答案是自動(dòng)化加可視化。自動(dòng)化就是部署一個(gè)應(yīng)用時(shí),應(yīng)該有腳本能夠一鍵從構(gòu)建物倉(cāng)庫(kù)拉取出正確版本的構(gòu)建物,然后部署到相應(yīng)的機(jī)器(或者多臺(tái)機(jī)器)上。更重要的是這個(gè)自動(dòng)化腳本不應(yīng)該藏在一個(gè)秘密機(jī)器的角落,因?yàn)檫@樣的話, 就很難告訴團(tuán)隊(duì)成員如何去使用它們。所以應(yīng)該把它可視化,而可視化的最好的平臺(tái)就是上面提到的那個(gè)持續(xù)集成流水線,在流水線的后面再加上一個(gè)部署線上的環(huán)節(jié)。

      這樣,開發(fā)人員就能夠在一個(gè)統(tǒng)一的入口去了解從驗(yàn)證、打包,再到生產(chǎn)環(huán)境部署的的全流程。當(dāng)然我們的持續(xù)集成流水線也就順理成章的變成了持續(xù)交付流水線。

      持續(xù)交付

      在發(fā)布方面,還有一個(gè)重要的課題就是環(huán)境管理。

      環(huán)境管理

      現(xiàn)在大多的線上部署模式是:申請(qǐng)幾臺(tái)虛擬機(jī),標(biāo)明每一臺(tái)的用途,然后開始在各個(gè)虛擬機(jī)上安裝各自需要的基礎(chǔ)軟件,比如nginx、tomcat等。然后寫一個(gè)腳本進(jìn)行各個(gè)應(yīng)用程序的部署(這個(gè)腳本最終會(huì)集成到持續(xù)交付流水線中),注意這里的腳本僅僅負(fù)責(zé)應(yīng)用程序的部署,而不包含前面提到的基礎(chǔ)軟件。如果基礎(chǔ)軟件需要升級(jí),或者安裝新的基礎(chǔ)軟件,或者需要調(diào)整系統(tǒng)參數(shù),這些過程都需要手動(dòng)進(jìn)行。這種模式在大多數(shù)情況下是沒有問題的,但一旦機(jī)器出了問題,或者需要擴(kuò)容時(shí),就需要花費(fèi)大量時(shí)間來重新安裝一臺(tái)和之前那臺(tái)一模一樣的機(jī)器,再修改部署腳本把軟件部署上去。這個(gè)過程不但耗時(shí),而且非常不可靠,因?yàn)槟銢]法保證你裝出來的這臺(tái)機(jī)器就和之前的那臺(tái)一模一樣,很有可能就給未來埋下了一顆定時(shí)炸彈。

      解決這個(gè)問題的思路就是所謂的“基礎(chǔ)設(shè)施即代碼”。也就是把環(huán)境的創(chuàng)建過程使用代碼的形式描述出來,并且提交到代碼庫(kù)中。任何的環(huán)境變更都必須通過修改代碼、提交,然后總是使用代碼庫(kù)中的最新版本重新構(gòu)建環(huán)境。禁止直接在機(jī)器上進(jìn)行任何環(huán)境變更,比如裝軟件,升級(jí)軟件,該軟件配置等。這樣所有機(jī)器的狀態(tài)就是可預(yù)測(cè)的,并且是一致的。

      基礎(chǔ)設(shè)施及代碼的相關(guān)工具有很多,比如最早流行的chef和puppet,到后來的Ansible。這里我們就拿Ansible為例子講一講環(huán)境管理和部署自動(dòng)化。

      Ansible是一個(gè)Agent Less的通用部署及環(huán)境管理工具。也就是說不需要在目標(biāo)機(jī)器上預(yù)先安裝任何客戶端軟件,這點(diǎn)與chef有所差別。它依賴的就是簡(jiǎn)單的ssh命令。你說這跟我直接寫shell或者ruby腳本ssh到目標(biāo)機(jī)器,然后執(zhí)行一些腳本有什么差別呢?

      差別當(dāng)然是有的,它會(huì)在以下幾個(gè)方面給你提供便利:

      第一:Inventory管理。Inventory,即你要管理的那些機(jī)器。使用Ansible,你可以在一個(gè)集中的文件中,以結(jié)構(gòu)化的形式列出所有你需要管理的機(jī)器,及如何登陸它們,也就是ssh的用戶名和密碼 等信息。不同機(jī)器的用途不同,比如這三臺(tái)是web服務(wù)器,那兩臺(tái)是搜索引擎等。那么Ansible也提供了對(duì)機(jī)器進(jìn)行分組的能力。有了這些分組后,就可以很容易的在命令行中指明我這次要對(duì)那些機(jī)器做變更。并且Ansible會(huì)自動(dòng)地對(duì)所有這些機(jī)器做變更,省去了自己做循環(huán)的工作。

      下面看幾個(gè)Ansible官方的Inventory例子:

      Inventory

      第二個(gè)重要的點(diǎn)叫做變更操作的冪等性。舉個(gè)例子,某一次對(duì)機(jī)器的變更是在~/.bash_profile中添加一行對(duì)JAVA_HOME的配置:“export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_71.jdk/Contents/Home/”。那么我可以寫一個(gè)shell腳本完成這件事情:“echo export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_71.jdk/Contents/Home/ >> ~/.bash_profile”。但是如果下次我的shell腳本里面多了安裝apache web server的代碼。我就需要把這整個(gè)腳本再對(duì)目標(biāo)機(jī)器運(yùn)行一次。那么就會(huì)出現(xiàn)~/.bash_profile中出現(xiàn)兩行JAVA_HOME的配置的問題。雖然不至于引入錯(cuò)誤,但也是很沒有必要的操作。

      所謂冪等性,就是同一個(gè)腳本對(duì)同一臺(tái)機(jī)器運(yùn)行多次后,機(jī)器的狀態(tài)應(yīng)該都是一致的。Ansible中模塊(module)的概念就覆蓋了“冪等性”這個(gè)概念。所謂模塊是預(yù)先寫好的一些庫(kù),然后可以在Ansible的腳本中進(jìn)行調(diào)用。上面的在一個(gè)文件中添加一行的操作就可以使用“l(fā)ineinfile”這個(gè)module來做。在Ansible腳本中的寫法是:“l(fā)ineinfile: dest=~/.bash_profile line=/Library/Java/JavaVirtualMachines/jdk1.8.0_71.jdk/Contents/Home/”。再比如還有一個(gè)module,叫做service,Ansible腳本中對(duì)于service的一個(gè)調(diào)用示例是這樣的: “service: name=httpd state=started”。這個(gè)描述的含義就是:“保證名為httpd的service是started狀態(tài)”。所以你可以想象到它的具體實(shí)現(xiàn)就是先檢查下httpd這個(gè)service的狀態(tài),如果已經(jīng)是started的就什么都不做,否則就啟動(dòng)它。

      這種冪等性在配置管理方面是非常有用的,這樣我就可以放心的運(yùn)行這些腳本,知道最終一定可以得到某個(gè)一致的狀態(tài)。而且可以節(jié)省運(yùn)行這些腳本的時(shí)間,比如發(fā)現(xiàn)JDK已經(jīng)裝好了,就不需要再裝一遍。

      上面提到的Ansible編寫的腳本被稱作Playbook,下面是幾個(gè)playbook的例子:

      這個(gè)playbook是一個(gè)完整的例子,其中包括了我要部署那些機(jī)器(hosts)。是用什么賬戶登錄(root),運(yùn)行哪些任務(wù)(tasks)等等。task中的name只是描述信息。

      Playbook

      但是遺憾的是這種冪等性是不能完全保證的,有的module可以保證,比如上面提到的service和lineinfile。但有些是不行的,比如command module,它做的事情就是運(yùn)行一條命令。Ansible無法判斷這條命令是否執(zhí)行過。

      所以在使用Ansible的過程中需要盡量使用能夠保證冪等性的module。這樣才能保證所有的機(jī)器在運(yùn)行一段時(shí)間之后配置是相同的,避免“配置漂移”。當(dāng)然還有一個(gè)避免配置漂移的方法就是每次都重新申請(qǐng)一臺(tái)新的機(jī)器,然后對(duì)著它運(yùn)行一遍這些腳本。這也是可行的,我們后面對(duì)此進(jìn)行討論。

      Ansible作為一個(gè)完備的工具,在錯(cuò)誤處理,回滾,調(diào)試等方面也都提供了便利的支持。詳情大家可以參看Ansible的官網(wǎng)。上面有關(guān)于Ansible本身的介紹,和一系列的擴(kuò)展module。

      最后再看一看Ansible整體的結(jié)構(gòu):

      Ansible部署管理

      前面我們提到了一種模式,即每次都新做出來一臺(tái)機(jī)器,然后把這些Ansible(或者其它什么工具)腳本對(duì)著這些干凈的機(jī)器運(yùn)行一遍。最后再把特定版本的軟件部署上去。也就是說每次部署都會(huì)把原來的虛擬機(jī)實(shí)例干掉,再重新生成一臺(tái)。在實(shí)際場(chǎng)景中,同一個(gè)應(yīng)用會(huì)存在多個(gè)實(shí)例,我們沒有必要對(duì)每臺(tái)機(jī)器都這么做,只需要把一臺(tái)機(jī)器使用Ansible裝好之后,再打個(gè)鏡像,然后通過這個(gè)鏡像啟動(dòng)多臺(tái)實(shí)例。

      這種模式能夠帶來的好處是顯而易見的,不但保證了環(huán)境的一致性,且擴(kuò)容非常容易,只需要把同一個(gè)鏡像再多啟動(dòng)幾個(gè)實(shí)例,然后掛接到相應(yīng)的負(fù)載均衡中即可。而且永遠(yuǎn)不需要害怕線上機(jī)器crash掉。按照鏡像再啟動(dòng)一個(gè)就可以了。但這種模式帶來的問題也是顯而易見的,首先打虛擬機(jī)鏡像的時(shí)間是很長(zhǎng)的。其次這種做法就要求服務(wù)器是沒有狀態(tài)的,也就是不能在硬盤上存文件,寫log。還好現(xiàn)在的云服務(wù)提供商(AWS,阿里云等)都有相應(yīng)的產(chǎn)品來解決這些問題。

      對(duì)于上傳的附件和圖片等文件來說,有兩種方式:

      1. 用戶上傳的文件直接轉(zhuǎn)存第三方云存儲(chǔ)。
      2. 把NAS等第三方存儲(chǔ)掛載到實(shí)例的本地目錄。

      這兩種方法能夠在一定程度上解決問題,但終究不是本地磁盤,在讀寫速度和并發(fā)寫的處理等方面都會(huì)多多少少存在一定問題。所以只能適用于對(duì)這些指標(biāo)要求不高的場(chǎng)景。

      對(duì)于log來說,也有兩種方式:

      1. 用戶產(chǎn)生的log不要寫到本地,而是直接推送到一個(gè)中央log處理服務(wù)。
      2. log還是寫在本地,但是本地會(huì)有一個(gè)收集log的agent,不斷的讀取log內(nèi)容,并發(fā)送到集中的log服務(wù)。比如阿里云的SLS就是這么工作的。

      使用上述的方式時(shí),所有的代碼,軟件和配置的變更都需要走這么一個(gè)流程:各種各樣的自動(dòng)化測(cè)試、鏡像構(gòu)建,實(shí)例化鏡像啟動(dòng)服務(wù)。所有的變更,不管再小,都會(huì)走這樣的流程,而不會(huì)直接更改在實(shí)例機(jī)器上。所以實(shí)例機(jī)器就是不可變的了。這就是所謂“不可變服務(wù)器”的概念。

      但這個(gè)過程是比較漫長(zhǎng)的。所以對(duì)于緊急發(fā)布之類的場(chǎng)景,是很讓人捉急的。而Docker技術(shù)的出現(xiàn)就很好的解決了這個(gè)問題。Docker基于Linux Container(LXC)技術(shù),能夠做到輕量級(jí)的虛擬化。

      Docker采用了分層的文件系統(tǒng),所以如果我在包含Java的鏡像的基礎(chǔ)上打一個(gè)包含Tomcat的鏡像,只需要?jiǎng)?chuàng)建出一層只包含Tomcat的鏡像,然后和原先的包含Java的鏡像疊加在一起,就可以形成一個(gè)完整的可運(yùn)行的鏡像。

      在這種分層的鏡像機(jī)制下,如果每次只修改最上面一層鏡像,則構(gòu)建的速度是很快的。而最上面一層通常就是添加應(yīng)用程序。以Java Web程序?yàn)槔琂ava和Tomcat的鏡像可以作為一個(gè) 基礎(chǔ)鏡像。然后每次生成的WAR包通過Dockerfile(用于構(gòu)建Docker鏡像的描述文件)中的ADD指令添加到新的鏡像層中即可。

      Docker鏡像as交付物

      舉個(gè)例子:這里有一個(gè)Java的web應(yīng)用,通過運(yùn)行“./gradlew war”的命令會(huì)在本地目錄下生成’build/libs/bookstore.war’。然后編寫如上圖的Dockerfile,它會(huì)把本地生成的war包ADD到Docker鏡像中。運(yùn)行’docker build . -t bookstore: <版本號(hào)>’就可以生成一個(gè)鏡像。

      分層鏡像

      通過Docker的history命令可以看到1.5和1.3兩個(gè)版本的最上面一層是不同的,但它們的基礎(chǔ)鏡像層都是“25e98610c7d0”。最上面一層的大小是6.106M,也就是比一個(gè)war包稍微大了一點(diǎn)點(diǎn)。

      綜上所述,可以看到相比使用虛擬機(jī)鏡像作為不可變服務(wù)器,使用Docker鏡像有如下優(yōu)勢(shì):

      1. 構(gòu)建時(shí)間短。
      2. 使用空間小。

      而前面提到的那些使用虛擬機(jī)作為不可變服務(wù)器時(shí),需要解決的問題(本地文件,log等),使用Docker同樣會(huì)面對(duì)。而解決方法也是類似的。

      既然Docker這么方便,那么使用虛擬機(jī)作為不可變服務(wù)器是否還有價(jià)值呢?這個(gè)其實(shí)主要還是看相關(guān)工具,及其成熟度。比如AWS和阿里云都提供了使用配置文件來編排虛擬機(jī)資源的能力,而且可以設(shè)置一些觸發(fā)器來自動(dòng)以虛擬機(jī)為單位對(duì)應(yīng)用程序進(jìn)行擴(kuò)展(scale)。這種模式已經(jīng)非常成熟了。

      而對(duì)于容器而言,這些云提供商也開始逐漸推出容器服務(wù),把上述的那些對(duì)虛擬機(jī)的操作也引入到了容器的領(lǐng)域。今年五月份阿里云的容器服務(wù)就已經(jīng)商用化了。它提供了集群管理的能力,也可以設(shè)置觸發(fā)器對(duì)某一個(gè)應(yīng)用進(jìn)行擴(kuò)容和縮容。關(guān)于阿里云容器服務(wù)提供的更多能力,因?yàn)闀r(shí)間關(guān)系,就不再贅述,有興趣的朋友可以在這里做詳細(xì)了解:https://yq.aliyun.com/teams/11。

      Ansbile、虛擬機(jī)不可變服務(wù)器、Docker Image都是很有用的技術(shù),但針對(duì)每個(gè)具體的技術(shù),還是需要仔細(xì)評(píng)估你的應(yīng)用是否能夠克服或者容忍前文提出的相應(yīng)的限制和問題。并且需要看看這些技術(shù)能給你的業(yè)務(wù)帶來多大的好處。

      最重要的一點(diǎn)就是無論你在部署階段使用的是何種技術(shù),使用一條完整的從代碼提交到最終部署上線的持續(xù)交付流水線都是必須的。在流水線上看到的都只是一個(gè)一個(gè)的stage,并且某些stage(比如部署)應(yīng)該需要手動(dòng)批準(zhǔn)觸發(fā)。至于點(diǎn)擊之后到底是調(diào)用了Ansible腳本,還是運(yùn)行了docker pull都是實(shí)現(xiàn)細(xì)節(jié)了。下面是一個(gè)使用 http://crp.aliyun.com 配置出來的示例持續(xù)交付流水線,及其不同的狀態(tài)。

      微服務(wù)

      上圖是一個(gè)持續(xù)集成流水線的不同狀態(tài)的樣子??梢钥吹絼傞_始的兩個(gè)stage,代碼檢出和集成測(cè)試,是由代碼提交自動(dòng)觸發(fā)的。到了第三個(gè)stage,也就是部署測(cè)試環(huán)境,就需要手工批準(zhǔn)了,所以出現(xiàn)了一個(gè)按鈕給你按。后續(xù)的預(yù)發(fā)和生產(chǎn)環(huán)境也都類似。

      持續(xù)交付部分就講到這里,下面是個(gè)小結(jié):

      持續(xù)交付與微服務(wù)

      接下來我們?cè)倭牧奈⒎?wù)。

      微服務(wù)與持續(xù)交付的相互作用

      關(guān)于微服務(wù)的概念,《微服務(wù)設(shè)計(jì)》一書給出的定義是:一些協(xié)同工作的小而自治的服務(wù)。微服務(wù)能夠帶來很多的好處,幫助我們更好的進(jìn)行持續(xù)交付。當(dāng)然微服務(wù)本身也需要很多實(shí)踐的支撐,比如Martin Fowler就在他的bliki(http:///bliki/MicroservicePrerequisites.html)中提到了“You must be this tall to use microservices”。而這個(gè)’tall’中的很多內(nèi)容都已經(jīng)涵蓋前面討論的那些持續(xù)交付的技術(shù)實(shí)踐中。所以可以說微服務(wù)和持續(xù)交付也是相輔相成的關(guān)系。

      使用微服務(wù)之后,顯然你需要部署的服務(wù)就會(huì)增多。如果一個(gè)服務(wù)的自動(dòng)化部署和相應(yīng)的流水線都沒有做好,那么服務(wù)多了之后部署的復(fù)雜性就可想而知了。所以只有把持續(xù)交付的實(shí)踐先做好,才有可能順利地使用微服務(wù)。

      反過來看,微服務(wù)架構(gòu)下,每個(gè)服務(wù)都很小。因此如果我的某次修改只涉及了一個(gè)微服務(wù)的代碼,我只需要發(fā)布這一個(gè)服務(wù)即可。那么相應(yīng)的測(cè)試工作也就簡(jiǎn)單的多。

      其實(shí)按理說,雖然服務(wù)拆開了,但是還是需要這些服務(wù)在一起才能完成整個(gè)系統(tǒng)的功能。所以只修改一個(gè)服務(wù),還是有可能影響整個(gè)系統(tǒng)的功能的。但是因?yàn)樗鼈兪遣煌姆?wù),所以一定會(huì)有非常清晰的API接口。這種API接口其實(shí)跟一個(gè)單塊系統(tǒng)中的模塊化的概念很類似。只不過API容易做的清晰,而單塊系統(tǒng)中的模塊化的邊界很難維持。所以從這個(gè)角度看,微服務(wù)帶來的其實(shí)是“強(qiáng)制的模塊化”,從而帶來更好的設(shè)計(jì)。

      好的,話說回來。既然每次發(fā)布只涉及到需要修改的那些微服務(wù),那么影響的面就相應(yīng)的較小,所以就可以更加放心大膽的去做發(fā)布,也就進(jìn)一步促進(jìn)了持續(xù)交付。

      微服務(wù)所涉及的話題非常多,大家可以移步《微服務(wù)設(shè)計(jì)》這本書查看所有的話題。這里只分享一點(diǎn),那就是使用漸進(jìn)式的方式進(jìn)行微服務(wù)化。當(dāng)然其實(shí)“漸進(jìn)式”是我做大部分變動(dòng)時(shí)的一個(gè)通用原則,比如重構(gòu),架構(gòu)變化等。

       

      漸進(jìn)式微服務(wù)化的一個(gè)場(chǎng)景就是當(dāng)你要新做一塊相對(duì)來說比較大,而且比較獨(dú)立的功能時(shí),就可以考慮,是否可以單獨(dú)寫在一個(gè)服務(wù)中。舉個(gè)例子,若干年前我在一個(gè)比較大的Java Spring項(xiàng)目上工作。然后客戶有了一塊新的業(yè)務(wù),最終希望以主站上的一個(gè)tab頁(yè)的形式存在。但我們都不想在這個(gè)陳舊的系統(tǒng)上繼續(xù)開發(fā)。最終的方式就是新啟一個(gè)應(yīng)用。使用當(dāng)時(shí)開發(fā)效率最高的技術(shù)。

       

      那么怎么做到存在主站上的一個(gè)tab呢?答案是使用nginx集成。為了不暴漏客戶信息,下面我們會(huì)用一些加的信息。這個(gè)應(yīng)用的所有url都在/new_app/下。在主站的nginx配置中加上一條轉(zhuǎn)發(fā)的規(guī)則,把/new_app/*這樣的url,都轉(zhuǎn)發(fā)到新部署的應(yīng)用上。

      nginx

       

      這是一個(gè)行之有效的粘合新服務(wù)的方法。后來我們使用類似的方法把其它的“tab頁(yè)”(也就是其它不同的業(yè)務(wù))也都一一用新的技術(shù)重寫了一遍,掛載到了主站上。

       

      當(dāng)然,這只是一種微服務(wù)的形態(tài)而已。關(guān)于更多的形態(tài),大家可以了解一下淘寶的前后端分離技術(shù):http://blog./65513/。

       

      好的,稍微總結(jié)一下今天的內(nèi)容:

       

      今天主要講了什么是持續(xù)交付的目標(biāo),為了達(dá)到這個(gè)目標(biāo)需要使用哪些技術(shù)。然后還聊了聊微服務(wù)的方法論會(huì)給持續(xù)交付這件事情帶來怎樣的機(jī)遇和挑戰(zhàn)。最后舉了一個(gè)例子來說明如何逐步進(jìn)行微服務(wù)化。

      感謝大家的聆聽。

      Q&A

      Q1:使用Docker部署微服務(wù)持續(xù)交付時(shí),應(yīng)該注意什么?你們的Docker使用情況是怎樣的?

      A1:我現(xiàn)在做的是一款持續(xù)交付產(chǎn)品,本身會(huì)有一個(gè)構(gòu)架集群,執(zhí)行任務(wù)使用的是Docker,但集群軟件本身并沒有使用Docker來不熟。不然就是在Docker中運(yùn)行Docker了,性能會(huì)有些影響。

      前端的portal正在做Docker化,還沒有應(yīng)用到生產(chǎn)環(huán)境中。一個(gè)可以分享的就是,要把自己的應(yīng)用的相關(guān)配置都環(huán)境變量化,這樣對(duì)于Docker化比較友好。

      我們還有一個(gè)產(chǎn)品是code.aliyun.com。這個(gè)產(chǎn)品也沒有Docker化,或者說『不可變服務(wù)器化』,原因就是因?yàn)橐诒镜卮疟P寫代碼庫(kù)。

      所以上面提到對(duì)本地讀寫要求比較高的應(yīng)用做『不可變服務(wù)器』還是有些困難的。

       

      Q2:你們目前關(guān)注的持續(xù)集成的量化指標(biāo)有哪些?比如項(xiàng)目單元測(cè)試/接口測(cè)試/靜態(tài)檢查等方面的內(nèi)容。整個(gè)持續(xù)集成有效運(yùn)轉(zhuǎn)的效率如何?失敗了怎么辦?怎么保證交付系統(tǒng)的穩(wěn)定性?

      A2:指標(biāo)主要是測(cè)試覆蓋率、代碼復(fù)雜度,及checkstyle檢查出來的一些問題。持續(xù)集成會(huì)有一個(gè)大屏幕把信息輻射出來,所以如果出錯(cuò)了,所有人都能看到會(huì)要求把CI break的同學(xué)立即修復(fù),并且在修復(fù)之前不允許新功能的提交。

       

      Q3:問個(gè)小問題,崔力強(qiáng)老師描述的package能包括什么內(nèi)容?

      A3:可以是純粹的應(yīng)用,比如war包。也可以是一個(gè)壓縮包,里面包含了war包和安裝腳本,這樣這個(gè)軟件包就是可以自安裝的。

       

      Q4:Windows的架構(gòu)會(huì)支持嗎?

      A4:剛才提到的Ansible是支持Windows的。Docker的話,現(xiàn)在出了原生的Docker,可以做開發(fā)測(cè)試之用。但生產(chǎn)環(huán)境的性能如何,還需要測(cè)試一下。

      Windows上有原生的Docker,我是mac用戶,win版的Docker其實(shí)也沒有用過,只是看到Docker官網(wǎng)的消息:https://www./products/docker :)原生的mac版Docker的volume掛載的性能也很差,猜測(cè)可能win版本的也不會(huì)太好。

      文章出處:DBAplus社群

      轉(zhuǎn)載請(qǐng)注明:運(yùn)維派 ? 阿里技術(shù)專家:持續(xù)交付與微服務(wù)背后的實(shí)踐邏輯

      57
      暫無評(píng)論



      分享文章

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多