另一個關于持續集成和版本分支的故事

發表于:2013-12-18來源:酷勤網作者:不詳點擊數: 標簽:持續集成
另一個關于持續集成和版本分支的故事.經典書籍《持續交付》[1]的作者曾就分支合并和代碼演化等問題詳細地討論過濫用分支對持續集成的負面影響。而我今天要說的是這樣一個故事,一個只能申請到非常有限的硬件設備的團隊,他們是如何在多分支策略下實踐持續集成的。

  經典書籍《持續交付》[1]的作者曾就分支合并和代碼演化等問題詳細地討論過濫用分支對持續集成的負面影響。而我今天要說的是這樣一個故事,一個只能申請到非常有限的硬件設備的團隊,他們是如何在多分支策略下實踐持續集成的。

  一個團隊接手了一個項目,需要在開發新特性的同時維護幾個發布分支。團隊計劃實踐持續集成,但手頭的硬件資源嚴重不足,無法滿足所有分支的部署流水線同時運轉。

  流水線分為三個階段,分別是:

  commit編譯、單元測試和部分集成測試并打包

  at部署應用程序并運行自動化驗收測試

  uat部署應用程序并由測試工程師執行手工驗收測試

  這里我們略去了性能測試階段和發布階段,它們一般需要額外安排硬件設備,與這個故事關系不大。流水線的每一個階段都可能依賴于某些外部服務,比如Web容器、數據庫等。為防止不必要的干擾,每個階段通常會盡可能地使用專用的外部服務,測試工程師在uat階段做手工測試時可不喜歡Web容器由于at階段被觸發而被重啟。

  長生命周期的分支同主干一樣也需要部署流水線,也就需要更多的外部服務。如果主干的at階段依賴于數據庫,那么某個發布分支的at階段也同樣需要依賴于數據庫。而通常你得為它們準備不同的數據庫實例以防互相干擾。外部服務的安裝和運行是需要硬件資源的,在資源拮據時,分支無疑加劇了這個問題。由于一些特殊情況,在好幾個項目中我們只申請到了一臺破舊的PC server作為團隊的測試設備。但我們并不打算因此放棄持續集成,所以讓我們看看能不能在螺螄殼里做道場吧。

  相對其他外部服務,數據庫是一個吃硬件資源的大戶。這個項目的生產環境將使用Oracle數據庫,如果流水線的每個階段都是用獨立的Oracle實例,那么一個主干和兩個發布分支就需要9個Oracle實例。

  在流水線的某些階段,可以使用一些替代方案,比如commit階段,可以把持久化測試運行在embedded的hsqldb上,這樣可以去除此階段對數據庫實例的需求,而且這樣commit階段的構建時間應該會有所減少[2]。

  后續at和uat的功能驗收測試最好運行在與生產環境相同類型的數據庫上。我們曾考慮過采用增量式的數據庫開發策略[3],那么不同階段、不同分支的數據庫模式(schema)應該是兼容的,這樣就只需要一個數據庫實例。不過這個技術門檻比較高,而且不同分支的流水線的測試可能由于清理和準備測試數據而互相干擾。于是我們決定利用數據庫用戶[4]來隔離不同的環境,比如主干的at環境使用用戶at_trunk,而分支的at環境使用at_branch_0816。

  這對應用程序的代碼和架構有更高的要求,由于數據庫用戶名變為環境相關配置了,就必須去除硬編碼,例如在SQL語句中不能有明確的用戶名

  select * from billing.t_order where .....

  改為

  select * from t_order where .....

  其實這種限制也有其好處,減少了團隊不經意地使用數據庫集成[5](比如直接操作另一個用戶中的數據)的機會,從而更謹慎地設計系統邊界和集成方案。不過,若要改造使用數據庫集成的遺留系統,還得曲線救國,先把其置入部署流水線的反饋循環再做改動,這時對于跨數據庫用戶操作可以采用數據庫同名來處理,比如Oracle支持將另外一個用戶的數據庫對象映射到本用戶的一個同名對象:

  -- Create the synonym

  create or replace synonym t_billing_order for billing.t_order;

  記得將這個腳本參數化,可以使用Ant和占位符替換,在執行腳本前,替換相應環境的用戶名。

  Web中間件是另一個大頭,不過這里目前團隊也沒發現有什么特別的辦法??梢钥紤]在部署腳本中使用參數化的contextPath,這樣在同一個 Tomcat或是Weblogic中可以部署多個環境的應用程序,但是這樣一來加大了配置難度,二來節約的資源有限,所以基本上還是通過一個環境一個 Tomcat或是一個Weblogic的一個Domain來實現的。

  如果應用程序還依賴消息組件,那么還應該準備流水線各階段專用的消息中間件。不像數據庫,共享消息中間件而引發的問題比較隱蔽。有一次,我們正在為一個應用程序做發布前的回歸測試,此前都沒有發現問題,正當我們認為高枕無憂時,這個環節的測試卻由于應用程序無法收到消息而失敗。當時距離發布截止期的時間緊迫,我們被迫暫時放棄了異步消息的方案,改用同步處理。后來,我們發現問題的原因在于多個Consumer監聽同一個消息隊列,而一個意料之外的 Consumer“搶走”了我們的消息。

  如你所見,我們只有一臺server模式的ActiveMQ,而手工測試環境和試生產環境都監聽其中同一個消息隊列,手工測試環境的應用程序消費了試生產環境的應用程序發出的消息。于是我們另外搭建了一臺server模式的ActiveMQ,讓它們分別監聽,問題就解決了。這件事讓我意識到,作為一個有狀態的組件,消息中間件也是環境敏感的。當然,一個好消息是消息中間件需要的硬件資源一般沒有數據庫那么多(多安裝一個ActiveMQ和多安裝一個 Oracle實例相比),所以最簡單的做法就是再裝一個。但如果你的環境比較多(從而導致ActiveMQ比較多)時,也是很頭疼的。一是由于消息是需要持久化的,所以每個ActiveMQ是需要一些自定義的配置的。如果你使用數據庫作為消息存儲,還得讓不同的ActiveMQ依賴于不同的數據庫實例,或至少是不同的用戶,如果是文件存儲,那么需要指定不同的目錄,總之需要細心的配置。二是團隊成員有可能被這些broker地址搞的暈頭轉向。有一段時間,我經常聽到這樣的對話:

原文轉自:http://www.kuqin.com/shuoit/20131215/336973.html

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97