架构 | 微服务架构下如何解耦,对于已经紧耦合下如何重构?
點擊上方“朱小廝的博客”,選擇“設(shè)為星標”
當當滿200減40優(yōu)惠碼「J2KNAE」
來源:知乎
今天準備談下微服務(wù)架構(gòu)下各個微服務(wù)間如何解耦,以及對于已經(jīng)緊耦合的微服務(wù)如何進行重構(gòu)。要明白實際上微服務(wù)后續(xù)出現(xiàn)的諸多問題往往都是一開始微服務(wù)模塊劃分就不合理導致,對于具體的模塊劃分方法和原則,我總結(jié)出了以下幾點。
原則1:劃分為<10個微服務(wù)模塊
原則2:強數(shù)據(jù)關(guān)聯(lián)模塊不要拆分
原則3:以數(shù)據(jù)聚合驅(qū)動業(yè)務(wù)功能聚合
原則4:從縱向功能劃分思路到橫向分層思路轉(zhuǎn)變
原則5:高內(nèi)聚、松耦合的基礎(chǔ)原則
對于具體的內(nèi)容在這篇文章不再重復給出。可以看到對于微服務(wù)模塊拆分更多的是屬于業(yè)務(wù)建模和系統(tǒng)分析方面的內(nèi)容,而今天談的微服務(wù)解耦重點是想從可用的技術(shù)手段入手來談下可用的以下解耦方法和策略。
問題綜述
最近幾年對于微服務(wù)架構(gòu),企業(yè)中臺構(gòu)建,組件化和服務(wù)化,平臺+應(yīng)用構(gòu)建模式,包括Docker容器化,DevOps等都越來越受到傳統(tǒng)企業(yè)的關(guān)注,也可以看到很多企業(yè)傳統(tǒng)架構(gòu)也在朝這個目標進行演進和轉(zhuǎn)型。對于微服務(wù)架構(gòu)本身的優(yōu)點和缺點,包括傳統(tǒng)企業(yè)實施微服務(wù)架構(gòu)的演進路線等,在我前面很多微服務(wù)架構(gòu)相關(guān)的文章中都有所介紹,今天主要談下在微服務(wù)架構(gòu)下的解耦問題。
要明白,企業(yè)實施微服務(wù)架構(gòu)后,原來所有內(nèi)部的接口調(diào)用,內(nèi)部的完整事務(wù)都會變成微服務(wù)模塊間的跨域的接口服務(wù)調(diào)用,傳統(tǒng)事務(wù)也變成了分布式事務(wù),這些本身是增加了系統(tǒng)復雜度。
原來一個系統(tǒng)就能夠完成的事情,現(xiàn)在要依賴底層技術(shù)組件服務(wù),其它業(yè)務(wù)微服務(wù)模塊多個Http Rest API接口調(diào)用往往才能夠完成。只要其中任何一個API接口出現(xiàn)問題,都會直接影響到前端的業(yè)務(wù)功能使用。
微服務(wù)間的雪崩效應(yīng):在采用微服務(wù)架構(gòu)后,各個微服務(wù)間存在大量的API接口服務(wù)調(diào)用,相互之間還形成了服務(wù)調(diào)用鏈,比如A-》B-》C,那么如果C服務(wù)出現(xiàn)故障就將直接影響到B服務(wù)無法正常訪問和服務(wù)阻塞,同時B的故障又將進一步傳導到A服務(wù)的消費和使用。
對于互聯(lián)網(wǎng)企業(yè)實施微服務(wù)架構(gòu),其中有幾個關(guān)鍵點。
其一就是微服務(wù)架構(gòu)可以更好的進行平臺的性能擴展和高伸縮要求。
其二就是互聯(lián)網(wǎng)應(yīng)用本身業(yè)務(wù)規(guī)則相對簡單,模塊間容易解耦。
其三就是大的互聯(lián)網(wǎng)企業(yè)IT技術(shù)積累更強,有更好的技術(shù)能夠搭建高可用的技術(shù)平臺,也有更好的技術(shù)能夠?qū)崿F(xiàn)微服務(wù)架構(gòu)實施后的自動化運維和監(jiān)控。
而這些往往都是傳統(tǒng)企業(yè)在實施微服務(wù)架構(gòu)所欠缺的,比如有些企業(yè)一開始實施微服務(wù)架構(gòu)沒發(fā)現(xiàn)問題,結(jié)果最終上線后卻發(fā)現(xiàn)后續(xù)的系統(tǒng)運維和性能監(jiān)控,故障問題分析和排查等能力跟不上,無法及時響應(yīng)客戶需求并快速的定位和解決問題。
即前面經(jīng)常說到的,傳統(tǒng)企業(yè)的IT治理和團隊技術(shù)能力跟不上,直接影響到微服務(wù)架構(gòu)實施成敗。
那么回到正題,今天希望討論和分析下,企業(yè)實施微服務(wù)架構(gòu)后,如何盡量減少微服務(wù)模塊的耦合導致的單個微服務(wù)模塊功能實現(xiàn)和運行故障,簡單來說就是一個微服務(wù)模塊中業(yè)務(wù)功能的運行,如何做到最小化的依賴外部微服務(wù)模塊Http API服務(wù)接口的可用性。即使外部模塊掛點,當前模塊也能夠正常使用,或者說能夠不影響到當前模塊核心功能的使用。后臺(朱小廝的博客)回復1024,即可領(lǐng)取k8s資料。
對于該問題,我們可以分開從幾個方面進行討論。
同步調(diào)用轉(zhuǎn)為異步調(diào)用
一說到解耦,我們一定會首先想到消息中間件來實現(xiàn)異步,即將同步轉(zhuǎn)為異步,通過異步來實現(xiàn)解耦。我們可以先想消息發(fā)送給消息中間件,只要消息中間件是高可用性的沒有宕機,整個接口集成過程就是OK的,而消息中間件再異步方式分發(fā)消息給目標系統(tǒng),同時支持重試。
消息中間件的采用
消息中間件(message oriented middleware)是指支持與保障分布式應(yīng)用程序之間同步/異步收發(fā)消息的中間件。消息是分布式應(yīng)用之間進行數(shù)據(jù)交換的基本信息單位,分布式應(yīng)用程序之間的通信接口由消息中間件提供。其中,異步方式指消息發(fā)送方在發(fā)送消息時不必知道接收方的狀態(tài),更無需等待接收方的回復,而接收方在收到消息時也不必知道發(fā)送方的目前狀態(tài),更無需進行同步的消息處理,它們之間的連接完全是松耦合的,通信是非阻塞的,這種異步通信方式是由消息中間件中的消息隊列及其服務(wù)機制保障的。
消息中間件實現(xiàn)了發(fā)布者和訂閱者在時間、空間和流程三個方面的解耦:
時間解耦—-發(fā)布方和訂閱方無需同時在線就能夠進行消息傳輸,消息中間件通過存儲轉(zhuǎn)發(fā)提供了這種異步傳輸?shù)哪芰?#xff1b;
空間解耦——發(fā)布方和訂閱方都無需知道對方的物理地址、端口,甚至無需知道對方的邏輯名字和個數(shù);
流程解耦——發(fā)布方和訂閱方在發(fā)送和接收數(shù)據(jù)時并不阻塞各自的控制流程。
從消息中間件的基本功能來看,無論是點對點消息中間件還是消息代理,其體系結(jié)構(gòu)都是非常清晰簡單的。但由于分布式應(yīng)用及其環(huán)境的多樣性和復雜性,導致了消息中間件的復雜性。
當前的消息中間件仍然分為兩類,一類是基于AMQP高級消息協(xié)議的,一類是基于JMS消息協(xié)議的。對于互聯(lián)網(wǎng)使用較多的RabbitMQ,Kafka等基本都基于AMQP高級消息協(xié)議。而對于Weblogic JMS,IBM MQ則是基于JMS消息協(xié)議的消息中間件產(chǎn)品。
對于Weblogic而言是一個企業(yè)級的應(yīng)用服務(wù)器中間件,同時Weblogic JMS也是企業(yè)級的消息中間件產(chǎn)品,該產(chǎn)品是一個企業(yè)級消息中間件產(chǎn)品,具備了高可靠,高可用,高擴展,高性能基礎(chǔ)特性。支持主流的各種消息模型,消息發(fā)布訂閱,消息持久化,事務(wù)處理,集群等核心特性。
消息中間件的使用場景,具體包括了如下幾個方面:
消息通知:單據(jù)狀態(tài)變化后的事件通知,數(shù)據(jù)傳輸完成后的事件通知
異步集成:服務(wù)消費方只需要將數(shù)據(jù)送到OSB即實時返回,通過異步集成實現(xiàn)徹底解耦
目標系統(tǒng)削峰:大并發(fā)數(shù)據(jù)導入而目標系統(tǒng)處理性能受限的場景
消息發(fā)布訂閱:基礎(chǔ)主數(shù)據(jù)通過JMS實現(xiàn)1對多的實時數(shù)據(jù)分發(fā)
高可靠性場景:確保在數(shù)據(jù)集成中不出現(xiàn)任何丟失的情況
對于采用Weblogic JMS來實現(xiàn)消息集成,具體過程如下圖:
基于事件驅(qū)動的業(yè)務(wù)分析
而要做到同步轉(zhuǎn)異步,我們必須從業(yè)務(wù)需求分析開始就轉(zhuǎn)變思維,即從傳統(tǒng)的業(yè)務(wù)流程需求分析方法轉(zhuǎn)到事件驅(qū)動分析方法,這個在我很早的EDA事件驅(qū)動架構(gòu)內(nèi)容整理的時候?qū)iT談到過,今天摘錄部分內(nèi)容供大家參考。
事件驅(qū)動框架(EDA)里事件可傳輸于松散耦合的組件和服務(wù)之間。一個事件驅(qū)動系統(tǒng)典型地由事件消費者和事件產(chǎn)生者組成。事件消費者向事件管理器訂閱事件,事件產(chǎn)生者向事件管理器發(fā)布事件。當事件管理器從事件產(chǎn)生者那接收到一個事件時,事件管理把這個事件轉(zhuǎn)送給相應(yīng)的事件消費者。如果這個事件消費者是不可用的,事件管理者將保留這個事件,一段間隔之后再次轉(zhuǎn)送該事件消費者。
EDA架構(gòu)往往具備如下特征:
廣播通信:參與通信的系統(tǒng)將事件廣播給任何對該事件感興趣的參與者。
實時性:在業(yè)務(wù)事件發(fā)生時候,EDA架構(gòu)下可以實時的發(fā)送事件給消費方,而無需等待
異步:事件發(fā)布系統(tǒng)不用等待事件接收系統(tǒng)來處理事件,發(fā)送到EDA模塊即可返回。
細粒度:只要具備獨立的業(yè)務(wù)價值,即可以發(fā)布為細粒度的事件,而不是傳統(tǒng)服務(wù)下的粗粒度。
復雜事件處理:根據(jù)業(yè)務(wù)流程需求,事件間可以聚合和組裝,形成事件鏈滿足復雜事件處理。
并行運行:多個事件可以同時運行,單個事件可以同時分發(fā)給多個訂閱方。
非阻塞:EDA本身提供MQ等消息持久化機制,不會在事件大并發(fā)下出現(xiàn)事件阻塞情況。
簡單來講,消息集成,異步,徹底解耦,消息發(fā)布訂閱,事件鏈是EDA整個架構(gòu)的核心。但是在EDA包括CEP復雜事件處理,在使用的時候首先還是應(yīng)該了解清楚其和傳統(tǒng)流程驅(qū)動在業(yè)務(wù)分析方法上的區(qū)別。簡單來說,流程驅(qū)動和事件驅(qū)動的一個簡單比較可以用下圖描述:
基于EDA的核心業(yè)務(wù)分析思路說明
在事件驅(qū)動架構(gòu)下,業(yè)務(wù)分析的核心就是事件的識別。而對于傳統(tǒng)方法往往則是關(guān)鍵流程和活動即可。在總體分析思路上的變化來說,傳統(tǒng)分析方法只分析到第2-3級業(yè)務(wù)流程,識別業(yè)務(wù)活動和交互點,而EDA需要業(yè)務(wù)分析時候分析到L4級的最底層EPC事件流程圖,并識別關(guān)鍵業(yè)務(wù)事件和事件分解,聚合關(guān)系。
在具體分析內(nèi)容上的變化來說,傳統(tǒng)方法只關(guān)心業(yè)務(wù)活動,而不關(guān)系業(yè)務(wù)活動具體的啟動機制,業(yè)務(wù)活動完成后產(chǎn)生的業(yè)務(wù)事件。基于EDA業(yè)務(wù)分析方法,需要打開業(yè)務(wù)活動,識別業(yè)務(wù)活動的前者觸發(fā)條件和業(yè)務(wù)活動引起的業(yè)務(wù)對象狀態(tài)的變化,往往狀態(tài)變化點都是關(guān)鍵的事件識別點。
具體可以用下圖進行描述:
簡單事件-基于業(yè)務(wù)需求用例分析和識別
業(yè)務(wù)事件的識別可以從業(yè)務(wù)需求用例入手,分析業(yè)務(wù)用例中的業(yè)務(wù)前置觸發(fā)條件,分析業(yè)務(wù)對象的狀態(tài)流轉(zhuǎn)過程和后續(xù)操作,以找尋業(yè)務(wù)活動的事件輸入和事件產(chǎn)生。
從下圖里面也可以看到,對于事件的識別往往比用例的識別更加細化,需要詳細的分析業(yè)務(wù)用例中的基本流,擴展流,業(yè)務(wù)規(guī)則,特別是關(guān)注其中核心的業(yè)務(wù)對象和單據(jù)狀態(tài)的變化。同時對于用例分析中的觸發(fā)條件也需要重點分析,這些觸發(fā)條件往往是事件鏈形成,或者說觸發(fā)消息事件訂閱的來源。
復雜事件-基于事件識別形成事件鏈
傳統(tǒng)的基于流程的業(yè)務(wù)分析方法往往只會分析到業(yè)務(wù)流程,具體的業(yè)務(wù)活動,而不關(guān)心具體業(yè)務(wù)活動執(zhí)行前或執(zhí)行后產(chǎn)生的業(yè)務(wù)事件,這和接口平臺前期重點關(guān)注數(shù)據(jù)集成有關(guān)系。而為了保證業(yè)務(wù)實時響應(yīng)需求,必須準確的識別業(yè)務(wù)事件,才能進一步設(shè)計基于業(yè)務(wù)事件的處理和響應(yīng)機制。基于EPC事件流程鏈分析思路,需要對傳統(tǒng)分析流程進行細化,增加紅色事件識別點和事件分解聚合關(guān)系。在事件鏈的形成過程中往往存在一些復雜場景需要分析,包括了事件的一對多分發(fā)和訂閱,也包括了多個事件聚合,在滿足某個特定的業(yè)務(wù)規(guī)則后才觸發(fā)下一個新的業(yè)務(wù)活動和新事件。這些都是在復雜事件分析中必須考慮的內(nèi)容之一。
從EDA事件驅(qū)動到CQRS
顧名思義,CQRS即命令查詢職責分離,將CUD操作和R查詢操作分離,對于CUD操作仍然參考傳統(tǒng)的領(lǐng)域模型建模思路來實現(xiàn),但是在命令中增加了消息事件機制,實現(xiàn)CUD操作變更通過消息事件異步寫入到數(shù)據(jù)庫。
在CQRS中,查詢方面,直接通過方法查詢數(shù)據(jù)庫,然后通過DTO將數(shù)據(jù)返回,這個方面的操作相對比較簡單。而命令方面,是通過發(fā)送具體Command,接著由CommandBus來分發(fā)到具體的CommandHandle來進行處理,CommandHandle在進行處理時,并沒有直接將對象的狀態(tài)保存到外部持久化結(jié)構(gòu)中,而僅僅是從領(lǐng)域?qū)ο笾蝎@得產(chǎn)生的一系列領(lǐng)域事件,并將這些事件保存到Event Store中,同時將事件發(fā)布到事件總線Event Bus進行下一步處理;接著Event Bus同樣進行協(xié)調(diào),將具體的事件交給具體的Event Handle進行處理,最后Event Handler把對象的狀態(tài)保存到對應(yīng)Query數(shù)據(jù)庫中。
對于CQRS,最容易想到的還是在數(shù)據(jù)庫層面做的讀寫分離模式,可以看到CQRS本身和數(shù)據(jù)庫的讀寫分離模式可以更好的匹配,由于采用事件驅(qū)動和消息訂閱模式,對于R讀庫我們可以更加容易對數(shù)據(jù)變更信息進行更新,達到讀庫數(shù)據(jù)的及時同步更新。同時讀庫既可以采用讀寫分離數(shù)據(jù)庫,也可以采用類似Solr,Nosql等分布式,非結(jié)構(gòu)化數(shù)據(jù)來實現(xiàn)彈性水平擴展能力。后臺(朱小廝的博客)回復1024,即可領(lǐng)取k8s資料。
在命令查詢職責沒有分離的時候,可以看到一方面是模型本身的擴展性受到影響,另外一方面是原有的領(lǐng)域模型本身偏重,而且Entity實體本身也通過完整的DTO對象進行傳輸,這樣在一些特殊的只需要更新或查詢個別字段的時候,整個模型仍然偏重。
通過命令查詢職責的解耦,不僅僅是提升整個框架模型的擴展性,更加重要是將兩類業(yè)務(wù)規(guī)則和實現(xiàn)徹底的解耦開,方便后續(xù)的功能開發(fā)和運維,特別是在整個業(yè)務(wù)場景和邏輯實現(xiàn)復雜的情況下,這種解耦會使整個開發(fā)架構(gòu)更加清晰簡單。
同時也可以看到有一Command命令都是采用異步事件的方式進行寫入,因此不存在同步和長連接占用的問題,有利于提升整個平臺在大并發(fā)下的整體響應(yīng)性能。
當然,采用CQRS模式最大的一個問題點就是無法實現(xiàn)命令和查詢兩部分內(nèi)容的強一致性保障,即很可能你界面上查詢到的數(shù)據(jù)不是最新的持久化數(shù)據(jù)庫里面的數(shù)據(jù),這個本身和消息管道異步寫入的實時性有關(guān)系。
其次在使用CQRS模式的時候,有一個重要假設(shè)就是,在事件和命令發(fā)出后,無特殊情況在事件接收方都必須要能夠接收事件成功處理,否則就存在大量的異常錯誤消息的異步回寫,反而增加系統(tǒng)的復雜度。舉個簡單例子來說:
當我們在電商平臺購買一個商品的時候,只要訂單提交成功,那么這個訂單就一定能夠生效,也一定有庫存能夠發(fā)運和配送,而不是在后續(xù)到了配送環(huán)節(jié)的時才發(fā)現(xiàn)沒有庫存而導致訂單取消。如果這樣的話就極大的降低了系統(tǒng)本身的易用性。
即在異步命令和事件發(fā)送場景,當命令發(fā)送成功時候,雖然我們沒有及時接收到處理方的事件處理結(jié)果信息,但是我們默認是接收方能夠成功處理事件。但是我們也看到在CQRS場景框架下,只要命令事件發(fā)出,我們并不需要等待任何反饋信息。
另外還有一種CQRS實現(xiàn)場景,即雖然在內(nèi)部對Command命令處理的時候是基于事件機制,異步響應(yīng),但是客戶在前端的操作是同步等待返回。在這種情況下我們就可以保持前端連接,但是是否后端的類似DB連接等。
在CQRS模型下,由于職責分離,可以看到我們通過事件和消息的訂閱,可以實現(xiàn)多個讀庫的訂閱,這些讀庫既可以是結(jié)構(gòu)化數(shù)據(jù)庫,也可以是非結(jié)構(gòu)化數(shù)據(jù)庫;既可以用來實現(xiàn)業(yè)務(wù)功能本身的查詢讀,也可以用來做海量數(shù)據(jù)本身的分布式全文檢索。
對于CQRS框架的實施,不是簡單的設(shè)計模式使用問題,更加重要的仍然是是否能夠接受最終一致性要求,同時在該要求下將傳統(tǒng)的同步請求下業(yè)務(wù)功能和邏輯處理機制轉(zhuǎn)變?yōu)楫惒绞录r值下的事件鏈驅(qū)動模式。要實現(xiàn)這種轉(zhuǎn)變就必須能夠拆分出獨立,自治的命令和事件,同時確保這些事件在朝后端業(yè)務(wù)功能和邏輯模塊發(fā)送的時候能夠處理成功(即該做的校驗必須提前做完)。
將同步接口調(diào)用轉(zhuǎn)為本地消息緩存
這個類似消息中間件的功能,舉例來說我們設(shè)計了一個同步發(fā)送訂單到ERP系統(tǒng)的接口,如果在同步實時調(diào)用這個接口服務(wù)的時候出現(xiàn)異常,那么我們可以首先將消息存儲到本地,然后設(shè)置定時任務(wù)和重試機制,通過重試方式將消息發(fā)送到目標系統(tǒng)。
即對于業(yè)務(wù)功能來說不用關(guān)心實時是否發(fā)送成功,而由業(yè)務(wù)系統(tǒng)自身機制來完成消息發(fā)送的重試。而要做到這點,在接口功能設(shè)計時候,最好要做到單據(jù)業(yè)務(wù)完整性校驗接口和實際的數(shù)據(jù)發(fā)送接口分離,即先調(diào)用接口進行完整性校驗,在校驗沒有問題后再進行消息發(fā)送。以確保最終發(fā)送的消息不會因為數(shù)據(jù)完整性的原因?qū)е聼o法發(fā)送成功。
查詢數(shù)據(jù)的本地化緩存或落地
memcached是一套分布式的高速緩存系統(tǒng),由LiveJournal的Brad Fitzpatrick開發(fā),但被許多網(wǎng)站使用。這是一套開放源代碼軟件,以BSD license授權(quán)發(fā)布。
memcached的API使用三十二比特的循環(huán)冗余校驗(CRC-32)計算鍵值后,將數(shù)據(jù)分散在不同的機器上。當表格滿了以后,接下來新增的數(shù)據(jù)會以LRU機制替換掉。由于memcached通常只是當作緩存系統(tǒng)使用,所以使用memcached的應(yīng)用程序在寫回較慢的系統(tǒng)時(像是后端的數(shù)據(jù)庫)需要額外的代碼更新memcached內(nèi)的數(shù)據(jù)。
對于實時查詢類接口,將查詢的基礎(chǔ)數(shù)據(jù)進行本地化緩存,即如果在實時查詢出現(xiàn)異常的時候,我們可以直接查詢本地緩存的數(shù)據(jù),減少對業(yè)務(wù)功能使用的影響。
比如查詢供應(yīng)商接口服務(wù),如果主數(shù)據(jù)系統(tǒng)提供的接口出現(xiàn)異常,我們可以直接查詢本地緩存的供應(yīng)商數(shù)據(jù)。這種模式對于變更不頻繁的數(shù)據(jù)基本都適應(yīng),同時本身也減少實時調(diào)用接口帶來的性能損耗。
如果是接口服務(wù)注冊在API網(wǎng)關(guān)或ESB服務(wù)總線上面,我們還可以考慮在ESB服務(wù)總線上啟用緩存能力,即對于調(diào)用過的接口,在同樣參數(shù)重復調(diào)用的時候能夠通過緩存數(shù)據(jù)獲取,這樣即使在源端業(yè)務(wù)系統(tǒng)不可用的情況下,也不好影響到當前接口服務(wù)的成功調(diào)用。
可以適度考慮數(shù)據(jù)落地
在微服務(wù)架構(gòu)里面,我們一直在強調(diào)一點,即數(shù)據(jù)實時需要實時訪問,不進行底層數(shù)據(jù)庫的數(shù)據(jù)集成和同步,這既滿足了數(shù)據(jù)的高一致性,也滿足了數(shù)據(jù)實時性的要求。
但是帶來的問題就是強耦合,如果數(shù)據(jù)提供方出現(xiàn)異常,那么導致消費方業(yè)務(wù)功能也無法使用。后臺(朱小廝的博客)回復1024,即可領(lǐng)取k8s資料。
因為我們可以適量考慮數(shù)據(jù)落地方式的數(shù)據(jù)集成在整體微服務(wù)架構(gòu)實施過程中,對于變化不頻繁的數(shù)據(jù)適度落地到微服務(wù)模塊本地。這樣本身可以減少實時的業(yè)務(wù)接口服務(wù)調(diào)用,增加單個微服務(wù)模塊的可用性和可靠性。
對于已經(jīng)出現(xiàn)強耦合如何重構(gòu)
如果微服務(wù)已經(jīng)實施完成并出現(xiàn)了大量緊耦合的情況,那么我們就需要在后期考慮對微服務(wù)架構(gòu)進行重構(gòu),具體重構(gòu)的方法可以從如下幾點考慮。
兩個微服務(wù)本身緊耦合
如果兩個微服務(wù)間出現(xiàn)大量接口相互調(diào)用,即可以認為緊耦合。
或者我原來的判斷標準,即兩個微服務(wù)對應(yīng)的后臺數(shù)據(jù)表,其中30%以上都需要兩個微服務(wù)交叉訪問,那么就認為兩個微服務(wù)本身耦合性極強。
在這種情況下處理措施就是原來微服務(wù)劃分的太細了,需要對兩個微服務(wù)進行合并。
交叉依賴變?yōu)楣残砸蕾?/h3>
要知道在傳統(tǒng)軟件開發(fā)里面往往是不允許兩個組件交叉依賴的。
但是在新的IOC和微服務(wù)開發(fā)里面,大量都是反射調(diào)用,兩個組件相互依賴不會有問題。但是這本身也不是一種很好的設(shè)計方法。
如果兩個微服務(wù)或多個微服務(wù)相互依賴內(nèi)容本身具備共性。那么最好的做法就是將共性內(nèi)容全部移出,下沉為一個共性基礎(chǔ)微服務(wù)模塊再朝上提供服務(wù)。
即交叉依賴轉(zhuǎn)變?yōu)閷Φ讓拥墓残砸蕾嚒?/p>
對某個微服務(wù)實現(xiàn)單元進行遷移
為什么出現(xiàn)這種場景?
簡單來說就是原來的微服務(wù)模塊劃分和業(yè)務(wù)功能劃分不合理。比如上圖中的微服務(wù)A中的A1部分。這個部分內(nèi)容需要大量被微服務(wù)B調(diào)用,但是A1實際依賴微服務(wù)A中其它部分的內(nèi)容卻很少。
這種就是典型的A1部分功能劃分位置不合理。
最好的做法就是將A1功能從微服務(wù)A遷移到微服務(wù)B,實現(xiàn)對原有業(yè)務(wù)劃分不合理的糾正。
將細粒度服務(wù)轉(zhuǎn)變?yōu)榇至6确?wù)
服務(wù)本身應(yīng)該具備粗粒度屬性,暴露僅僅需要暴露的內(nèi)容。
比如微服務(wù)A實現(xiàn)客戶信用檢查和評級。微服務(wù)B需要客戶信用。有兩種做法
第一種是B調(diào)用A多個接口,把客戶基本信息,客戶交易信息,客戶違約信息全部查詢過來,然后自己計算客戶信用。
第二種即是只需要輸入客戶編碼,微服務(wù)A返回最早的信用評級。
對于后者就是我們常說的粗粒度接口或領(lǐng)域服務(wù),服務(wù)間的交互應(yīng)該以領(lǐng)域服務(wù)和粗粒度服務(wù)為主,避免掉完全的數(shù)據(jù)庫表的CRUD類服務(wù)接口。
想知道更多?掃描下面的二維碼關(guān)注我
當當1024圖書優(yōu)惠活動,“實付滿200再減40”的優(yōu)惠碼「J2KNAE」,囤書薅羊毛再走一波~~(使用時間:10月20日~11月3日,使用渠道:當當小程序或當當APP)
【精彩推薦】
原創(chuàng)|OpenAPI標準規(guī)范
如此簡單| ES最全詳細使用教程
ClickHouse到底是什么?為什么如此牛逼!
原來ElasticSearch還可以這么理解
面試官:InnoDB中一棵B+樹可以存放多少行數(shù)據(jù)?
點個贊+在看,少個 bug?????
總結(jié)
以上是生活随笔為你收集整理的架构 | 微服务架构下如何解耦,对于已经紧耦合下如何重构?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何构建一套高性能、高可用性、低成本的视
- 下一篇: CTO要我把这份MySQL规范贴在工位上