日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

微服务化的基石——持续集成

發布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微服务化的基石——持续集成 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、持續集成對于微服務的意義:拆之前要先解決合的問題


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

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

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

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

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

最初的應用大多數是一個單體應用

一個Java后端,后面跟一個數據庫,基本上就搞定了。

隨著系統復雜度的增加,首先Java程序需要做的是縱向的拆分。

首先最外面是一個負載均衡,接著是接入的nginx,做不同服務的路由。

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

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

為了承載更多的請求,設置緩存層,將數據緩存到Memcached或者Redis中,增加命中率。

當然還有些跨服務的查詢,或者非結構化數據的查詢,引入搜索引擎,比關系型數據庫的查詢速度快很多。

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

一個服務化的架構如圖所示。

首先是接入層,這一層主要實現API網關和動態資源和靜態資源的分離及緩存,并且可以在這一層做整個系統的限流。

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

下面是組合服務層,有時候被稱為編排層,compose層,是實現復雜邏輯的一層。

下面是基礎服務層,是提供原子性的基本的邏輯的一層,他下面是緩存,數據庫。

服務之間需要治理,需要相互發現,所以一般會有dubbo或者springcloud一樣的框架。

對所有的服務,都應該有監控告警,及時發現異常,并自動修復或者告警運維手動修復。

對于所有的服務的日志,應該有相同的格式,收集到一起,稱為日志中心,方便發現錯誤的時候,在統一的一個地方可以debug。

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

通過簡單的描述,大家可以發現,從一個簡單的單體應用,變成如此復雜的微服務架構,除了關心怎么拆的問題,還必須關注:

  • 如何控制拆的風險

  • 如何保證代碼質量

  • 如何保證功能不變,不引入新的Bug

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

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

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

?

二、持續集成就是不斷的嘗試在一起


集成就是在一起。

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

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

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

為什么需要聯調測試Staging環境呢?需要將不同模塊之間集成在一起,在一個類生產的環境中進行測試。

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

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

?

三、持續集成,持續交付,持續部署,敏捷開發,DevOps都啥關系?


這些概念都容易混淆,他們之間是什么關系呢?

敏捷開發Agile是一種開發流程,是一種快速迭代的開發流程,每個開發流程非常短,長到一個月,短到兩個星期,就會是一個周期,在這個周期中,每天都要開會同步,每天都要集成。正是因為周期短,才需要持續的做這件事情,如果一個開發周期長達幾個月,則不需要持續的集成,最后留幾個星期的集成時間一起做也是可以的,但是這樣就不能達到互聯網公司的快速迭代,也是我們常常看到傳統公司的做法。

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

持續交付是指將集成好的交付物,例如war,jar,或者容器鏡像,部署在聯調環境,或者預發環境的過程。

持續部署是指將交付物持續部署在生產環境的過程。

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

接下來就是DevOps,DevOps不只是CICD,除了技術和流程,還包含文化。例如容器化帶來的一個巨大的轉變是,原來只有運維關心環境的部署,無論是測試環境,還是生產環境,都是運維搞定的,而容器化之后,需要開發自己寫Dockerfile,自己關心環境的部署。因為微服務之后,模塊太多了,讓少數的運維能夠很好的管理所有的服務,壓力大,易出錯,然而開發往往分成很多的團隊,每個模塊自己關心自己的部署,則不易出錯,這就需要運維一部分的工作讓研發來做,需要研發和運維的打通,如果公司沒有這個文化,研發的老大說我們不寫Dockerfile,則DevOps是搞不定的。

?

四、從一個持續集成的日常,看上述的幾個概念如何實踐


這是一個持續集成的流程,但是運行起來更加的復雜。

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

每天早上第一件事情,就是開站會standup meeting,為什么要站著呢?因為時間不能太長,微服務的一個模塊,大概需要5-9人的團隊規模,如果團隊規模太大了,說明服務應該進行拆分了,這個團隊規模,是能夠保證比較短的時間之內過完昨天的狀態的。

一定要大家一起開,而不要線下去更新Jira,雖然看起來一樣,但是執行起來完全不一樣。只有大家一起開,一起看燃盡圖,一起說我昨天做了什么,今天打算做什么,有什么阻礙,才能夠讓大家都了解情況,不要期望大家會去看別人的Jira,經驗告訴你,不會的。

而且這個站會對于開發是比較大的壓力,例如你的一個功能block了依賴方的開發,在會議上會暴露出來,大家都知道這件事情了,一天block,兩天block,第三天你都不好意思去說了,這會強迫你將大任務,比如原來寫1周干一件什么事情,寫成小時級別,這樣每天你都有的說,昨天完成了一個task,而不是一周只在那里說干同樣一件事情,而且一旦有了block,team leader會知道這件事情,會幫你趕緊解決這個事情,推進整個項目的進展。讓一個技術人員在團隊面前承認這件事情我嘗試了幾天,的確搞不定了,也是一種壓力。

站會中的內容其實在前一天晚上就要開始準備了。

持續集成要求每天都提交代碼,這樣才能降低代碼集成的風險,不能埋頭寫一周一起提交,這樣往往集成不成功。怎么樣才能鼓勵每天都提交代碼呢?一個就是第二天的站會,你這個功能代碼提交了,單元測試通過了,第二天才能說做完了,否則不算,這就逼得你,將大任務拆成小任務,每天都多次提交。

而且Git的提交方式,是后提交者有責任去merge,保證代碼的編譯通過和測試通過,你會發現,如果你不及時提交,等你改了一大片代碼,別人都提交完了,這一大片的沖突都是你來merge,測試用例不通過的你來fix,所以逼的你有一個小的功能的改動,就盡早提交,pull一下發現沒有人提交,趕緊提交。

提交不是馬上進入主庫,而是需要代碼審核,這是把控代碼質量的重要的環節。

代碼質量的控制往往每個公司都有文檔,甚至你可以從網上下載一篇很長很長的Java代碼規范。但是我們常??吹降睦邮?#xff0c;規范是有,但是虱子多了不咬人,規范太多的,誰也記不住,等于沒有規范。

所以建議將復雜的規范通過項目組內部的討論,簡化為簡單的10幾條軍規,深入人心,大家都容易記住,并且容器執行。

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

  • 代碼結構:整個項目組應該規定統一的代碼組織結構,使得每個開發拿到另一個人的代碼,都能看的熟悉的面孔。這也是scrum中提倡的每個開發之間是可替代的,當一個模塊有了阻礙,其他人是可以幫上忙的。至于核心的邏輯,估計審核人員也來不及細看,這不要緊,核心邏輯是否通過,不能靠眼睛,要靠測試。

  • 有沒有注釋,尤其是對外的接口,應該有完善的注釋,方便自動生成接口文檔。

  • 異常的處理,是否拋出太過寬泛的異常,是否吞掉異常,是否吞掉異常的日志等。

  • 對于pom是否有修改,引入了新的jar。

  • 對于配置文件是否有修改,對外訪問是否設置超時

  • 對于數據庫是否有修改,是否經過DBA審核

  • 接口實現是否冪等,因為Dubbo和springcloud都會重試接口。接口是否會升級,是否帶版本號

  • 是否有單元測試

當然還有一些不容易一眼看出來的,可以通過一段時間通過統一的代碼review,來修改這些問題。

  • 某個類代碼長度過長

  • 設計是否合理,高內聚低耦合

  • 數據庫設計是否合理

  • 數據庫事務是否使用合理

  • 代碼是否有明顯的阻塞

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

再就是要通過單元測試。我們應該要求每個類都要有單元測試,并且單元測試覆蓋率要達到一定的指標。單元測試要有帶Mock的模塊內的集成測試。

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

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

單元測試完畢之后,就會上傳成果物,或者是war或者是jar,一般會用nexus,因為有版本號,有md5,可以保證安裝在環境中的就是某個版本的某個包,我們還遇到過有使用FTP的,這樣一個是很難保證版本號的維護,升級和回滾比較難弄,另一個是沒有md5,很可能包不完整都有可能的,而且一旦發生,很難發現。

如果使用了容器,則還需要編譯Dockerfile,使用Docker鏡像作為交付,能夠實現更好的環境一致性,保證原子的升級和回滾。

每天下班前,當天的代碼需要提交到庫中去,晚上會做一次統一的環境部署和集成測試。

每天晚上凌晨,會有自動化的腳本將Docker鏡像通過編排部署一個完整的環境,然后跑集成測試用例,集成測試用例應該是基于API的,很多的公司是基于UI的,這樣由于UI變化太快,還有UI不能覆蓋所有的場景,所以還是建議UI和API分離,通過API進行集成測試,有了每天的測試,才能保證每天晚上的版本都是可以交付的版本,也保證我們微服務拆分的時候,盡管改了很多,不會因為新的修改,破壞掉原來能夠通過的測試用例,保證不會有了新的,壞了舊的。

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

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

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

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

這就是整個過程,層層保證質量,從中可以看到,敏捷開發,持續集成,持續交付,持續部署,DevOps是互相聯系的,少了哪個,流程都玩不轉。

?

五、有關代碼結構


代碼結構往往包括:

  • API接口包

  • 訪問外部服務包

  • 數據庫DTO

  • 訪問數據庫包

  • 服務與商務邏輯

  • 外部服務

如果使用Dubbo RPC,則API接口往往在一個單獨的jar里面,被服務端和客戶端共同依賴,但是使用了springcloud的restful方式就不用了,只要在各自的代碼里面定義就可以了,會變成json的方式傳遞,這樣的好處是當jar有多個版本依賴,需要升級的時候,關系非常復雜,難以維護,而json的方式比較好的解決了這個問題。

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

訪問外部服務的包,這將所有對外的訪問獨立出來,好處一是可以抽象出來,在服務拆分的時候,可能會用到,例如原來支付的邏輯在下單的模塊中,要將支付獨立出來,則會有一個抽象層,涉及到老的支付方式,還是調用本模塊中的邏輯,涉及到新接入的支付方式使用遠程調用,有了這一層方便的多。好處二是可以實現熔斷,當被調用的服務不正常的時候,在這里可以返回托底數據。好處三是可以實現Mock,這樣對于單元測試來講非常好,不用依賴于其他服務,就可以自己進行測試。

DTO和訪問數據庫的包,看到了這些數據結構,會幫助程序員快速掌握代碼邏輯,不知道大家有沒有這個體驗,你去看一個開源軟件的代碼,首先要看的是他的數據結構,數據結構和關系看懂了,代碼邏輯就比較容易懂了,如果數據結構沒看懂,則光看邏輯,就容易云里霧里的。

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

?

六、有關接口設計規范


上面也說過了,Dubbo和Springcloud會對接口進行重試,因而接口需要保持冪等。也即多次調用,應該產生一致的結果,例如轉賬1元,因為調用失敗或者超時重試的時候,最終結果還應該是轉賬1元,而非調用兩次變成轉賬2元。

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

接口的實現應該盡量避免阻塞,可以使用異步方式提升性能。

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

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

接口應該有良好的注釋。

?

七、有關代碼設計


對于代碼的設計,這里常說的就是SOLID原則。

S是單一責任原則,如果你的代碼中有一個類行數太長,可能你需要重新審視一下,是不是這個類承擔了過多的責任。

O是開放關閉原則,比較拗口,對擴展開放,對修改關閉。思想是對于代碼的直接修改是非常危險的事情,因為你不知道這段代碼原來被誰用了,而且當時用的時候,面臨的情況都是怎樣的。因而不要貿然修改一段代碼,而是選擇用接口進行調用,用實現進行擴展的方式進行。當你要實現一段新的功能的時候,不要改原來的代碼,也不要if-else,而是應該擴展一種實現,讓原來的調用的代碼邏輯還是原來的,在新的情況下使用新實現的代碼邏輯。

L是里氏替換原則,如果基于接口進行編程,則子類一定要能夠擴展父類的功能,如果不能,說明不應該繼承自這個接口。例如你在實現的時候,發現接口中有一個方法在你這里實在對應不到實現,不是接口設計的問題,就是你不應該繼承這個接口,絕不能出現not implemented類似之類的實現方法。

I是接口隔離原則,接口不應該設計的大而全,一個接口暴露出所有的功能,從而使得客戶端依賴了自己不需要的接口或者接口的方法。而是應該將接口進行細分和提取,而不應該將太過靈活的參數和變量混雜在一個接口中。

D是依賴倒置原則,A模塊依賴于B模塊,B模塊有了修改,反而要改A,就是依賴的過于緊密的問題。這就是常說的,你變了,我沒變,為啥我要改。如果基于抽象的接口編程,將修改隱藏在后面,則能夠實現依賴的解耦。

以上是模塊內部常見的設計原則,對于模塊之間,則是對于云原生應用常說的十二原則。

?

詳情可云原生時代下的12-factor應用與實踐

?

八、有關配置文件


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

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

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

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

  • 內部配置項(啟動后不變,改變需要重啟)

  • 集中配置項(配置中心,可動態下發)

  • 外部配置項(外部依賴,和環境相關)

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

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

依賴的內部服務的地址,在容器平臺kubernetes里面,可以通過配置服務名進行服務發現,僅僅在配置文件中配置名稱就可以了,不用配置真實的地址,kubernetes可以根據不同的環境,不同的namespace自動關聯好,大大簡化了配置。當然也可以用服務中心Dubbo和Springcloud做內部服務的相互發現。

依賴的外部服務的地址,例如mysql,redis等,往往不同的環境不同,也可以通過配置kubernetes外部服務名的方式進行,而不用一一核對,擔心測試環境連上了生產環境的IP地址。

還有一些集中配置項,需要動態修改的,例如限流,降級的開關等,需要通過統一的配置中心進行管理。

?

九、有關數據庫版本


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

唯一比較難做到的就是數據庫如何版本化管理。

有一個工具flyway可以比較好的做這件事情。

在代碼中,flyway需要有以下的結構:

  • 在src/db/migration中有sql文件,命名規則,如:V1__2017_4_13.sql ,V開頭+版本號+雙下劃線+描述,后綴為sql

  • 增加flyway的java類,實現migration方法

在數據庫中,flyway會自動增加SCHEME_VERSION表。

當服務啟動的時候,java類的migration方法會被調用,它會按照指定路徑中sql語句的版本號進行排序并且按照這個排序去執行,當每一個sql文件被執行后,元數據的表就會按照格式進行更新。

當服務重啟的時候,Flyway 再次掃描sql的時候,它就會檢查元數據表中遷移版本,如果要執行的遷移腳本的版本小于或者等于當前版本,Flyway將會忽略,不再重復執行。

但是flyway從來不解決數據庫升級和回滾的代碼兼容性問題。

太多的人問這個問題了,代碼可以灰度發布,數據庫咋灰度?代碼升級了,發現不對可以回滾,數據庫咋回滾。

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

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

總結

以上是生活随笔為你收集整理的微服务化的基石——持续集成的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本少妇色 | 久久久久久亚洲中文字幕无码 | 成人精品动漫 | 久久精品片 | 亚洲在线视频 | 午夜黄色影院 | 夜夜夜综合 | 精品自拍av | 久操福利视频 | 色呦呦呦呦| 亚洲综合p | 国产又色又爽无遮挡免费动态图 | 中文字幕人妻无码系列第三区 | 自拍偷拍第八页 | 好看的毛片| 日本做爰高潮又黄又爽 | 日本在线免费观看视频 | 人妻少妇精品无码专区二区 | 欧美日韩人妻精品一区在线 | 亚洲一级片网站 | 动漫美女被到爽 | 一级黄色免费大片 | 成人国产在线观看 | 日韩欧美的一区二区 | 日批视频免费观看 | 亚洲精品国产视频 | a级黄色网址 | 欧美做爰猛烈床戏大尺度 | 欧美日韩三 | 自拍99 | 17c在线| 欧美裸体xxx | 欧美一级黄视频 | 天堂中文在线播放 | 一级黄色裸体片 | 黄色www | 无码国产精品96久久久久 | av激情影院 | 中文字幕精品在线观看 | 青青草原国产 | 色婷婷久久久 | 91精品国自产在线 | 超级砰砰砰97免费观看最新一期 | 国产精品成人免费 | 毛片无码免费无码播放 | 97免费在线视频 | 成人福利院 | www.亚洲视频| 亚洲欧美另类激情 | 欧美无遮挡高潮床戏 | 精品国自产拍在线观看 | 樱井莉亚av| 黄色污污视频 | 久久久久国产精 | 亚洲第一中文字幕 | 色综合久久久久久 | 97人人模人人爽人人少妇 | 黄色录像a | 制服丝袜av电影 | 深夜视频在线观看免费 | 国产精品有限公司 | 成人精品在线 | 国产精品视频免费网站 | 久草视| 久久国产成人精品国产成人亚洲 | 一区二区导航 | 手机在线看永久av片免费 | 艳妇臀荡乳欲伦交换在线播放 | 怡红院av久久久久久久 | 色香五月| 麻豆69| 九九视频在线播放 | 性猛交xxxx乱大交孕妇印度 | 风间由美一二三区av片 | 永久免费54看片 | 伊人影片| 黄色美女免费网站 | 色综合久久综合 | 亚洲永久免费 | 天天操 夜夜操 | 天天操天天干天天爱 | 毛片在线网| 久久亚洲精品中文字幕 | 欧美干 | 91成年人视频 | 日韩欧美在线观看一区二区 | 欧美在线v| 3d动漫啪啪精品一区二区中文字幕 | 日韩在线视频网站 | 一级色网站 | 久久久久久久国产精品美女 | 农村少妇久久久久久久 | 色在线免费观看 | 国产av精国产传媒 | 日韩一区二 | 欧美春色| 日干夜干天天干 | 把高贵美妇调教成玩物 | 96日本xxxxxⅹxxx17 |