至從ThoughtWorks的 Martin Fowler 喊出來“微服務”,IT業界仿佛打了一陣強心劑,從互聯網行業,到相對保守的電信,金融業,都在對著自己的系統,拿著拆遷大錘躍躍欲試,想一拆為快。微服務到底給我們帶來了什么,用微服務真的就是萬能解藥嗎?今天就來侃侃這個話題。
這文章本來計劃要寫一篇就搞定,后來發現內容還是比較多,就拆成幾部分來寫,這樣可以寫的更加透徹。
本文假定的讀者是那些已經對微服務有了一點兒了解,并且已經計劃要按照微服務風格進行系統改造了的拆遷預備隊們。
1. 為什么要拆,單片系統的七宗罪
說到傳統系統,大致可以想象成這個樣子,系統在橫向功能上按照模塊分開,在縱向上分成控制層,業務層,數據訪問層等幾層。無論是模塊間的調用,還是功能層次間的調用,幾乎都是代碼級調用。一個系統代碼動輒10萬行起步,極其龐大,我曾經用瑞士軍刀來形容這種系統。
過去幾十年我們一直在開發這樣的系統,我們謹慎的建立業務模型,梳理業務流程,做好每一個模塊的設計,并嘗試做好通用模塊。然后經過數月甚至經年的開發,再花費更長的時間進行各種測試,最后交付給客戶。這種系統集所有功能于一身,什么都能干,用瑞士軍刀來形容一點兒也不為過。
以下單片系統的這些問題會隨著代碼量的增大而變得嚴重,大就是原罪。
當今環境下,單片系統暴露出的不足:
- 代碼規模龐大,難于讀懂,難于修改,難于維護,甚至修改幾行代碼,要做超過預想的大規模測試。
- 開發周期長,很多系統都需要以半年為單位來計算上線時間,對于業務更新頻繁的系統,單片系統模式更是難以應對,尤其是互聯網產品。
- 技術棧單一,通常一個技術棧能夠解決整個系統90%的問題,但是總有那么些特例,讓架構師,讓開發人員費盡腦筋去找一些折衷方案,不能用最合適的技術棧去解決問題。
- 難以部署,一個單片系統功能眾多,配置文件有時真的如滿天繁星,上線那幾天徹夜的日子想必大家都經歷過,上線之前燒柱香,祈禱疏通測試順利通過這是常例吧。
- 某些bug會搞垮整個系統,單片系統內部功能模塊通常共享一個進程空間,如果某個處理破壞了整體運行環境(比如內存泄漏),那系統就會崩潰,影響極其巨大。
- 對客戶反饋慢,從筆者的經驗來講,客戶第一次碰到能動的系統,常常是CUT結束的那個階段,我們叫它 alpha版,但那通常已經是三個月以后的事情了。如果這個時候客戶說這不是我想要的,就需要大返工,將影響后面的結合測試,系統測試,最終影響上線時間。而很明顯的,修改時機拖的越晚,風險越大。
- 高可用要求下,通常以整個系統為單位,進行冗余擴張,也就是完全一樣的系統拷貝一份兒留著當備份,極其浪費資源。而且當系統真正面對客戶使用量潮汐壓力的時候,又很難快速的擴張實例來進行擴容,靈活性差。
其實還可以寫很多,但是為了切題,就不大批特批了,畢竟用了單片系統好多年,不能太過分。
2. 拆分時代的罪與罰
微服務的概念,特征,原則這些東西咱就不掰了。去中心化,各個服務協同,高內聚,低耦合,獨立進化……天天的吹著交付快,部署快,修改快,性能伸縮快,耳朵磨一層繭子。好多人看完了馬丁那書,對著自己眼前那幾十萬行代碼,都躍躍欲試拿著錘子去過一把拆遷隊的癮,但是掄起你的錘子之前先等等,看看下面這一段再說。
以下這些問題,會隨著拆分粒度變細而變得顯著,相對單片系統的大是原罪,微服務小也是原罪。
2.1.真的容易維護了嗎?
拆分以后,各個服務代碼規模變小(也許真的能夠達到數千行的級別),對于單個服務來講可能更容易維護,但是服務之間都使用MQ,RPC來進行通信,要弄懂全盤一樣要跟著調用鏈跑遍整個系統,調用鏈的增長,隨之而來的一樣是難于讀懂,難于修改,難于維護,出了bug難于調查,在這一點上,微服務和單片系統不分伯仲。
還有一點要說,就個人經驗來講,微服務風格實現同樣一套功能,需要的代碼實際更多了(后面還會講哪些變多了),最簡單的例子,有些通用代碼例如StringUtils到處都要寫(你總不能把StringUtils也做成一個服務吧 )。
2.2. 真的更加容易治理嗎?
SOA時代還有一個ESB,要治理服務只要順著ESB這條主線看過去就可以,到了微服務時代,ESB都被丟棄了,想在框架上做好治理,幾乎成為一件不可能的事情,甚至都無法預測將來這個服務要被多少個其他服務調用。
其實用西方的民主制度做比喻非常形象,他們推崇的是每個人都有權利做決定,每個人都應該參與其中,但是這里有一個大前提,那就是每個人都有判斷的能力,得“懂行”。西方的民主可以給自己選一個光明的未來,也可以讓英國脫歐。
2.3. 真的降低了系統復雜性嗎?
這個答案非常有可能是NO,微服務風格下,連數據庫都要給拆開,有些服務之間的技術差異非常大,要畫出系統圖的話,那真是能看到“百家爭鳴”,“百花齊放”的繁榮景象,最后連數據更新事務的一致性都保證不了,還得使用TCC,最終一致性之類的模式來替代。匯總報表要從各個服務數據庫中抽取數據去做統計,有時候連個最簡單的join都做不到了,“跨著數據庫呢大哥,想要數據?用接口來調!”
2.4. 真的節省系統資源了嗎?
單片系統通常部署在一個進程空間內,或者是一個集群內,代碼級別相對調用較多,這是比較節約資源的,雖然這種方式難以擴張,但是在其性能容量容許范圍之內是最快的。微服務風格體系是靠著網絡通信來進行相互調用,從效率上來講,被單片系統甩了不止一條街,系統拆完了以后消耗網絡資源比以前大是肯定的事情。而且因為需要為每一個服務準備隔離運行環境(甚至要準備獨立的數據庫),因此和單片系統相比,CPU資源,內存資源,磁盤資源的消耗也會更多。
2.5. 真的省了錢了嗎?
曾經有一些文章提到過這樣的論點:“微服務降低開發成本。”,但就我個人的實踐經驗來講,并不是這樣,這里用吃飯這個事兒來說這個事兒,“以前做單片系統,就好像吃一頓飯,大家入座,端起碗筷,吃肉,吃菜,喝湯,放下碗筷,離席。”,“如今做微服務,吃飯流程都變了,大家入座,端起碗筷,吃肉,放下碗筷,離席;大家再入座,吃菜,放下碗筷,離席;大家第三次入座,端起碗筷,喝湯,放下碗筷,離席。”,很多項目初始化和收尾的工作都要重復的做,從工作的總量上來講,也是比之前多了,而絕對不是少了。
比單片系統少寫兩點吧,批的太多,連我自己都快把微服務架構扔到垃圾堆里面去了。
(未完待續。。)