.Net微服務實戰之DevOps篇
技術只是基礎
該系列的兩篇文章《.Net微服務實戰之技術選型篇》和《.Net微服務實戰之技術架構分層篇》都是以技術角度出發描述微服務架構的實施。
如果技術選型篇敘述的是工具,那麼架構分層篇講的就是技巧,而本篇要討論的就是原則。一直以來我會給身邊向我探討問題的人灌輸一種理念,沒有什麼技術銀彈,因為我們做的是軟體工程,提供的是問題相應的解決方案,不同型別問題的解決方案是存在著本質上的差異。
繼續提供之前的原始碼:https://github.com/SkyChenSky/Sikiro
PS:該篇文章與.Net無關,其實主要是沿用前面兩篇文章的命名,此外我認為DevOps不是簡單的工具使用,應從軟體工程角度進行出發。
什麼才是優秀的架構設計?
曾經有好幾個同行問過我同一個問題:什麼才是優秀的架構設計?我一直信奉著兩句話和一個定律:
- 架構服務於業務,技術服務於架構
- 康威定律(簡單理解成組織架構的設計等同於系統架構的設計)
架構設計其實就是一種方案的取捨,在有限的資源裡(包括但不限人力、時間)能讓團隊順利的實施技術,同時滿足業務規模的需要,我認為可以稱之為優秀的架構設計,簡單來說兩個字合適
架構核心要素
核心的主要5大:效能、可用性、伸縮性、擴充套件性、安全性。
而我們所討論的微服務,選擇了擴充套件性,犧牲了可用性、效能,擴充套件性的目的就是為了快速響應需求變化、降低系統耦合度、提高系統模組的複用度。而微服務的呼叫是通過跨程序的網路通訊的,跟程序內方法呼叫比無疑是慢了一個單位;原本單服務99.99%高可用,假如現在三個服務就是99.99%*99.99%*99.99%=99.97%。
當然我們可以在基於微服務的通過引入其他技術提高可用性、伸縮性和安全,但是確保無疑是犧牲了效能,除了效能還會在團隊開發效率與運維複雜度上會受到影響。由此可見,沒有萬能技術手段,而架構其實在取捨。
引入一種技術必定帶新的技術問題這是個必然結果,剛提到團隊開發效率與運維複雜度會受到影響,那是否有辦法緩解甚至解決並提高呢?既然涉及到團隊、流程這些關鍵字那麼就應該向軟體工程方向尋找方案,合適架構實施還需要合適的開發模式進行支撐的,而風靡全球的DevOps就是不二之選。
軟體工程
在行業盛傳的一條公式:軟體 = 軟體工程 + 程式,可想而知軟體工程的佔據多麼重要的比重。那麼什麼是軟體工程?百度是這麼解釋的:
軟體工程是研究和應用如何以系統性的、規範化的、可定量的過程化方法去開發和維護軟體,以及如何把經過時間考驗而證明正確的管理技術和當前能夠得到的最好的技術方法結合起來的學科。它涉及到程式設計語言、資料庫、軟體開發工具、系統平臺、標準、設計模式等方面。
我自己重新總結了一個軟體工程的通俗描述,通過多人協作、有目標、有步驟、有計劃的並使用科學方法論指導開發與維護程式的這個過程。也可以用一條公式表達:軟體工程 = 工具 + 流程 + 模式。
軟體危機
軟體工程的出現目的是為了解決軟體危機的。軟體危機其實是當時落後的軟體生產方式無法滿足迅速增長的計算機軟體需求,從而導致軟體開發與維護過程中出現一列的嚴重問題的現象。那麼三次軟體危機是什麼呢?我整理了個表格(詳細可以自行百度閱讀)
名稱 | 時間 | 原因 | 解決方案 |
第一次軟體危機 |
20世紀60年代—70年代 |
使用機器語言或者組合語言在特定的機器上進行軟體的設計與編寫,引出的“抽象性”和“可移植性”的問題 | 高階的程式語言+瀑布開發模式 |
第二次軟體危機 |
20世紀80年代—90年代 |
軟體複雜性進一步升級,需要更好更好的“可組合性”(Composability)、“可延展性”(Malleability)以及“可維護性”(Maintainability) | 面向物件程式語言+設計模式 |
第三次軟體危機 | 2005年至今 | 軟體的發展速度已經遠超於硬體的發展,體現於需求複雜度、技術複雜度、團隊協作 | 更好的工具、開發模式、與協作流程 |
由上可見,軟體的快速發展直接促使了軟體工程上的進步,新的工具、新的開發與設計模式,新的協作流程也隨之而生。
開發模式的發展
我工作多年經歷了多家公司,所經歷的有三種開發模式,瀑布、敏捷、DevOps。那麼這三種主流的開發模式也對應著三個發展階段:
瀑布開發模式
瀑布開發模式是在第一次軟體危機1970時Winston Royce博士提出來。其思想是把專案過程劃分為主要的六個階段:需求收集、需求分析、軟體設計、程式編碼、軟體測試、執行維護。團隊劃分也通過崗位職責進行劃分:產品團隊、開發團隊、測試團隊、運維團隊。到目前為止該開發模式仍然用到做專案制的開發團隊。
那麼其優點與劣勢也很明顯,優點是計劃明確,職責清晰,按部就班的完成就好。缺點是週期容易拖得太長,不容易調整變更,每個人只為自己職責範圍內的負責,跨部門溝通成本大(這就是為什麼我在圖裡畫了兩堵牆的原因)。我自己呆過一個瀑布模式的團隊,在專案立項後就會被專案經理調動資源成為團隊,而開發人員只會在這一次批次負責編碼與修改測試反饋的問題,基本上上線後的問題跟你無關(除非緊急嚴重的),其他的BUG也許是下一個批次的另外一個開發人員幫你填。
敏捷開發模式
準確的說敏捷開發是一種價值觀和原則的體現,2001年17位IT大佬想把瀑布發模式這種重量級的開發過程替換成一種更加輕量級,可惜大家都沒有達成統一意見因此把各自都認同的觀念整理出來成為敏捷宣言。
敏捷開發其實把產品、開發、測試三種崗位職責的人緊密的聯絡了起來,由原來長週期的大目標拆解成了一個個短週期的小目標。他之所以快,不是因為寫程式碼快了,而是節省了很多不必要的前置條件與返工,同時小步快跑的交付也可以提高團隊的士氣,一個長週期專案那枯燥、乏味、痛苦的過程,誰試誰知道。
舉個例子,大家都是為公司的同個產品努力,沒有什麼合同談判可言,只要需求要求相互瞭解清楚並且可行就可以開幹了。寫詳細設計文件的時間,還不如花時間多溝通下需求的核心點,想辦法設計得更容易滿足需求。短週期的交付後,產品與客戶就可以及時的檢視交付效果並相應的優化與調整。(快速響應並不代表隨時隨地接受變更響應,可以統一歸到下一個迭代週期,我不贊同拍拍腦袋的變更,自己都沒清楚的功能怎麼說服客戶使用?)
敏捷開發的最大好處之一就是短週期的持續交付,這樣方式能在現階段的網際網路行業得到更快速的響應與市場的搶佔,同時能很好的進行技術改進與試錯。但是這種”野蠻的“方式會讓開發團隊與運維團隊形成一條鴻溝,而鴻溝的形成主要原因是運維團隊希望軟體的運作是可靠的,所以他們對資源的變動、新技術的使用尤為的小心、謹慎。
我曾經呆過一個敏捷開發團隊,生產出了問題運維團隊會自行去修改配置,當然會越改越錯了,而且一天釋出次數多了,就會起爭執。
DevOps
DevOps可以看過是敏捷的擴充套件與延申,它的出現就是為了解決開發團隊與運維團隊的那條鴻溝,只要存在人工處理的方式擔心的問題總會出現,同一段程式無論執行多少次相同輸入的輸出總是一致的,但是人的處理卻不能保證,那麼使用自動化改善協作的過程,鴻溝自然就跨越了,。那麼開發團隊與運維團隊就可以為相同的目標與方向而努力。而組織架構也將演變成如下:
從上圖也與開頭的康威定律做了一個很好的呼應。
我是如何實施DevOps的?
技術
這個角度是大家最樂意去關注的,在我們團隊主要使用了以下技術,指令碼什麼的我就不花時間貼出來了,在我看來工具的使用,只要花點時間就能解決。
型別 | 名稱 |
持續整合/持續交付 | Jenkins |
原始碼管理 | Gitlab |
雲平臺 | 阿里雲 |
軟體包管理器 | 私有Nuget |
程式碼檢查 | Reshaper |
容器化 | Docker |
分散式鏈路跟蹤 | SkyWalking |
日誌系統 | ES+Filebeat+kibana |
系統監控 | Prometheus |
原本程式碼檢查想引入SonarQube代替人工檢查+Reshaper,可惜於伺服器資源不足。
對於一般的團隊,我建議優先從Gitlab+Jenkins搭建好完成CI/CD,其次把日誌系統給完善起來,這兩者完成得越早,給團隊帶來的收益就越高,後續才會有更多的時間來完善整套技術體系,這是一個良性的迴圈。
人
人延申出的就是團隊與文化,經過上面的講解大家都意識到軟體工程就是一樣多人協作的工作,只有團隊目標一致,共同負責承擔團隊的專案,願意一同與專案成長才能很好的實施DevOps。就像多匹馬拉車一樣,只有它們都有共同的目標的時候才能快速拉車到目的,如果他們一匹向東一匹西,只會讓馬車無法前行甚至四分五裂。
在我的團隊,因為在招聘人員的時候已經進行過了篩選,所以在合作上非常的順利,當然我也經常在例會和業餘的時候都會給大家傳達思想,讓團隊成員真正的從實際意義上去理解現在的做法。
對於已經成型的團隊來說如何去落地呢?無非三種,激勵、考核和逐步試行。如果有條件的公司可以設定獎金激勵,如果有績效考核的可以將DevOps實施納入考核目標,如果兩者都沒的,那就選取團隊裡願意改變的同事進行試行,使用過後都說好的那麼更會有說服力。
流程
為了落實了文化的改進與技術的使用的這個過程,我們需要科學的、有步驟、有計劃的方式完成這項工作,並且可以讓這套標準化的方式可以重複使用到其他專案上。
在我的團隊是有產品、前端開發,後端開發、測試、運維組成的。我採用了原型模式+DevOps模式:
- 產品人員會優先使用Axure RP工具把需求整理產出原型並與需求方確認。
- 產品確認好的原型就是我們技術的輸入,技術拿到需求後會做一次需求評審,主要是排查需求疑惑和確認需求目標。
- 需求明確後,由我使用Visual Project任務拆解與排期,任務會建立在我們的專案管理系統Redmine上,如果任務週期過程,我會拆分成多個可交付的短週期,一般會控制在2個星期內。
- 接到任務後,大家就跟根據自己的任務使用PowerDesigner資料庫設計(早期是由我獨裁設計,後期團隊發展壯大了,就由業務負責人各自設計),在這個階段,如果有新的服務與新的工具庫需要部署,我就會正面與運維溝通讓他把自動化給完成。
- 因為我們是前後端分離的,所以我們使用了Swagger減少了寫介面文件的時間,所有任務是否完成以前端是否對接好介面為主導,前端對接好後,就會在Redmine修改自己的任務狀態並新建一個測試任務給到測試。
- 測試會根據自己寫好的測試用例,進行對完成的任務進行場景測試,如果有BUG會在Redmine提給相應的人進行修改。一般會先由前端人員排查是否是他的互動上的BUG,如果確認是資料問題那麼就會轉給後端開發,開發人員定位BUG時,可以通過我們的SkyWalking和Kibana聯合定位問題,定位問題時間一般都在2-10分鐘。
- 程式碼合併到測試分支後就會通過Jenkins釋出到測試環境,生產環境的釋出是合併到生產環境後手動確認釋出的。
除此之外,每週一會有一個例會內容不限工作,也可以分享週末去哪裡娛樂了。在該迭代週期快到結束的2-3天會開一個進度會議,看看大家完成情況。因為公司沒有下午茶,所以我們自己通過玩搶紅包領到最大的兩個的請吃下午茶,最少一星期一次。
結束
該篇到這裡就分享結束了,也是該系列的最後一篇,我曾經認為技術與管理必須二選一,自從我成為了一個技術與團隊的負責人後,終於讓我認識到,一個優秀的技術思想還是需要一些管理手段才能很好的實施,而我們的技術管理無非就是軟體工程。