并不是所有的場景都適合微服務,我理解技術開發者都有一顆追求新技術的心,但是更重要的是業務場景及團隊,
-
關于微服務
微服務架構,說白了就是一種上層體系的演變,從最早的單體架構,到前后分離,SOA,甚至微服務架構,其實它們都在做一件事,并且都朝著一個方向去發展:那就是分而治之!從簡!
分而治之有什么好處呢? 對于服務來說,可能每個服務實體都是集群化、容器化、并且輕量級;對于設計人員就是低耦合,高內聚;
有了這種思想,對整體架構其實是進一步的升級,因為我們都知道微服務架構一方面也是由于對服務性能要求更好的進化,我們追求“三高”,從某種意義而言,通過疊加機器的方式更能有效的提升性能,畢竟現在的機器,甚至云服務器成本不是那么高不可攀!
readMe:
我接觸過很多公司,它們的產品體系也是一步步轉化而來的!很多產品設計的前期,都追求快速上線,功能正常,并不需要太多的設計,但是慢慢產品體系、功能模塊甚至榷訓到達一個量級后,會做一些上層的設計拆分,重構,它們的目的是為了滿足我們具體的業務場景更流暢、甚至交付更快速等等...
在技術討論交流中,很多開發者對上層設計甚至架構能力會持有不同的看法,比如某某功能模塊業務邊界、是否應該做服務拆分、是否需要上微服務生態,而且大部分開發者和領導決策層往往會有不同的看法,因為大家站在角度不同:如果是技術開發者,更習慣于追求新的技術,或者希望做出一定的改變,但是對于管理者甚至技術CEO往往會從不同的角度思考:微服務帶來的問題、微服務業務邊界、微服務DDD領域模型、以及上層聚合資料中臺或業務網關,
-
微服務帶來的問題
技術選型其實就跟買衣服一樣,看著好看的衣服不一定合身、也不定適合你;適合你的可能你會一開始覺得很一般,但是穿起來會很舒服!
我們不妨思考一下,如果你們的公司產品現在是一個單體架構,從現有的結構上考慮,如果做微服務拆分,會有哪些棘手的事情?
- 微服務生態組件的選擇
- 服務拆分邊界
- 微服務資料聚合問題
- 線上監控、排查
- 分布式老生常談的問題 :資料一致性
- 如果目前是單體服務,從哪些角度進行拆分靠譜
微服務生態組件:目前以java的生態為例,目前基于springcloud、springcloud&alibaba或者zookeeper dubbo 都可以實作分布式架構,當然它們也會有有缺點,比如nacos CP AP的選擇、cloud config的運維配置、持久化、這個可以根據團隊的技術方向、以及具體業務考慮、但是這往往是最簡單的一步,因為我相信很少有公司會自己寫分布式組件、像阿波羅或者其他組件,很多公司都是拿來即用即可,
服務拆分邊界:這個是一個棘手的問題,往往前期做服務拆分會伴隨著各種各樣的問題,比如我們應該根據功能模塊進行拆分還是根據場景壓力進行拆分?各個服務之間耦合性怎么控制?
微服務資料聚合:往往我們有這么一個場景、例如我的用戶服務和訂單服務是兩個獨立的微服務,但是有些場景我需要將各自的資料聚合查找,這種方式怎么處理?
線上監控、排查:微服務通信,主要還是采用rest或者異步MQ的方式進行通信的,那么一個場景多個服務直接呼叫,如果發生例外我們怎么排查問題?
資料一致性:每個服務都有自己的資料,怎么保證資料一致性?
單體演變微服務程序:如果我現在是一個單體服務,我需要做微服務拆分,慢慢將架構轉變到微服務架構,怎么做?
-
微服務帶來的好處
有了微服務帶來的問題,那么我們要考慮微服務帶來的好處有哪些?
- 微服務基于容器部署,單個服務相比較小,快速啟動
- 每一個服務都是一個獨立的server、不于其他服務向耦合
- 如果需要敏捷開發,微服務一定是最適合的,服務拆分可以快速迭代,不需要整體發布
- 服務單一職責,任務拆分
- 緩解業務場景壓力,比如某個服務壓力大,粗暴加機器擴容
- 很多公共組件可以抽象出來,避免重復造輪子
- 交付場景某種意義更適合
部署:基于容器自動化部署,更方便,更迅速
敏捷開發:敏捷開發一定是更適合微服務,如果單體要考慮敏捷迭代,合并甚至其他一系列問題
單一職責:可以由技術團隊去控制服務的分配,目標更明確
性能:集群實體,這個沒什么說的,畢竟現在機器的成本不大,而且如果是單體出現性能問題,那么可能上層做負載,下層的服務很笨重
公共組件:很多公司會有這樣的程式員,我們在一個單體開發,很多類似的功能每個人都會造一套輪子,冗余代碼超級多,
交付:這個不同公司的情況是不一樣的,舉個我們之前的公司,我們基于產品做開發,這時候每次有交付就會從產品拉一份然后做二開,而且交付場景也很笨重,例如某些客戶只想要我們的A不想要我們的B,它只給A模塊付費,那么傳統的方式就是lic控制,把B禁掉,這是一個很繁瑣的流程
-
如何解決微服務的問題
服務拆分問題
服務拆分,其實總體思想很簡單,就是一個服務要做什么事情?有了這個結論,其實我們就可以做服務拆分了,
具體一點,就是:單一服務高內聚低耦合,每個服務只需要關系自己干的是什么事情就夠了,例如用戶服務,那它只應該管用戶的事情,如果這時候它又要管訂單的職責,那么這個服務邊界就是一個不合理的,這樣有個好處就是,用戶服務發生改變不需要處理其他服務的代碼,當然(如果對外提供對應的api發生變化,那沒有辦法,當然也有辦法避免,各有好壞)
但是,在某些場景下,有可能服務違背了這個原則:(就跟資料庫設計三大范式,它是一種規范,但是它不適用所有場景!)例如幾何耦合性很高的服務,同時又大量有服務聚合的場景,那么它需要拆嗎?很明顯它是不需要的,何苦給自己找罪受呢?要知道服務多了也會有問題,整體架構會更加復雜!
如果我是一個單體專案,我要開始做服務拆分應該怎么做呢?首先,拆分的程序一定不能影響目前迭代的進度,一個不完善的服務想去拆分,往往最后的結果是拆不如不拆!我們可以先從相對獨立的模塊進行拆分,比如通知服務,或其他,它的選擇應該是核心功能很明確,并且業務耦合性不高,而且趨于穩定,
同時,在考慮服務拆分的時候,一定要結合業務場景!要了解業務模型后,整理出比如對外提供的結構、設計、甚至一些api之后,再考慮這件事情!舉個例子:如果我們有兩個服務,它們本身有一定的依賴,但是它們被拆分了,那么某個場景的動作應該就是A服務呼叫 -> B服務呼叫,如果我們有大量的場景需要資料聚合,那么這兩個服務是否應該拆分呢?往往我們得出的是否定的結論,除非處于其他的角度,比如這個服務場景性能要求或者其他,
所以,服務拆分一般來說主要取決這么幾點方式:
基于業務模塊:業務A是一個服務、業務B是一個服務
公共拆分:我們會有很多基礎的服務,這些是業務提供的核心,但它們往往不需要變動,就需要將上層抽離出來,那么往往我們再變動業務,只需要關心具體的業務變動就好了,不需要考慮基礎建設(試想一下,如果每個業務處理都要伴隨著基礎模塊修改,然后其他的業務又都依賴于這個基礎模塊,那是不是亂套了?只要發生變動就會從頭改到尾,或者針對變動單獨寫一套,周而復始這個代碼得屎山成什么樣?)
場景拆分:比如某個場景很重要,對性能要求很高,那么可以將這個抽出來,針對這個服務進行優化
資料一致性
微服務要保證資料一致性,但其實這也是個死命題,例如CAP,要保證高可用就要犧牲部分一致,魚和熊掌不可兼得!想想我們的服務都是通過網路去通信的,再好的方式也避免不了網路抖動,這里想到了之前有一個面試官跟我聊過的微服務資料庫短暫不一致的問題:如果我們通過主從 binlog同步,會有短暫的不一致,master寫入資料還沒來得及同步到slave,那這時候slave沒有資料,怎么辦?其實這個問題不需要解決,很多場景我們允許短暫不一致,但是我們要保證最終一致性!再者如果要求這么高,可以將同步方式設定為串行同步,寫資料就立刻刷到slave,同步完成后再回傳,那么主執行緒就會有短暫的阻塞,這個看業務的取舍了,
那么,從微服務資料讀寫來說,我們要關注的問題是:資料一致性讀、資料一致性寫、操作冪等,
首先我們來說說冪等,這個我相信更多在第三方sdk、暴露服務、甚至MQ消費程序中會用的更多,它的本身含義是:相同的引數在同一個方法里,無論執行一次還是多次都會回應相同的結果!
對于查詢和洗掉,其實本身就是冪等的,只要資料沒有變化,那么多次查是沒有問題的,至于洗掉,如果你想洗掉一個已經洗掉的元素應該怎么做?那就不操作了呀,反正已經刪了,
新增資料的冪等,這個有很多種方式控制,例如通過key簽名校驗、客戶端防抖、甚至unique唯一索引都可以做到,
修改資料的冪等,就是一個相對復雜的問題了,首先,并發問題下會導致資料重復修改導致臟資料,第二來說也會導致獲取的是臟資料,例如我查詢和修改同時進行,查詢的資料可能是還沒來得及修改的資料,
所以 這里引申出的幾種方案,分別是讀寫共享鎖、樂觀鎖ABA,一方面控制并發處理,一方面控制資料安全,
資料一致性讀,這個不是但個服務的查詢,而是服務之間的資料處理,具體請看資料聚合模塊,
資料一致性寫,寫的一致性說白了,就是分布式事務,我們知道分布式事務是一個很繁瑣的問題,分布式事務主要有這么幾種方式:TCC、XA二階段提交(seate)、異步事務中間件、異步請求、回呼補償等等
首先我們說最特殊的,異步事務中間件:舉個例子:Rocket的分布式事務消息,TCC+本地訊息表的變種,具體請查看:【打怪升級】【rocketMq】如何保證訊息零丟失
其實,更多時候我們通過seata或者其他全域事務中間件去處理,使用方便,集成簡單,
常規的場景不過多描述,但是在某些業務場景下還有其他的處理方式:例如事務場景也有等級之分,那么核心的事務執行完成后,要保證其他事務必須完成,舉個例子:電商下單完成后,可能需要呼叫會員積分,給賬號加積分,那我們允許積分沒加成導致的下單回滾嗎?很明顯是不行的,這種情況我們會將失敗但必須要完成的事務操作快取起來,讓異步執行緒或者其他操作去重新執行,如果一直執行失敗我甚至可以直接操作資料庫(特定場景...)保證這個資料沒有問題,
服務聚合問題
微服務資料聚合問題,是一個比較常見的問題,通常我們會有這樣一個疑問,如果我的兩個服務需要關聯查詢資料怎么辦?
首先,給出結論:常見的方式有這么幾種:
- 部分冗余欄位,違反資料庫范式
- 廣播資料(binlog主從)
- 上層聚合服務
- 記憶體整理資料,例如服務A先查出一部分資料 然后拿著資料去查B
上面的幾點,其實都是我們常用的方式,那么我們在設計中如何選擇呢?
首先,部分冗余欄位是大家的常見手段,這種方式實作起來很簡單,但是它的問題是對應的資料更新后要及時同步到冗余欄位里,所以它更適合比較重要但是不常變動的列上,
廣播資料,說白了就是mysql binlog主從同步,mysql我們不光可以指定不同庫的同步,也可以指定某張表的binlog 同步,那說白了其實它只適用一種場景,就是資料統計資料整理,你想想有一個服務它的db包含其他服務的db,并且它的db資料由其他服務db同步而來,這種其實違背了微服務的設計原則,這種只適合做復雜查詢、復雜關聯、甚至報表統計之類的場景需要,可以通過sql處理過濾很多資料,
上層聚合服務,這個方式也用的很多,最常見的方式是例如我們有AB兩個服務,但是api有很多AB關聯查詢的大量場景,并且這個服務一般是需要暴露API的,那這種方式就會更好,因為如果api變動只需要考慮上層聚合服務的變動,而底層服務變動只需要考慮api的變動,對于外在是不感知的,但是它會導致我們的結構更繁瑣,根據業務場景慎用,畢竟它增加了多維護一個服務的壓力,
記憶體資料整理,這個從字面意思大家已經知道它是什么了,例如在資料量很小的情況下,我將AB的資料都查出來記憶體處理就夠了;或者業務以A為主,我先查出A的資料,然后根據A的資料查出B的資料
微服務監控運維
微服務的運維監控主要分為這幾部分:線上問題排查、自動化運維監控、呼叫鏈路
對于開發者來說,這個角度其實就轉換成:線上日志、鏈路追蹤、系統監控指標
首先,很多微服務生態日志都采用kfaka + ES + kibana,因為如果服務數量龐大,你不可能切換各種服務登陸上去看對應的服務log,所以更好的是把所有服務的實時日志收集起來,統一存盤ES,并且不同服務不同場景有不同的key方便排查,再通過ES的索引進行搜索,這樣運維也可以通過kibana去實時查看日志資訊,
再者,我們的服務呼叫可能會有很多層,這是針對服務呼叫鏈路追蹤也是一個必要的場景,比如通過Zipkin集成做服務鏈路呼叫追蹤,
系統監控,這個就很常見了,現在很多公司喜歡采用Kubernetes,通過Kubernetes也可以做一些線上系統監控,
舉個場景,例如某個場景業務出現問題,那么排查的第一思想就是:哪個模塊哪個介面出現問題?問題的癥狀?服務的狀態?其實這恰恰是上文說的幾個問題的體現,
微服務和SOA,DDD
很多人喜歡把微服務和SOA放在一起,其實SOA跟微服務的角度是不同的,SOA的思想是服務橫向拓展能力:說白了就是通過SOA思想達到服務耦合的程序,
我們都知道SOA中有ESB訊息總線,那么其實SOA更像一個服務網關、甚至是一個上層業務網關:因為SOA體現的能力就是服務間各自獨立,但是某種規范、甚至方式將服務間的處理聯合起來,這么看它是不是更像一個上層的業務網關?
而微服務主要體現在架構設計上,微服務的思想就是服務分而治之,每個服務職責單一,至于你怎么通信,怎么聚合其實根據個人的選擇了,
再來說DDD,DDD理念很多人第一印象就是服務拆分思想,其實這個角度沒有錯,我最開始也認為DDD是為了幫助我們完成服務拆分的,首先DDD的思想就是分而治之,化繁為簡,那這個跟微服務設計其實不謀而合了,
但是一般來說,如果我們拆分某個服務,如果這個服務在業務變動或者因為其他服務而頻繁變動,甚至不能在短時間內完成,需要大量的考慮其他服務帶來的影響,那么其實這個服務拆分是錯誤的,而DDD則完全遵循了分而治之的原則,我們知道服務拆分的顆粒度由很多因素決定:場景、團隊、時間成本等等... 所以DDD只是一種思想,我們拋開DDD提供的領域服務之類的概念閉口不談,它更像一個標準,就像資料庫的三大范式我們設計都滿足嗎?如果都滿足這公司的開發人員估計要罵娘了把,
寫在后面
其實我們發現,微服務設計是一個方式,也是一種手段,它不一定適合所有的場景!例如金融或者軍工行業它們就比較適合,一方面它們的周期會比較長,另一方面它們也涉及者大量的變動,甚至作為服務能力的提供者,這種是由必要的,只有這樣才能滿足敏捷開發,并且滿足一些使用場景;那如果你們開發一個小程式,一個簡單的BS,沒有大的體量也沒有時間成本,更沒有復雜的功能模塊,你問我需要拆分微服務嗎?跑著就行了,拆它干嘛?
同時,一些做上層服務重構的團隊來說,也要考慮時間成本,團隊人員成本(一個開發寫一個微服務?頭疼?),并且實際的場景,很多公司高層不看重這些,覺得這些就是白出力,浪費時間的事情;往往等到體量上來了發覺后悔了,太過笨重成本太高都是很常見的事情,
tips:如果你是一個技術CEO或者團隊技術老大,這些事情一定要慎重,而且要了解公司上層的想法,不然出力不討好的鍋可能就在你身上了....
本文來自博客園,作者:青檸_fisher,轉載請注明原文鏈接:https://www.cnblogs.com/oldEleven/p/17322302.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/550275.html
標籤:架構設計
上一篇:03裝飾者模式
