大家都在學SpringCloud,貌似學會了SC就牛逼哄哄,感覺不得了的樣子。但微服務,在整個企業級應用中,只佔了一小部分。微服務引入的問題比解決的問題還要多,你會遇到各種各樣的bottleneck。
微服務解決的是計算節點的問題,然而根源卻在儲存節點。當業務規模變得越來越龐大,儲存、編碼、管理都會成為問題。
接下來我們談一些放之四海而皆準的道理,不需要貼上"XX公司最佳實踐"之類的標籤。
下面是一張因資料擴張引出的微服務相關的圖,簡約但不簡單。中小型公司只要有這些元素,就能玩的很好;大點的公司,因為規模太大,每個元件都會遇到瓶頸,所謂的專項的優化並不能脫離它的本質。
那我們開始。
注意,這張圖僅是主要資料路徑,一個子集,其他的包括CDN、通訊層等,不在此列。
這張圖並不包含某個特定領域的具體架構,屬於一個整體性的概括。我們從資料庫容量的瓶頸說起,看一下微服務在其中的比重。
資料庫
使用者資料要儲存,就存在資料庫。過去這麼多年,NoSQL並不能消除開發人員的恐懼,所以,MySQL之類還是大多數公司的首選儲存。
假設你的業務增長的很好,這個就有意思多了。專案開始,你的sql玩的越6,那麼給後人埋的坑,越多。因為sql的功能太豐富了,一不小心,就炫技了。你會發現,林子越大,對sql的規範要求越高。一些官宣的特性,在公司內是嚴格禁止的。
市場發展很好,終於來報應了。以前的技巧變成了現在的累贅。慢查詢、全文掃描,招招斃命。想要加快取,結果發現無從下手;想要分庫分表,結果發現表關係錯綜複雜。
小表和寬表
所以第一步,還是得去填坑。一個超過3個表的聯合查詢業務,大概率是不合理的。在加快取和分庫分表之前,還是得重新設計一下資料表。
忘掉什麼資料庫正規化,我們將存在兩類表:小表和寬表。
小表提供了最基本的資料,可能一個簡單的KV就完成了。一些聯合查詢,是直接可以在程式裡進行迴圈拼接的。程式裡迴圈1000次10毫秒的查詢,比單次查詢耗費6秒要強的多。這就是分散式系統的特點,小耗時的批量查詢,比hang在那裡更加有生命力。
寬表通過冗餘的方式,提供了某個重要功能常用的分析資料。這種表的欄位一般都特別多,在寫入時通過拼接獲取冗餘資料,一般用在讀多寫少的場景。
完成了這一步,接下來的工作才能進行。
分庫分表
在《“分庫分表" ?選型和流程要慎重,否則會失控》中,詳細的說明了分庫分表的選型,這裡淺談一下過程。
分庫分表很可能會引入某一種中介軟體,因為僅僅將資料庫分開還不行。HA,FailOver等特性,是同時需要的。
分庫分為垂直分和水平分。垂直面向的是業務拆分,即將一部分表按照業務邏輯獨立到其他庫中;水平面向的是容量,即通過分庫分表的模式使資料有一個擴張的途徑。
資料一定要有一個可以度量的切分維度,否則就過於分散,或者過於傾斜,影響後續的處理。
資料同步
有分就有合,比如某些報表業務需要全量的資料。
不同業務通過共享資料庫來共享資料不得不說是個非常蠢的主意。這個時候就需要一些資料同步工具。
資料同步元件可以說是一個公司的必備元件。有基於最後更新時間的高延遲同步工具,也有基於binlog的低延遲同步工具。有的公司為了穩定,還會有所謂的多機房同步。
資料同步最怕異常,因為大多數同步都有順序性要求。一切執行良好的時候,大家皆大歡喜;一旦出現異常,就需要其他手段來保證異常期間的資料同步和延遲。
這都是些髒活,自動化有時候會適得其反,監控是第一位的。
分層的資料儲存
可以預見的是,即使你分庫分表了,還是能很快達到瓶頸。分庫分表後,你的一些統計功能可能還用不了了,在一些傳統的管理系統上,這是硬傷。
一個分層的資料儲存層是必要的。你的一些業務,可能一個分支走的是MySQL,換了另外一個條件就成了ES。
不同的DB做不同的事情。RDBMS只做原是資料的儲存和查詢,是扁平快的資料通道;特定的單機高效能DB,做一些匯聚和科學計算;分散式的類RT的儲存,用來儲存一些中等規模的資料,並提供一些中延遲的搜尋功能;海量的儲存系統,儲存系統所有的歷史記錄,並提供離線分析功能。
不要想著某一類儲存解決所有的問題,那是騙人的。儲存部分的複雜性不是普通的微服務能夠相比的。是誰保證了分層的資料儲存設計呢?除了一部分通過MQ分發資料的業務,還是得靠我們的資料同步元件。
快取
但DB的壓力實在是太大了,我們不得不考慮快取。快取不能亂用,有兩個原則:一個是快取不能侵入業務,也就是不能帶有業務邏輯;一個是快取的命中率要高,否則適得其反。快取是對高併發、高速介面的補充,是系統穩定性的必要不充分條件。
除了Redis等外接的快取叢集,jvm內快取也是一個比較重要的場所。快取的存在是因為I/O裝置的緩慢,通常放在記憶體中,斷電後即消失。
快取涉及到源資料庫和快取資料庫之間的資料同步。通常,更新源庫時,會同時刪掉快取中相關的就資料,這樣在下次讀取的時候,能夠讀取到最新的資料。
快取限制最大的就是其容量問題,而且都貴的很。假如業務模式固定,一些kv儲存使用LevelDB或者HBase等方案,會顯著節約成本。模組化
是時候將工程模組化了,畢竟上百個程式設計師共享一個程式碼庫,風險已經很大了。
模組化通常會按照業務線進行拆分。比如,支付模組和報表模組的拆分。
模組拆分後,相似的模組會共享資料庫。但更多的是通過冗餘資料來解決,這樣能將業務解耦,一部分出現問題,另一部分能夠執行良好。好比你隔壁出了殺人案你第二天還能正常去上班。
模組之間要找到一種互動方式,比如使用HttpClient、OkHttp等。重要的是統一,統一了以後就有一個高大上的名字了:RPC。
一個小模組很有可能會發展為一個大的業務線,也有可能無人問津。
MQ
模組化之間另一種共享資料或者資料互動的方式就是MQ。除了有削峰等功效,MQ更多改變的是一種互動模式,一種對業務的解耦。
Kafka幾乎每個公司都在用,最高能有幾十萬的吞吐量。RabbitMQ、RocketMQ等,更多用在可靠性要求非常高的場景,但比較耗機器。
MQ資源一般都要求絕對的高可靠,作為基礎設施,一旦出問題,將帶來非常大的事故。設計的時候要考慮異常情況下的資料處理流向,以及MQ恢復後的補償策略。
MQ叢集設計的比較小一些才合理,避免不同業務,不同可靠性級別的訊息互相影響。MQ在業務上和功能上要相互隔離,做到最小服務集合。
為了避免MQ當機對正常業務產生影響,非重要鏈路上的MQ不能阻塞業務的正常進行,這種訊息通常通過非同步執行緒傳送。
微服務
我們已經使用訊息和模組化,將系統拆分成了多個工程。將這些工程使用統一的方式管理起來,統一其互動模式和在上面的治理,就是微服務的範疇。
微服務就是一個多模組專案規範化的過程。非規範的服務與微服務體系,是要共存一段時間的,如何保證新舊服務的替換,是一個管理上的問題。
功能元件
根據SpringCloud的描述,一個服務想要被發現,需要將自己註冊到通用的註冊中心,其他服務可以從同一個地方,獲取它的例項,進而呼叫。
而真正產生呼叫的功能,就是RPC的功能。RPC要考慮一系列比如超時、重拾、熔斷等功能。在某些訪問量非常大的節點,可能還要考慮預熱。
RPC要能產生一些統計性資料,比如TPS、QPS、TP值等,很顯然SpringCloud是缺乏的,我們要藉助外部系統進行分析。
在外部請求流轉到內部之前,需要經過一層閘道器的處理。像一些通用的操作,比如許可權、限流、灰度等,就可以在閘道器層處理。
服務治理
微服務最重要的特色就是其治理功能。服務治理的依據就是監控資訊。通過統計每次呼叫的大小、耗時、分佈,能夠得出服務的大體拓撲。
通常以下資訊最有用: 1、QPS,時間序列的qps分佈,最高區間qps 2、平均響應時間,介面的平均響應時間,最大耗時和最小耗時 3、TP值分佈,90%,99%等請求是在x耗時內完成
通過以上資訊能夠對服務進行畫像。是擴容、縮容、專項治理的資料依據。
微服務引出的另外一個問題就是呼叫鏈,即某個請求的真實路徑。分散式環境下的問題排查,會非常的困難,呼叫鏈能夠幫助研發快速定位問題,並幫助理解業務的資料流向。
服務治理的目的就是找到不合理的請求和分佈,比如某個介面耗時太長;某個介面請求量大,需要加快取;某個功能依賴鏈條過長,需要業務優化等。
服務治理要藉助大量的外部分析工具,更多通用的業務模型,需要大資料平臺的支援。
我們把監控/報警也放在服務治理的部分,在《這麼多監控元件,總有一款適合你》中,我們詳細的討論了監控部分的技術選擇方案。
日誌
微服務產生的另外一個問題就是日誌太過分散。一個核心的業務可能有上百個例項,你不可能開啟100個終端去看日誌。這就涉及到日誌的收集。日誌歸集功能就是把分散的日誌集合到一個地方,它的主要挑戰就是資料量。
通常日誌分為兩部分,一部分是全量的,可以通過定時同步等方式,備份到日誌堡壘機或者hdfs中;一部分是過濾後的日誌,比如一些異常資訊,集中在某一個處理平臺中進行報警。
很多研發喜歡將使用者行為資料輸出到日誌檔案中,這部分日誌被收集後,會通過流計算或者離線計算,得到一些推薦和模型。日誌資訊進入了大資料處理的範疇,我們不過多描述。
持續整合
如果一個上點規模的公司,技術團隊有什麼值得一做的系統,那麼釋出系統算一個。《釋出系統有那麼難麼?》中,談了一種可能的模式。
釋出系統就是給一堆指令碼包了一張方便的皮。一些流程性工具、釋出驗證、CI/CD功能,很容易能夠新增到自己的釋出系統中。
很多微服務推廣的文章中,談到虛擬化(Docker)等,其實不是必須的。虛擬化減少了服務編排的時間,能夠方便的進行擴容和縮容,但對監控、日誌收集、網路拓撲等,要求比較高。建議是整個體系中的最後一步而不是第一步。
你的系統是否靈活,還與公司的文化環境相關。如果上個線走審批流程就需要一兩週,那麼做一個敏捷的持續整合系統就不是那麼必要了。
基礎設施
基礎設施更多指的是運維體系,這是支撐整個系統健康發展的基石。我傾向於基礎運維和基礎架構不分家,因為它們的模式和文化,是一個公司研發環境的基石。
另外一些基礎元件,比如配置中心、排程中心、分散式鎖管理等,都對可靠性有較高的要求。END
這套體系看著簡單,也有固定的解決方案。但問題就在於,許多公司從成立玩到倒閉,玩了那麼多年,還是沒玩好。
真是可憐。