土味微服務
前段時間有大佬邀請,參加了一個微服務方面的交流,期間大放厥詞,回味起來意猶未盡,整理一稿出來,博諸君一哂。
扯一扯定義
單體應用(monolithic application)這個名詞,是經常被拿出來和微服務做比較(吊打)的。知己知彼百戰不殆,在說微服務之前,似乎蠻有必要了解一下這個老對手的情況。
按照 Google 程式設計師的常用抄襲手段,我在 Google 搜尋 monolithic application
,選一點結果摘錄如下:
In software engineering, a monolithic application describes a single-tiered software application in which the user interface and data access code are combined into a single program from a single platform.
Monolith means composed all in one piece. The Monolithic application describes a single-tiered software application in which different components combined into a single program from a single platform.
根據上面的陳述,會發現很難對單體應用做出一個精準的判斷, single program
、 single-tiered
放到真實世界中,除了單伺服器、單程序的小網站之外,這種情況似乎很難看到。在面對幾十幾百臺伺服器的時候,我想大概沒有架構師會有興趣讓幾百臺伺服器都跑同一個 WAR 吧。
對手身份不太明確,那麼會不會是個兔死狗烹呢?微服務的定義又是什麼樣的呢?下面是 Martin Folwer 給出的定義:
In short, the microservice architectural style 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.
小有多小,輕有多輕,全自動的範圍有多大,去中心化到底有怎樣的自治,似乎也都讓人摸不到頭腦。
雖說概念沒有一清二楚,然而從上述的定義來看,微服務是對一些既有的觀點進行了強調的:
- 以業務為中心
- 多技術棧共存
- 輕量協議互訪
- 去中心化
據此,我對微服務這個風向的理解,是在傳統軟體的設計開發體系基礎之上的一種變化,相對於翻天覆地的變革,我更願稱之為一種改良。
是誰坑了瀑布流程
人人喊打的瀑布流程,在我看來,面對的是一種類似讀書時候經常提到的 理想狀況
:
在理想狀況中:
- 需求是清晰而持久的
- 基礎設施都是穩定的
- 依賴服務都是靠得住的
過往的開發過程在這種理想狀況中,是具備非常多的好處的:
- 單一的技術棧有利於人才招聘、培養以及技術積累。
- 少量的業務程序對釋出、運維都有較小的壓力,並且內部呼叫效率更高。
- 集中資料的好處更是車載斗量,安全、事務等方面有極大的優勢。
然而世界發生了變化,廉價伺服器包打天下,IT 人滿坑滿谷,業務日新月異,新技術層出不窮,使用者漫山遍野,這一切因素疊加起來,都讓以前重如千鈞的需求變得相當輕浮。
結果現在越來越多的開發過程,變成了這樣:
所有的環節,都隨時面臨變化的衝擊:
- 既有需求尚未完成,已經產生變更。
- 設計開發過程受到新技術新方法的衝擊。
- 測試標準、交付標準的變化。
- 執行環境升級和故障響應要求。
種種變化歸結起來:
硬體和人力都變得廉價,變更頻繁並且範圍更大。
快速的變化除了產生需求之外,還讓黏連在一起的大程序難於適應:
- 不同業務之間的信任關係會發生變化。
- 共享資料容易汙染。
- 多小的程式碼變更,都可能引發大量的測試和上線動作。
- 特定業務場景無法使用最優技術棧進行實現。
- 必須同步進行縮放。
除了上述的外部因素之外,開發團隊和交付物自身其實也同樣的不理想:
- 牽一髮而動全身的共享程式碼庫。
- 不嚴格的元件邊界,可能導致不同業務互相干擾。
應對思路也順理成章:
- 越長的流程越容易被變化擊中,換句話說,越短的流程越容易完成。
- 縮短的流程,決定了交付物體積縮小,但是並行開發的需求大增。
- 並行開發的過程,要求有多團隊協同工作。
- 多團隊的結果就會導致擴充套件技術棧、去中心化的要求。
更小的交付物,和更便宜的伺服器勾搭起來,產生了大量執行小程序的廉價伺服器,自然也就催生了“民用”的分散式計算。
如此一來,各種叢集、各層協議、各種分散式框架就成了剛需,產生了空前發展。
從“集中力量幹大事”,到“各村有各村的高招”,這種變化自然是 為了滿足客戶需要 。
沒有 Silver Bullshit
按照前面提到的思路,我們:
- 把程序內的元件拆成獨立服務。
- 獨立的服務執行各自的程序。
- 原有的程序內呼叫變成了網路呼叫。
- 各個服務可能採用不同的技術棧來實現。
- 每個服務獨佔儲存自己的儲存。
大的有點不好,小的就一定好麼?各自放飛的微服務,有了各自的實現、釋出、伸縮的彈性,是不是就一定好了?
- 更多的伺服器,和相關設施,代表著更多的故障。所以微服務經常強調的是面向故障進行設計。
- 分離的資料,相對於原有的單一資料庫來說,事務保障變得複雜無比。
- 大量的程序會給運維工作帶來很大壓力,急需監控和自動化的大力支援。
- 單一業務的呼叫序列大幅延長,除錯優化難度也一定是大大增加了。
- 散亂的技術棧,會大幅提高技術管理的難度,降低知識的複用性。
- 獨立的程式碼庫,很明顯會降低程式碼複用的可能性。
由此看來,這種拆分並非只賺不賠的好買賣。是一個需要權衡的事情。不論微服務的數量有多大,個頭有多小,作為一個獨立的交付物,都還是需要遵循既有的軟體開發技能和規律的。那麼問題來了——對於給定的系統,到底應該有多少個微服務,每個服務有多大呢?
前文說道,我更願意稱微服務為一種改良,他是一種應對變化的手段,而非特徵。在如今的情況下,不管是對新業務實現的設計,還是對既有系統的重構,任何架構師都不會把明明應該拆分的東西硬性的合併到一起。所以這個分離的標準就比較重要了。
拆還是不拆,這是個問題
很明顯的,微服務的設計不是一個靠數量取勝的事情,所以重點不是能拆成多少塊,而是什麼東西需要拆,下面列出我所知的幾個影響因素。
組織機構
利益人的識別,在各種軟體開發過程中都是很重要的一個環節,在微服務中也是如此,而且尤其重要。當一份交付物存在多個利益人,並且互相之間不存在管轄關係的時候,就表明當前交付物的邊界出現了問題,面臨著令出多頭、需求干擾的風險。
伸縮需求
同一個程序之內的不同業務功能,有時在業務量方面會出現較大的差異,具體要求的程序數量會有較大差別,這樣的模組鎖定在同一程序之內,勢必會造成資源的浪費。
部署頻率
這個很容易理解,同一個交付物內不同的元件有著不同的上線頻率,會大大的提高上線流程的發生頻率,會造成較大的人員浪費。
修改的相關性
如果同一交付物內的不同元件,經常會被同步修改,這可能說明,如果發生拆分,這兩個模組應該是”在一起“的。
技術棧
新技術的爆發,讓很多不同的場景有了更好的實現方式,如果有業務急需使用新的技術棧來(重新)實現。這種新技術除了新的語言、新的資料庫之外,可能還包括容器、Service Mesh、API 閘道器等新晉 PaaS 能力。毫無疑問,這種業務也同樣有拆分的需要。
結論
微服務雖說不是一個全新的東西,但也絕非是簡單的新瓶裝舊酒。總體說來,我認為這是在尊重現實,適當妥協的基礎上,一種應對變化的好辦法。