成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

拆雖不易,合則更難!持續(xù)集成是微服務(wù)化的“基石”

開發(fā) 架構(gòu)
在很多微服務(wù)化的文章中,很少會把持續(xù)集成放在第一篇,因為大多數(shù)的文章都會講如何拆的問題,例如拆的粒度,拆的時機,拆的方式。

 在很多微服務(wù)化的文章中,很少會把持續(xù)集成放在***篇,因為大多數(shù)的文章都會講如何拆的問題,例如拆的粒度,拆的時機,拆的方式。

持續(xù)集成對于微服務(wù)的意義:拆之前要先解決合的問題

為什么需要拆呢?因為這是人類處理問題的本質(zhì)方式:將一個大的復(fù)雜問題,變成很多個小問題解決。

所以當(dāng)一個系統(tǒng)復(fù)雜到一定程度,當(dāng)維護一個系統(tǒng)的人數(shù)多到一定程度,解決問題的難度和溝通成本大大提高,因而需要拆成很多個工程,拆成很多個團隊,分而治之。

然而當(dāng)每個子團隊將子問題解決了,整個系統(tǒng)的問題就解決了么?你可以想象你將一輛整車拆成零件,然后再組裝起來的過程,你就可以想象拆雖然不容易,合則更難,需要各種標(biāo)準(zhǔn),各種流水線,才能將零件組裝成為車。

我們先來回顧一下拆的過程。

最初的應(yīng)用大多數(shù)是一個單體應(yīng)用。

一個 Java 后端,后面跟一個數(shù)據(jù)庫,基本上就搞定了。

隨著系統(tǒng)復(fù)雜度的增加,首先 Java 程序需要做的是縱向的拆分。

首先最外面是一個負(fù)載均衡,接著是接入的 Nginx,做不同服務(wù)的路由。

不同的服務(wù)拆成獨立的進程,獨立部署,每個服務(wù)使用自己的數(shù)據(jù)庫和緩存,解決數(shù)據(jù)庫和緩存的單點瓶頸。

數(shù)據(jù)庫使用一主多從的模式,進行讀寫分離,主要針對讀多寫少的場景。

為了承載更多的請求,設(shè)置緩存層,將數(shù)據(jù)緩存到 Memcached 或者 Redis 中,增加***率。

當(dāng)然還有些跨服務(wù)的查詢,或者非結(jié)構(gòu)化數(shù)據(jù)的查詢,引入搜索引擎,比關(guān)系型數(shù)據(jù)庫的查詢速度快很多。

在高并發(fā)情況下,僅僅縱向拆分還不夠,因而需要做真正的服務(wù)化。

一個服務(wù)化的架構(gòu)如下圖所示:

首先是接入層,這一層主要實現(xiàn) API 網(wǎng)關(guān)和動態(tài)資源和靜態(tài)資源的分離及緩存,并且可以在這一層做整個系統(tǒng)的限流。

接下來是 Web 層,也就是 controller,提供最外層的 API,是對外提供服務(wù)的一層。

下面是組合服務(wù)層,有時候被稱為編排層,Compose 層,是實現(xiàn)復(fù)雜邏輯的一層。

下面是基礎(chǔ)服務(wù)層,是提供原子性的基本的邏輯的一層,它下面是緩存,數(shù)據(jù)庫。

服務(wù)之間需要治理,需要相互發(fā)現(xiàn),所以一般會有 Dubbo 或者 Spring Cloud 一樣的框架。

對所有的服務(wù),都應(yīng)該有監(jiān)控告警,及時發(fā)現(xiàn)異常,并自動修復(fù)或者告警運維手動修復(fù)。

對于所有的服務(wù)的日志,應(yīng)該有相同的格式,收集到一起,稱為日志中心,方便發(fā)現(xiàn)錯誤的時候,在統(tǒng)一的一個地方可以 Debug。

對于所有的服務(wù)的配置,有統(tǒng)一的管理的地方,稱為配置中心,可以通過修改配置中心,下發(fā)配置,對于整個集群進行配置的修改,例如打開熔斷或者降級開關(guān)等。

通過簡單的描述,大家可以發(fā)現(xiàn),從一個簡單的單體應(yīng)用,變成如此復(fù)雜的微服務(wù)架構(gòu),除了關(guān)心怎么拆的問題,還必須關(guān)注:

  • 如何控制拆的風(fēng)險
  • 如何保證代碼質(zhì)量
  • 如何保證功能不變,不引入新的 Bug

答案當(dāng)然就是集成,從一開始就集成,并且不斷的集成,反復(fù)的將拆分的模塊重新組合,看看是否能夠順利組合起來,并且保證功能的不變。

要是不沒事兒就組合一下,天知道幾個月以后還能不能合的起來。

別忘了程序是人寫的,你和你媳婦長時間不溝通都談不上默契,別說兩個程序員了。

持續(xù)集成就是不斷的嘗試在一起

集成就是在一起,如下圖:

為什么需要一個統(tǒng)一的代碼倉庫 Git 來做代碼管理呢?是為了代碼集成在一起。

為什么需要進行構(gòu)建 build 呢?就是代碼邏輯需要集成在一起,編譯不出錯。

為什么要單元測試呢?一個模塊的功能集成在一起能夠正確工作。

為什么需要聯(lián)調(diào)測試 Staging 環(huán)境呢?需要將不同模塊之間集成在一起,在一個類生產(chǎn)的環(huán)境中進行測試。

最終才是部署到生產(chǎn)環(huán)境中,將所有人分開做的工作才算真正的合在了一起。

持續(xù)集成就是制定一系列流程,或者一個系列規(guī)則,將需要在一起的各個層次規(guī)范起來,方便大家在一起,強迫大家在一起。

持續(xù)集成、持續(xù)交付、持續(xù)部署、敏捷開發(fā)、DevOps 都有啥關(guān)系?

這些概念都容易混淆,他們之間是什么關(guān)系呢?如下圖:

敏捷開發(fā) Agile 是一種開發(fā)流程,是一種快速迭代的開發(fā)流程,每個開發(fā)流程非常短,長到一個月,短到兩個星期,就會是一個周期,在這個周期中,每天都要開會同步,每天都要集成。

正是因為周期短,才需要持續(xù)的做這件事情,如果一個開發(fā)周期長達(dá)幾個月,則不需要持續(xù)的集成。

***留幾個星期的集成時間一起做也是可以的,但是這樣就不能達(dá)到互聯(lián)網(wǎng)公司的快速迭代,也是我們常常看到傳統(tǒng)公司的做法。

持續(xù)集成往往指對代碼的提交,構(gòu)建,測試的過程,也就是上述的在一起的過程。

持續(xù)交付是指將集成好的交付物,例如 war、jar 或者容器鏡像,部署在聯(lián)調(diào)環(huán)境,或者預(yù)發(fā)環(huán)境的過程。

持續(xù)部署是指將交付物持續(xù)部署在生產(chǎn)環(huán)境的過程。

我們常說 CI/CD,CD 有時候指的是 Delivery 交付,有的是指 Deployment 部署,對于非生產(chǎn)環(huán)境,自動部署是沒有問題的,對于生產(chǎn)環(huán)境,往往還是需要有專人來進行更為嚴(yán)肅的部署過程,不會完全的自動化。

接下來就是 DevOps,DevOps 不只是 CI/CD,除了技術(shù)和流程,還包含文化。

例如容器化帶來的一個巨大的轉(zhuǎn)變是,原來只有運維關(guān)心環(huán)境的部署,無論是測試環(huán)境,還是生產(chǎn)環(huán)境,都是運維搞定的,而容器化之后,需要開發(fā)自己寫 Dockerfile,自己關(guān)心環(huán)境的部署。

因為微服務(wù)之后,模塊太多了,讓少數(shù)的運維能夠很好的管理所有的服務(wù),壓力大,易出錯,然而開發(fā)往往分成很多的團隊,每個模塊自己關(guān)心自己的部署,則不易出錯。

這就需要運維一部分的工作讓研發(fā)來做,需要研發(fā)和運維的打通,如果公司沒有這個文化,研發(fā)的老大說我們不寫 Dockerfile,則 DevOps 是搞不定的。

從一個持續(xù)集成的日常,看上述的幾個概念如何實踐

如上圖,這是一個持續(xù)集成的流程,但是運行起來更加的復(fù)雜。

首先,項目開發(fā)的流程使用的是 Agile,用常見的 scrum 為例子。

每天早上***件事情,就是開站會 standup meeting,為什么要站著呢?

因為時間不能太長,微服務(wù)的一個模塊,大概需要 5-9 人的團隊規(guī)模,如果團隊規(guī)模太大了,說明服務(wù)應(yīng)該進行拆分了,這個團隊規(guī)模,是能夠保證比較短的時間之內(nèi)過完昨天的狀態(tài)的。

一定要大家一起開,而不要線下去更新 Jira,雖然看起來一樣,但是執(zhí)行起來完全不一樣。

只有大家一起開,一起看燃盡圖,一起說我昨天做了什么,今天打算做什么,有什么阻礙,才能夠讓大家都了解情況,不要期望大家會去看別人的 Jira,經(jīng)驗告訴你,不會的。

而且這個站會對于開發(fā)是比較大的壓力,例如你的一個功能 block 了依賴方的開發(fā),在會議上會暴露出來,大家都知道這件事情了,一天 block,兩天 block,第三天你都不好意思去說了,這會強迫你將大任務(wù)細(xì)化。

比如原來寫 1 周干一件什么事情,寫成小時級別,這樣每天你都有的說,昨天完成了一個 task,而不是周會只在那里說干同樣一件事情。

而且一旦有了 block,team lead 會知道這件事情,會幫你趕緊解決這個事情,推進整個項目的進展。

讓一個技術(shù)人員在團隊面前承認(rèn)這件事情我嘗試了幾天,的確搞不定了,也是一種壓力。

站會中的內(nèi)容其實在前一天晚上就要開始準(zhǔn)備了。

持續(xù)集成要求每天都提交代碼,這樣才能降低代碼集成的風(fēng)險,不能埋頭寫一周一起提交,這樣往往集成不成功。

怎么樣才能鼓勵團隊成員每天都提交代碼呢?一個就是第二天的站會,你這個功能代碼提交了,單元測試通過了,第二天才能說做完了,否則不算,這就逼得你,將大任務(wù)拆成小任務(wù),每天都多次提交。

而且 Git 的提交方式,是后提交者有責(zé)任去 merge,保證代碼的編譯通過和測試通過,你會發(fā)現(xiàn),如果你不及時提交,等你改了一大片代碼,別人都提交完了,這一大片的沖突都是你來 merge,測試用例不通過的你來 fix。

所以逼的你有一個小的功能的改動,就盡早提交,pull 一下發(fā)現(xiàn)沒有人提交,就趕緊提交。

提交不是馬上進入主庫,而是需要代碼審核,這是把控代碼質(zhì)量的重要環(huán)節(jié)。

代碼質(zhì)量的控制往往每個公司都有文檔,甚至你可以從網(wǎng)上下載一篇很長很長的 Java 代碼規(guī)范。

但是我們常常看到的例子是,規(guī)范是有,但是虱子多了不咬人,規(guī)范太多的,誰也記不住,等于沒有規(guī)范。

所以建議將復(fù)雜的規(guī)范通過項目組內(nèi)部的討論,簡化為簡單的 10 幾條軍規(guī),深入人心,大家都容易記住,并且容易執(zhí)行。

代碼審核往往需要注意下面的幾方面:

  • 代碼結(jié)構(gòu):整個項目組應(yīng)該規(guī)定統(tǒng)一的代碼組織結(jié)構(gòu),使得每個開發(fā)拿到另一個人的代碼,都能看到熟悉的面孔。

這也是 Scrum 中提倡的每個開發(fā)之間是可替代的,當(dāng)一個模塊有了阻礙,其他人是可以幫上忙的。至于核心的邏輯,估計審核人員也來不及細(xì)看,這不要緊,核心邏輯是否通過,不能靠眼睛,要靠測試。

  • 有沒有注釋,尤其是對外的接口,應(yīng)該有完善的注釋,方便自動生成接口文檔。
  • 異常的處理,是否拋出太過寬泛的異常,是否吞掉異常,是否吞掉異常的日志等。
  • 對于 pom 是否有修改,引入了新的 jar。
  • 對于配置文件是否有修改,對外訪問是否設(shè)置超時。
  • 對于數(shù)據(jù)庫是否有修改,是否經(jīng)過 DBA 審核。
  • 接口實現(xiàn)是否冪等,因為 Dubbo 和 Spring Cloud 都會重試接口。接口是否會升級,是否帶版本號。
  • 是否有單元測試。

當(dāng)然還有一些不容易一眼看出來的,可以通過一段時間通過統(tǒng)一的代碼 review,來修改這些問題:

  • 某個類代碼長度過長
  • 設(shè)計是否合理,高內(nèi)聚低耦合
  • 數(shù)據(jù)庫設(shè)計是否合理
  • 數(shù)據(jù)庫事務(wù)是否使用合理
  • 代碼是否有明顯的阻塞

代碼審核完畢提交上去之后,一個是要通過靜態(tài)代碼審查,可以發(fā)現(xiàn)一些可能帶來代碼風(fēng)險的問題,例如異常過于寬泛等。

再就是要通過單元測試。我們應(yīng)該要求每個類都要有單元測試,并且單元測試覆蓋率要達(dá)到一定的指標(biāo)。單元測試要有帶 Mock 的模塊內(nèi)的集成測試。

在編譯過程中會觸發(fā)單元測試,單元測試不通過,以及代碼覆蓋率,都會統(tǒng)計后發(fā)郵件,抄送所有的人,這對于研發(fā)來講又是一個壓力。

當(dāng)有一天你的提交 break 掉了測試,或者代碼覆蓋率很低,則就像通報批評一樣,你需要趕緊去修改。

單元測試完畢之后,就會上傳成果物,或者是 war 或者是 jar,一般會用 nexus。

因為有版本號,有 md5,可以保證安裝在環(huán)境中的就是某個版本的某個包,我們還遇到過有使用 FTP 的,這樣很難保證版本號的維護,升級和回滾也比較難弄。

另一個是沒有 md5,很可能包不完整都有可能的,而且一旦發(fā)生,很難發(fā)現(xiàn)。

如果使用了容器,則還需要編譯 Dockerfile,使用 Docker 鏡像作為交付,能夠?qū)崿F(xiàn)更好的環(huán)境一致性,保證原子的升級和回滾。

每天下班前,當(dāng)天的代碼需要提交到庫中去,晚上會做一次統(tǒng)一的環(huán)境部署和集成測試。

每天晚上凌晨,會有自動化的腳本將 Docker 鏡像通過編排部署一個完整的環(huán)境,然后跑集成測試用例,集成測試用例應(yīng)該是基于 API 的,很多的公司是基于 UI 的。

這樣由于 UI 變化太快,還有 UI 不能覆蓋所有的場景,所以還是建議 UI 和 API 分離。

通過 API 進行集成測試,有了每天的測試,才能保證每天晚上的版本都是可以交付的版本,也保證我們微服務(wù)拆分的時候,盡管改了很多,不會因為新的修改,破壞掉原來能夠通過的測試用例,保證不會有了新的,壞了舊的。

這個集成測試或者叫回歸測試每天晚上都做,都是在一個全新的環(huán)境中,這就是持續(xù)部署和持續(xù)交付。

如果某一天測試不通過,則會發(fā)出郵件來,是因為當(dāng)天誰的哪個提交,導(dǎo)致測試不通過,抄送所有人,這是另一個壓力。

所以第二天的站會上,昨天你完成了哪些功能,是否提交了,是否完成了單元測試,是否通過了集成測試,就都知道了,你需要給大家一個解釋,然后進入到新一天的開發(fā)。

到了兩周,一個周期完畢,可以上線到生產(chǎn)環(huán)境了,可以通知有權(quán)限的運維進行操作,但是也是通過自動化的腳本進行部署的。

這就是整個過程,層層保證質(zhì)量,從中可以看到,敏捷開發(fā),持續(xù)集成,持續(xù)交付,持續(xù)部署,DevOps 是互相聯(lián)系的,少了哪個,流程都玩不轉(zhuǎn)。

有關(guān)代碼結(jié)構(gòu)

代碼結(jié)構(gòu)往往包括:

  • API 接口包
  • 訪問外部服務(wù)包
  • 數(shù)據(jù)庫 DTO
  • 訪問數(shù)據(jù)庫包
  • 服務(wù)與商務(wù)邏輯
  • 外部服務(wù)

如果使用 Dubbo RPC,則 API 接口往往在一個單獨的 jar 里面,被服務(wù)端和客戶端共同依賴。

但是使用了 Spring Cloud 的 restful 方式就不用了,只要在各自的代碼里面定義就可以了,會變成 json 的方式傳遞。

這樣的好處是當(dāng) jar 有多個版本依賴,需要升級的時候,關(guān)系非常復(fù)雜,難以維護,而 json 的方式比較好的解決了這個問題。

這個模塊提供了哪些接口,只要到 API 接口這個 package 下面找就可以了。因為無論是 Dubbo 還是 Spring Cloud,接口的調(diào)用都會重試,因而接口需要實現(xiàn)冪等。

訪問外部服務(wù)的包,將所有對外的訪問獨立出來,有三個好處:

  • 可以抽象出來,在服務(wù)拆分的時候,可能會用到,例如原來支付的邏輯在下單的模塊中,要將支付獨立出來,則會有一個抽象層,涉及到老的支付方式,還是調(diào)用本模塊中的邏輯,涉及到新接入的支付方式使用遠(yuǎn)程調(diào)用,有了這一層方便的多。
  • 可以實現(xiàn)熔斷,當(dāng)被調(diào)用的服務(wù)不正常的時候,在這里可以返回托底數(shù)據(jù)。
  • 可以實現(xiàn) Mock,這樣對于單元測試來講非常好,不用依賴于其他服務(wù),就可以自己進行測試。

DTO 和訪問數(shù)據(jù)庫的包,看到了這些數(shù)據(jù)結(jié)構(gòu),會幫助程序員快速掌握代碼邏輯。

不知道大家有沒有這個體驗,你去看一個開源軟件的代碼,首先要看的是它的數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu)和關(guān)系看懂了,代碼邏輯就比較容易懂了,如果數(shù)據(jù)結(jié)構(gòu)沒看懂,光看邏輯,就容易云里霧里。

還有就是核心的代碼邏輯和對接口的實現(xiàn)。在這里面是軟件代碼設(shè)計的內(nèi)功所在,但是卻不是流程能夠控制的。

有關(guān)接口設(shè)計規(guī)范

上面也說過了,Dubbo 和 Spring Cloud 會對接口進行重試,因而接口需要保持冪等。

也即多次調(diào)用,應(yīng)該產(chǎn)生一致的結(jié)果,例如轉(zhuǎn)賬 1 元,因為調(diào)用失敗或者超時重試的時候,最終結(jié)果還應(yīng)該是轉(zhuǎn)賬 1 元,而非調(diào)用兩次變成轉(zhuǎn)賬 2 元。

冪等判斷盡量提前,可以使用 ID 作為判斷條件。

接口的實現(xiàn)應(yīng)該盡量避免阻塞,可以使用異步方式提升性能。

接口應(yīng)該包括能夠區(qū)分不同情況的異常,而非拋出寬泛的 Exception,不能吞掉異常。

接口的實現(xiàn)要有足夠的容錯性,以及對不同版本的兼容性。當(dāng)要引入新接口的時候,使用先添加,后刪除的方式。

接口應(yīng)該有良好的注釋。

有關(guān)代碼設(shè)計

對于代碼的設(shè)計,這里常說的就是 SOLID 原則:

  • S 是單一責(zé)任原則,如果你的代碼中有一個類行數(shù)太長,可能你需要重新審視一下,是不是這個類承擔(dān)了過多的責(zé)任。
  • O 是開放關(guān)閉原則,比較拗口,對擴展開放,對修改關(guān)閉。思想是對于代碼的直接修改是非常危險的事情,因為你不知道這段代碼原來被誰用了,而且到用的時候,面臨的情況都是怎樣的。

因而不要貿(mào)然修改一段代碼,而是選擇用接口進行調(diào)用,用實現(xiàn)進行擴展的方式進行。

當(dāng)你要實現(xiàn)一段新的功能的時候,不要改原來的代碼,也不要 if-else,而是應(yīng)該擴展一種實現(xiàn),讓原來的調(diào)用的代碼邏輯還是原來的,在新的情況下使用新實現(xiàn)的代碼邏輯。

  • L 是里氏替換原則,如果基于接口進行編程,則子類一定要能夠擴展父類的功能,如果不能,說明不應(yīng)該繼承于這個接口。

例如你在實現(xiàn)的時候,發(fā)現(xiàn)接口中有一個方法在你這里實在對應(yīng)不到實現(xiàn),不是接口設(shè)計的問題,就是你不應(yīng)該繼承這個接口,絕不能出現(xiàn) not implemented 類似之類的實現(xiàn)方法。

  • I 是接口隔離原則,接口不應(yīng)該設(shè)計的大而全,一個接口暴露出所有的功能,從而使得客戶端依賴了自己不需要的接口或者接口的方法。

而是應(yīng)該將接口進行細(xì)分和提取,而不應(yīng)該將太過靈活的參數(shù)和變量混雜在一個接口中。

  • D 是依賴倒置原則,A 模塊依賴于 B 模塊,B 模塊有了修改,反而要改 A,就是依賴的過于緊密的問題。

這就是我們常說的,你變了,我沒變,為啥我要改。如果基于抽象的接口編程,將修改隱藏在后面,則能夠?qū)崿F(xiàn)依賴的解耦。

以上是模塊內(nèi)部常見的設(shè)計原則,對于模塊之間,則是對于云原生應(yīng)用常說的十二原則。

有關(guān)配置文件

在代碼倉庫中,還需要管理的是配置文件,往往在 src/main/resource 下面。

配置的管理原來多使用 profile 進行管理,對于 dev、test、production 使用不同的配置文件。

當(dāng)配置非常多的時候,比較的痛苦,而且配置不斷的修改,每次上線各種配置需要仔細(xì)的核對,眼睛都花了,才敢上線。

我們可以將配置分為下面的三類:

  • 內(nèi)部配置項(啟動后不變,改變需要重啟)
  • 集中配置項(配置中心,可動態(tài)下發(fā))
  • 外部配置項(外部依賴,和環(huán)境相關(guān))

在梳理配置的時候,可以按著三類歸類,分門別類管理。

在使用了容器之后,很多的內(nèi)部配置項可固化在配置文件中,放在容器鏡像中,需要啟動的時候修改的,則通過環(huán)境變量,在啟動容器的時候,在編排文件中進行修改。

依賴的內(nèi)部服務(wù)的地址,在容器平臺 Kubernetes 里面,可以通過配置服務(wù)名進行服務(wù)發(fā)現(xiàn),僅僅在配置文件中配置名稱就可以了,不用配置真實的地址。

Kubernetes 可以根據(jù)不同的環(huán)境,不同的 namespace 自動關(guān)聯(lián)好,大大簡化了配置。當(dāng)然也可以用服務(wù)中心 Dubbo 和 Spring Cloud 做內(nèi)部服務(wù)的相互發(fā)現(xiàn)。

依賴的外部服務(wù)的地址,例如 MySQL、Redis 等,往往不同的環(huán)境,也可以通過配置 Kubernetes 外部服務(wù)名的方式進行,而不用一一核對,擔(dān)心測試環(huán)境連上了生產(chǎn)環(huán)境的 IP 地址。

還有一些集中配置項,需要動態(tài)修改的,例如限流,降級的開關(guān)等,需要通過統(tǒng)一的配置中心進行管理。

有關(guān)數(shù)據(jù)庫版本

代碼可以很好的版本化,應(yīng)用也可以用鏡像進行原子化的升級和回滾。

唯一比較難做到的就是數(shù)據(jù)庫如何版本化管理。有一個工具 Flyway 可以比較好的做這件事情。

在代碼中,F(xiàn)lyway 需要有以下的結(jié)構(gòu):

  • 在 src/db/migration 中有 SQL 文件,命名規(guī)則,如:V1__2017_4_13.sql ,V 開頭+版本號+雙下劃線+描述,后綴為 sql。
  • 增加 Flyway 的 Java 類,實現(xiàn) migration 方法。

在數(shù)據(jù)庫中,F(xiàn)lyway 會自動增加 SCHEME_VERSION 表。

當(dāng)服務(wù)啟動的時候,Java 類的 migration 方法會被調(diào)用,它會按照指定路徑中 sql 語句的版本號進行排序并且按照這個排序去執(zhí)行,當(dāng)每一個 SQL 文件被執(zhí)行后,元數(shù)據(jù)的表就會按照格式進行更新。

當(dāng)服務(wù)重啟的時候,F(xiàn)lyway 再次掃描 SQL 的時候,它就會檢查元數(shù)據(jù)表中遷移版本,如果要執(zhí)行的遷移腳本的版本小于或者等于當(dāng)前版本,F(xiàn)lyway 將會忽略,不再重復(fù)執(zhí)行。

但是 Flyway 從來不解決數(shù)據(jù)庫升級和回滾的代碼兼容性問題。

太多的人問這個問題了,代碼可以灰度發(fā)布,數(shù)據(jù)庫咋灰度?代碼升級了,發(fā)現(xiàn)不對可以回滾,數(shù)據(jù)庫咋回滾。

如果可以停服的話,自然是使用數(shù)據(jù)庫快照備份的方式進行回滾了。

如果不可以停服,沒辦法,只有在代碼層面做兼容性。每次涉及數(shù)據(jù)庫升級的都是大事情,代碼當(dāng)然應(yīng)該有個開關(guān),保證隨時可以切回原來的邏輯。

責(zé)任編輯:武曉燕 來源: 通俗云計算
相關(guān)推薦

2017-10-19 09:47:55

容器化微服務(wù)集成

2021-09-03 11:33:38

Jenkins 微服務(wù)集成

2021-05-07 08:03:15

微服務(wù)JenkinsGitHub項目

2021-03-31 09:00:00

管道集成工具

2017-09-06 15:16:54

微服務(wù)數(shù)字化云遷移

2015-07-22 14:59:30

OpenStac持續(xù)集成持續(xù)交付

2018-01-08 14:18:14

代碼互聯(lián)網(wǎng)持續(xù)集成

2017-02-27 18:35:23

集成交付部署

2016-08-05 17:19:37

持續(xù)集成持續(xù)交付系統(tǒng)運維

2023-03-19 11:47:57

Taro小程序持續(xù)集

2023-02-20 08:02:38

智能自動化交付

2019-04-18 10:35:30

持續(xù)集成工具Buddy

2015-09-29 10:08:26

DockerJava持續(xù)集成

2022-04-20 09:00:00

軟件開發(fā)自動化測試工具

2009-06-14 18:05:58

ibmdwWebSphere

2015-07-27 11:32:24

Docker持續(xù)集成Docker部署

2014-11-07 14:59:11

容器化ShippableDocker

2015-09-24 09:43:08

阮一峰持續(xù)集成

2021-07-08 07:52:48

微服務(wù)業(yè)務(wù)架構(gòu)

2021-06-18 09:00:00

云計算開發(fā)存儲庫
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产97视频在线观看 | 久久久高清 | 国产成人在线一区二区 | 精品欧美一区二区久久久伦 | 毛片一区二区三区 | 精品久久久久久国产 | 一区二区三区四区av | 久久亚洲综合 | 不卡一区二区在线观看 | 日韩福利 | 欧美国产一区二区三区 | 欧洲一区二区三区 | 天堂在线一区 | 极品的亚洲 | 久久久久免费精品国产 | 中文字幕二区三区 | 在线播放中文字幕 | 久草久草久草 | 精品一级毛片 | www.国产一区 | 国产一级片网站 | 国产一区免费视频 | 欧美日韩精品久久久免费观看 | 99热激情 | 97av视频| 久久久精品久久 | 国产精品久久久久久久粉嫩 | 先锋资源吧 | 中文字幕一区二区三区不卡 | a精品视频 | 日韩三级视频 | 国产免费一区二区三区免费视频 | 成人免费在线播放 | 精品视频在线一区 | 羞羞视频免费在线观看 | 在线一区 | 欧美日韩一区精品 | 亚洲国产精品视频 | 久久成人国产 | 91成人在线视频 | 久久精品二区亚洲w码 |