系列文章
前言
本文於 2022.6.22,首發於ITPUB 官方公眾號,作者陳珙,未經授權禁止轉載。如需轉載,請聯絡 ITPUB 公眾號。
開始前我跟大家分享個自己的小故事,大概1年多以前,我給某個企業培訓微服務實戰,既然是實戰當然是從實施落地出發。但是培訓完畢後,甲方卻反饋我對微服務的概念講得太少了,他們壓根不知道什麼回事。開始我以為他們只是謙虛客氣一下,因為我認為已經到了202X年了,微服務或多或少都瞭解一些,但是並非如此,經過我和其他同行溝通來看,我的想法確實以偏概全了。
所以我趁著這次和ITPUB 合作,把以重新理解微服務從他的過去、本質出發跟大家分享自己一些見解。這篇文章原本1萬7千多字,經過和DTCC的韓老師溝通後,最終拆成了兩部分,下星期會再發另外一篇。
溫故而知新
不少同行,對於“什麼是微服務”,都在各平臺發表過相關理解、看法等。隨著這些年的技術發展,只要涉及到“微服務”這三個字已經不再純粹,幾乎無論是什麼方向技術,或多或少會跟微服務扯上關係蹭蹭熱度。當然,也恰恰基於此,使得我為何重提何為微服務,並且單獨拿出從多個方面結合我的個人見解,想與大家深入探討。
先開頭這裡,就丟擲我自己的一個觀點吧,我並不認為非要把技術弄得多複雜,才顯得多牛X。再複雜的物品也是由一件件簡單的物品元件形成的,而適當的返璞歸真才能看清楚事物的本源。
若要想要更清晰地瞭解、理解、搞清楚“微服務是什麼”,我認為只需要認真看懂一篇文章就足夠了——2014年馬丁·福勒個人部落格發表的《Microservices》博文(https://martinfowler.com/articles/microservices.html)
但是,馬丁·福勒所著的作品多數是高度總結的,假如你沒有親自實踐過,他的作品與思想理解起來相對比較困難,因為他的敘述總體比較抽象。當然,這不影響我自願重複多次的閱讀他的作品——溫故而知新。
因此該篇我不會照搬翻譯,或是人云亦云,而是會從《Microservices》原文和其他書籍收集回來的資料並結合我的個人見解,來敘述微服務的What、When、Why。
這篇文章沒有微服務的How,可能您看完了也不知道應該怎麼去實施微服務,但是關係不大,因為我一直堅信,如果你能把某件問題的來龍去脈,清晰無誤、通俗易懂地傳達給別人,該問題已經解決了70%,那麼剩下30%就是尋找解決方法的路上。方法遠要比遇到的問題要多得多。如果您對具體的微服務實踐有興趣,可閱讀完該文後請移步到《.Net微服務實戰》(https://www.cnblogs.com/skychen1218/p/16352324.html)進行擴充套件閱讀。
本篇文章,我將通過選擇微服務的原因、微服務的小歷史、微服務的特性和我對微服務的個人見解多個角度,分享我對微服務理解的What。你可以總體瀏覽下大小標題,快速過一遍。抑或是期間挑自己更為感興趣的部分,直接跳到那裡看。
選擇微服務的原因
說到這,我想先問這樣一個問題,你選擇微服務的原因有哪些呢?可能這問題的回答會百花齊放,無論是哪種原因,促使我們選擇微服務終須一個或多個的理由。凡是做任何一件事情,都要有目的性,不可盲目,否則只能是毫無價值的冒進。因此在這我給大家分享下我選擇微服務的理由。
單體應用的優與劣
在早期的開發,單體應用給開發提供了很多的便捷性:
- 開發簡單方便;
- 專案管理集中;
- 程式內除錯,排查、定位問題更加便捷。
隨著團隊與業務規模的增加,單體應用的缺陷就會越發的明顯,以我個人實踐經歷,如果希望引入微服務,我認為得滿足以下任意3點,則可以考慮選擇微服務:
- 並行開發的程式碼衝突;
- 載入、編譯、部署專案緩慢;
- 程式碼耦合性越來越高;
- 需要統一資料讀寫入口;
- 無法按需擴充套件。
我早些年遇過10人並行開發共有兩三百個專案的解決方案,不論是每次專案載入、編譯、部署,其實都非常花時間。只要並行開發就會存在衝突,修改的程式碼資源越集中,出現合併衝突概率還越大。
在單體應用裡,我們會以“庫”的方式形成元件,以此來進行單元複用,如果在同一個解決方案裡共享複用,使用與修改的自由度會更高。
任何事情都會有利弊的,隨著專案的發展,參與的人越多,迭代的頻率越高,那麼“庫”的職責邊界就越不清晰,程式碼耦合也會越發嚴重。而且因為專案多了,為了方便複用,不同的“應用”引用相同“庫”的情況也自然會變多,這樣就導致了資料的讀寫入口擴大,假如資料出了問題:
- 不好定位原因。
- “庫”出了問題,相關引用的應用都得重新發布或回滾。
微服務的優點
微服務的優點有不少,但是我認為核心優點是獨立部署與協議統一,而其他的優點都是基於兩者之上進行擴充套件的。因此本小結會著重敘述這兩點,剩下的優點我將會在下文結合微服務的特徵再進行詳細敘述。
微服務其中之一的優點——獨立的程式部署,以軟體工程的角度出發,從物理層面約束了團隊職責,刻意地劃分了業務之間的邊界,每個開發組(人員)都會清晰瞭解各自的領域與職責,使得大家優先思考清楚需求的修改點,該由哪個業務組負責。
另外其中一個優點——資料的讀寫訪問統一協議,以技術設計的角度出發,資料的讀寫操作都被封裝成Http API以此隱藏了技術細節,能大幅度降低呼叫端的技術人員,對非所屬業務模組的細節關注,從而把他們注意力轉移到所屬的業務層面,減少認知負擔。
此外,還可以避免非所屬業務的技術人員對資料結構做出了不恰當的修改。
總得來說,微服務從工程化的層面解決了不少單體的“老大難”的問題,但是,既然沒有“銀彈”的存在,那麼“新”的技術同樣也會帶來更多新的挑戰,具體的新問題,我將單獨拿出來放到新的一篇文章,跟大家詳細地分享下,接下來會跟大家分享一下微服務的過去。
微服務的一些小歷史
雖然微服務無論是從理論還是實踐上解決了不少單體的“老大難”的問題,但是它並不是一門新的技術,它的誕生年份得追溯到2005年,而它的設計思想得追溯到Unix的哲學思想,因此,要想了解一樣事物的本質,那麼就應從它的歷史發展說起。
維基百科截圖
提到微服務,馬丁·福勒這個名字肯定不能忽視,不少人認為馬丁·福勒創造的微服務。對於該錯誤的認知,我認為我有必要應該重新說明下。參考了維基百科(https://en.wikipedia.org/wiki/Microservices#History),我把微服務發展歷史整理成了時間線。
時間
|
事件
|
2005年
|
Peter教授在Web Servces Edge大會提出了“Micro-Web-Services”
|
2007年
|
JuvalLöwy在他的著作與演講建議用服務構建系統,並意識到細粒度因此擴充套件了WCF。
|
2011年
|
一個軟體架構工作組在威尼斯附近舉行的軟體架構師研討會上使用了”Microservice”來代表這種架構模式
|
2012年
|
Jame Lewis針對微服務概念在某大會發表了演講
|
2014年
|
Jame Lewis 和 Martin Fowler合寫了關於微服務的一篇學術性文章
|
上文我們可以總結出三個核心關鍵點:
- 微服務的起源最早追溯到2005年;
- 微服務不是由馬丁·福勒他本人創造的;
- 那篇舉世聞名2014年寫的《Microservices》原文是由詹姆斯·劉易斯和馬丁·福勒他們兩人共同合作編寫的。
雖然說微服務架構並非馬丁·福勒所創造的,但是稱《Microservices》這篇文章是推動微服務的崛起的緣由,一點都不為過,而詹姆斯·劉易斯和馬丁·福勒兩位對微服務的盛行起到了非常關鍵的作用。
微服務的特點
上文結合了維基百科分享了微服務的小歷史,同時也為微服務、馬丁·福勒和《Microservices》原文三者之間的關係,做了個簡單敘述,以便大家更加清晰的認識。
原文的九大特徵
既然已經瞭解了微服務的過去,那麼接下來得了解它是什麼。馬丁·福勒曾經在《NoSQL精粹》寫過一句話,他並不喜歡給某件東西下定義。因此在書裡,他對於NoSQL總結幾大共同特徵,而擁有這些特徵的儲存系統可以稱之為NoSQL。
同樣,他在《Microservices》原文裡,對於微服務架構風格也總結出了微服務具有的9種特性(詳細請看下文),而我結合了資料與實踐提煉了一下關鍵字也總結了4個關鍵特徵:
對於原文裡的九種特徵,還有一段更加精煉的總結。大家看的時候可側重看我提煉和加粗的關鍵字,稍後我會結合原文與我的個人總結說一下,以便於幫助你快速抓住分享要點。
原文:
The term "Microservice Architecture" has sprung up over the last few years to describe a particular way of designing software applications as suites of independently deployable services. While there is no precise definition of this architectural style, there are certain common characteristics around organization around business capability, automated deployment, intelligence in the endpoints, and decentralized control of languages and data.
In short, the microservice architectural style [1] is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.
譯文:
“微服務架構”一詞在過去幾年中出現,用於描述將軟體應用程式設計為可獨立部署的服務套件的特定方式。雖然沒有對這種架構風格的精確定義,但圍繞業務能力、自動化部署、智慧端點以及語言和資料的分散控制的組織具有某些共同特徵。
簡而言之,微服務架構風格是一種將單個應用程式拆分為一組小的服務,每個小的服務都在自己的程式中執行並與輕量級機制(通常是HTTP REST API)進行通訊。這些服務圍繞業務功能構建,並且可以由全自動部署機制獨立部署。這些服務幾乎沒有集中式管理,它可以用不同的程式語言開發,並可以選擇不同的資料儲存技術。
我總結的四大特徵
從上面兩段原文,我們可以從中提煉出五小句關鍵表述:
- 由單個應用拆分為一組小的服務(small);
- 每個服務在獨立的程式執行,服務之間使用輕量級的通訊機制(lightweight);
- 服務圍繞業務構建,同時服務可以自動化獨立部署(independently 、automated);
- 可以使用不同的程式語言和資料儲存(different)。
對於以上五個關鍵詞和九大特性,我重新總結了自己的經驗並得出以下四個特徵:
- 輕量級(lightweight、small),通訊協議和服務應用自身都應該是輕量級的。
- 自治性(independently),能獨立部署執行,且低耦合,服務之間互不影響。
- 異構性/去中心化(different),可以根據業務特殊性,選擇合適的開發語言和儲存系統。
- 自動化(automated),可以由全自動部署機制獨立部署。
總地來說,我給微服務的定義是:從軟體工程的層面解決了專案臃腫、並行開發衝突、程式碼耦合度高的問題,並且它具有輕量級、自治性、異構性、自動化四大核心特性的架構風格。接下來,我會根據上述自己總結的關鍵詞和架構設計方法論,跟大家分享一下我對微服務的理解。
業務與團隊
我曾經在《十年技術進階路,讓我明白了三件要事》一文提到一句話,我認為可以引用到我們們做架構設計:
做任何事情就如同我們們寫程式碼Function一樣,得有輸入同時也得有輸出,輸入與輸出之間還得有執行。
業務需求與組織架構是架構設計的兩大核心輸入,具體原因有以下四點:
- 設計沒有對與錯,只有合適與不合適;
- 業務需求瞭解度越高,設計合適度則越高;
- 在能滿足需求的前提優先選擇簡單、合適的方案,避免過度設計;
- 技術選型應需要考慮自己的團隊是否足以支撐。
在《Microservices》原文提到的其中兩大特徵是與之有關,因此我打算放在一起敘述:
- 圍繞業務能力劃分團隊(Organized around Business Capabilities)
- 是產品而不是專案(Products not Projects)
我從原文中的兩大特性裡分別提煉了兩個核心句:
- 誰構建,誰維護(you build, you run it )
- 康威定律(Conway's Law)
業務
早些年我呆過專案制的公司,所有的專案組的成員是通過資源調配臨時組建的。職責劃分也很清晰,開發部門完成後就QA團隊測試,QA完成測試後就交給運維部門負責運營。批次完成後,該專案由誰會繼續參與後續批次的開發與維護,一切都是未知的,而眼前的專案如同一次性產物一般。
然而在微服務裡,更加希望的是團隊的生命週期與產品的生命週期是一致的,誰構建,誰維護(you build, you run it ),這樣做的好處有三點:
- 該團隊成員更加熟悉業務,就如前面所說業務是核心輸入之一。
- 對系統、產品有一個持續演進與迭代,這樣才會有足夠的資訊與瞭解,才足以讓系統與產品作出更加合適的優化與設計。
- 減少跨職責部門溝通的成本,同個業務組所有的成員都會為同一個產品負責,這賦予了他們責任心與共同的目標。
團隊
從以上三點也引出了康威定律(Conway's Law)。
原文
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure
— Melvin E. Conway
譯文:
任何組織在涉及一套系統(廣義概念上的系統)時,所交付的涉及方案在結構上都與該組織的溝通結構保持一致
— 梅爾文·康威
用通俗的話描述意思是:其組織架構等同於系統架構,舉個例子,該應用是前後端分離的,那麼團隊得有前端和後端開發,如果該團隊與其應用實施了DevOps,還得有運維開發人員等等。
團隊會隨著產品的演進而變化(擴招,縮編),而原文裡提到了兩個披薩原則,建議一個團隊6-12個人的大小。從我個人的經驗來看,一個人的溝通渠道大於5個以上,溝通佔據工作上的比例則呈指數級的增加,如果一個團隊少於2人,又容易形成單點問題與壓力,因此我認為3-5個人是一個比較合理的小組規模。
我曾經跟某企業做技術交流,他們的開發人員是一個人負責多個服務與專案,結合上文敘述的經驗角度來看,存在以下三個問題 :
- 一個人負責多個意味著微服務拆分過細,這個時候思考是否有必須這麼細的粒度拆分;
- 容易造成人員單點維護的問題,容易形成“知識孤島”、“非他不可”的局面;
- 應該為團隊定相同的目標,共同為業務系統負責。
小結
上文我主要從軟體工程的兩個角度(業務需求與組織架構),分享了對微服務的理解。
微服務雖然改變了系統、服務之間的架構模式,但也需要足夠的組織架構和軟體工程與之支撐。技術服務於架構,架構服務於業務,業務服務於商業,這是我架構設計以來堅持的原則,一切的技術與設計,最終用來服務於業務需求,反之,也是商業與業務成就了技術,拋開業務討論的技術與架構無疑是“耍流氓”的。
抽象與複用
我認為抽象思維,是我們程式設計師最基本也是最核心的思維方式,抽象思維結合了共性、類比方法,從問題的“質”的角度進行分析與思考,讓我們的關注面主要放在物件、動作與關係,使我們減少了因為具象的細節引起的鑽牛角尖的情況,恰好架構設計需要我們具有大局觀的能力,而大局觀的本質正好是抽象思維。
抽象性
從架構設計思想的抽象角度出發,我認為架構設計的目的主要有三點:確定運作方式、確定職責邊界與確定互動方式。
回到微服務,分而治之的本質思想就是"拆",拆是為把耦合性較低的模組是獨立成程式進行運作,拆後還得整合把具有關聯的服務給組織起來。因此上文的三個設計目的和《Microservices》原文與之對應的三大特性為:
- 通過服務代替元件(Componentization via Services)
- 分而治之(Decentralized Governance)
- 強服務和弱通訊(Smart endpoints and dumb pipes)
複用性
在早些年微服務還沒盛行的年代,我們或多或少接觸的應用,他們引用公共模組是通過"庫"的方式提供的,使用“庫“的是為了把具有共性的(抽象性)邏輯模組分離出來,以至於達到物理層面的複用,我們稱之抽離出來的單位叫元件(Componen)。
原文:
When talking about components we run into the difficult definition of what makes a component. Our definition is that a component is a unit of software that is independently replaceable and upgradeable.
譯文:
在談論元件時,我們遇到了如何構成元件的困難定義。我們的定義是, 元件是可獨立更換和升級的軟體單元。
然而使用這種“庫”方式會兩個缺點:
- 如果一個應用引用了10個“庫”,任意一個“庫”更新了,整個都需要全部更新上去。(一應用、多個庫)
- 如果一個“庫”被多個應用引用,如果該“庫”出了問題,每個涉及到的應用都更新一遍。(多應用、一個庫)
由於以上的問題,我們把這些公共引用的"庫",改造為可獨立部署的程式進行運作,可獨立部署就意味著,只要保證服務之間的通訊協議統一性,剩下服務內其他實現,我們就可以自由發揮了——技術異構性。
技術異構性
我認為在資訊系統角度的技術異構性主要分四個層面:硬體、作業系統、開發語言、儲存系統。在《Microservices》原文[Decentralized Governance]模組提到,不希望開發人員擁有錘子後,就把任何問題視為釘子,通俗點說,就是希望我們根據不同業務場景、解決方案,去選擇對應的技術或開發語言。
因微服務的自治性,給與擁有服務的團隊按需部署與選擇技術棧的機會,讓他們委派決策和控制權,我將從戰術與戰略兩個角度出發跟大家分享我的觀點:
從戰術層面出發,每個技術人員都會有自己擅長的方向,或許有些人認為,更新換開發語言、更換技術方向不就是換個工具而已這有什麼難的?我認為,更換技術方向成本並不在於語言,而是在語言所屬的生態與改技術方向的思維。
舉個例子,C#可以寫做客戶端與服務端,但是客戶端與服務端的技能生態、設計思維有著本質上的區別。如果是服務端的從C#轉Java因語言的特性相似,無疑成本是非常少的,但是我們得熟悉Java語言的生態,例如主流框架、工具、外掛等,甚至得踩一遍底層上的坑,例如JVM調優等。
因此,我認為並不存在在某個領域方向很厲害的人,在別領域也同樣厲害的說法,經驗、知識都是需要時間、實踐進行積累的。
再進而回到微服務上,我們並不會刻意去製造技術的異構性,在相同業務領域裡,在原有的成熟技術並且能滿足業務需求情況下,我建議不要刻意去更換,特別是整個團隊。
從戰略層面出發,我們關注的是團隊與架構,團隊與架構都有個共同點,抉擇與取捨。在有必要的時候,我們根據業務的發展情況按需擴充套件。
舉個例子:假如現有公司的已有完整的業務模式,需要基於已有的業務繼續發展,作為團隊負責人的你,對於技術團隊採取的策略主要兩點:降本與提效。
因此你增加原本團隊成本30%基礎上成立了一個ToB的低程式碼團隊,在未來半年內出第一個Beta版本,並在一年內投入公司內部生產使用,且預計提高後臺系統的300%的開發效率。低程式碼開發平臺,則選擇小組組長最熟悉的.Net平臺開發,而原有Java團隊交接了後臺系統的專案,團隊人力成本根據業務情況相應的減少10%-20%。
Not Only SQL
上文的異構性主要從開發語言與技術選型角度進行敘述,如今這個年代,無論做什麼型別的資訊系統,基本上離不開儲存系統。
NoSQL的特徵與型別
20世紀80年代,關係型資料庫陸續誕生以來,佔據著儲存系統的主導地位。隨著21世紀的網際網路崛起,關係型資料庫在高併發與海量資料的場景上,表現的力不從心,而NoSQL的高效能、橫向擴充套件性、多種資料庫結構等各種優點,彌補了關係型資料庫的不足。在如今的年代混合儲存的模式已經是隨處可見,NoSQL與關係型資料庫的關係,也成為了相輔相成的存在。
馬丁·福勒早些年著作的一本書名為《NoSQL精粹》,其中他對NoSQL無法下具體的定義,但是他認為有以下特性的可稱之為NoSQL:
馬丁·福勒在書中也總結出了共有四種型別的NoSQL,但我個人認為搜素引擎應作為第五種的補充:
去中心化儲存
我們們越是保證了微服務的自治性,去中心化的優勢越是更加明顯,微服務其中一個特性是非集中式資料管理(Decentralized Data Management),微服務可以根據領域內的業務特點選擇合適儲存系統,就如上文所提到的技術異構性的儲存系統。
關係型資料庫在高效能、海量資料與擴充套件性會有一定的侷限性,因此現有的網際網路系統不單純把關係型資料庫作為它們唯一的選擇,混合型儲存才是未來的主流。
簡單舉兩個例子,鍵值型的Redis作為代表,可以存放會話資訊、購物車、快取等臨時性的熱資料。搜尋引擎以ElasticSearch為例,可以代替關係型資料的Like搜尋,也可以作為海量資料業務的Query端的儲存。
我們們後端開發的核心關注點,主要以資料讀寫為主。毫不誇張地說,如果後端開發能把常用的儲存系統(關係型與非關係型)瞭解清楚,在對應的業務場景的選擇合適的儲存系統,此外對已有的業務,能根據業務特性提出優化方案,相信我們在日常遇到的80%問題都能迎刃而解。
因篇幅有限不再做具體敘述,我這裡提供兩篇曾經記錄儲存系統優化的文章,可以供大家參考《後端思維之資料庫效能優化方案》和《記一次引入Elasticsearch的系統架構實戰》。
總結
到這裡,今天這一講就已接近尾聲了。關於前面分享的諸多內容點,為了幫助你快速回顧、梳理、思考,我將全文內容的行文框架、每部分側重講解的內容等,整理到圖中,這樣看的時候,也更直觀、明晰,以便於幫助你理解、記憶。
整篇文章的篇幅稍微有點長,最後結合我今天分享的內容,再與你交流下我的一點想法、觀點等,此外也算是進一步給大家做了個文章的升級版總結。
從微服務的發展來看,微服務不是馬丁·福勒創造的,但是他在推動微服務的發展方面,還是起到了非常重要的作用的。我不是馬丁·福勒老爺子的黑粉哈,我還是非常建議大家多看幾次老爺子的作品,每次看都會有新的感悟。
雖然我自己很喜歡微服務,包括我最近的時間技術關注點都在微服務上。當時我仍然認為微服務並不能解決一切的技術問題,還是那句老話——沒有銀彈。微服務給我帶來了不少的良性成長,但是我也不會逢人就吹噓它,因為微服務有它的優缺點,我們得對結合具體問題選擇方案,而不是強行地把方案硬塞到某個問題上。
毫不誇張地說,80%的資訊系統,甚至可能到90%,如果從客觀中立的角度出發、分析,都是不需要用上微服務的。因此,要是您選擇了使用單體,正在處理您的專案問題,這並不是一件丟人或者覺得很low的事。
我個人認為微服務的引入,更加側重的是從軟體工程的角度出發考慮的,大家可能聽到的什麼效能問題啊、高併發啊或者別的問題,選擇微服務更多是充分不必要的。
另外再提一嘴,微服務它的本質是無法解決效能問題和高併發的,大家在這裡可以停下想想,資訊系統的效能問題主要瓶頸在資料庫,所以調優方案應該從儲存系統的型別、設計、架構方案進行選擇;高併發方案,無非是從叢集、NoSQL、靜態和訊息佇列這些角度出發進行選擇。只不過微服務實施後,它的自治性特徵,可以使得系統在這些高效能和高併發的場景中,擁有更多的擴充套件餘地。
好了,到這裡我們就要結束了,非常感謝你耐心的閱讀,後面的分享再見。同時期待後續的某幾個時段裡,我與你能夠有更多思想上的交流、碰撞。如果願意分享,這一講也歡迎轉發給你的朋友,和他一起討論。還有,對這一講的內容分享,有疑問或是不同的差異化、多元化想法,可以提出來,留言區裡,我們多交流。