<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          數(shù)字化轉(zhuǎn)型:服務(wù)化設(shè)計(jì)原則 | IDCF

          共 8681字,需瀏覽 18分鐘

           ·

          2021-06-09 03:17


          來源:技術(shù)瑣話
          作者:鐘華
          本文由機(jī)械工業(yè)出版社獨(dú)家授權(quán)發(fā)布,中臺(tái)圣經(jīng)——《企業(yè)IT架構(gòu)轉(zhuǎn)型之道》作者鐘華新作《數(shù)字化轉(zhuǎn)型的道與術(shù):以平臺(tái)思維為核心支撐企業(yè)戰(zhàn)略可持續(xù)發(fā)展》
          在設(shè)計(jì)服務(wù)中心的過程中,對(duì)服務(wù)中心內(nèi)服務(wù)接口和數(shù)據(jù)模型的設(shè)計(jì)非常重要,良好的設(shè)計(jì)原則和方法可以最大化地保障服務(wù)中心的可擴(kuò)展性。
          強(qiáng)烈建議讀者學(xué)習(xí)著名建模專家Eric Evans最具影響力的著作Domain-Driven Design-Tackling Complexity in the Heart of Software(《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì):軟件核心復(fù)雜性應(yīng)對(duì)之道》)以及Thomas Erl的著作SOA principles of Service Design(《SOA服務(wù)設(shè)計(jì)原則》),在實(shí)際的服務(wù)中心設(shè)計(jì)過程中,大多數(shù)情況下都可參考這兩本書中的原則和方法。


          Fac?ade(外觀)模式



          接下來在介紹服務(wù)化設(shè)計(jì)原則時(shí),會(huì)多次出現(xiàn)Fac?ade模式。

          外觀模式的使用原理如圖4-11所示。

          外觀模式的優(yōu)點(diǎn)如下:

          • 松散耦合:外觀模式使得前臺(tái)應(yīng)用與中臺(tái)服務(wù)中心可以進(jìn)行松散耦合,讓服務(wù)中心內(nèi)部的模塊能更容易地?cái)U(kuò)展和維護(hù)。

          • 簡(jiǎn)單易用:外觀模式讓服務(wù)中心的服務(wù)更加易用,前臺(tái)應(yīng)用不再需要了解服務(wù)中心內(nèi)部的實(shí)現(xiàn),也不需要跟服務(wù)中心內(nèi)部眾多的功能模塊進(jìn)行交互,只需跟外觀類交互就可以了。

          • 更好地劃分訪問層次:通過合理使用外觀模式,可以更好地劃分訪問的層次,有些方法是對(duì)系統(tǒng)外的,有些方法是系統(tǒng)內(nèi)部使用的。把需要暴露給外部的功能集中到外觀中,這樣既方便客戶端使用,也很好地隱藏了內(nèi)部的細(xì)節(jié)。


          DTO的使用



          DTO可以將服務(wù)中心復(fù)雜或易變的數(shù)據(jù)對(duì)象對(duì)前臺(tái)應(yīng)用屏蔽,讓前臺(tái)具備更好的穩(wěn)定性。DTO是系統(tǒng)分層設(shè)計(jì)和服務(wù)化架構(gòu)中經(jīng)常使用的技術(shù),概念本身也容易理解,如圖4-12所示。


          服務(wù)接口的設(shè)計(jì)原則



          業(yè)務(wù)中臺(tái)架構(gòu)的核心是各個(gè)業(yè)務(wù)領(lǐng)域的設(shè)計(jì)建模以及服務(wù)接口的設(shè)計(jì),筆者結(jié)合業(yè)界優(yōu)秀的設(shè)計(jì)原則以及自己的實(shí)踐,將服務(wù)接口典型的設(shè)計(jì)原則整理如下,供各位讀者參考。
          1、契約先行
          服務(wù)間的交互類似于不同組織之間的合作,按照正常邏輯,兩個(gè)組織之間合作的首要任務(wù)就是先簽訂明確的契約,詳細(xì)規(guī)定雙方合作的內(nèi)容、合作的形式,等等,這樣才能對(duì)雙方形成強(qiáng)有力的約束和保障,同時(shí)工作也能夠并行不悖,不用相互等待。因此服務(wù)化架構(gòu)中最佳的實(shí)踐方式也是服務(wù)契約先行,即先做服務(wù)契約的設(shè)計(jì)。在進(jìn)行服務(wù)接口設(shè)計(jì)時(shí)需要有業(yè)務(wù)、產(chǎn)品和技術(shù)等不同方面的人員共同參與,并定義出相應(yīng)的契約,然后再實(shí)現(xiàn)具體的代碼。
          在實(shí)際的中臺(tái)架構(gòu)設(shè)計(jì)階段,當(dāng)在企業(yè)不同的業(yè)務(wù)部門收集到業(yè)務(wù)需求,形成產(chǎn)品需求調(diào)研文檔后,需要從全局的視角對(duì)服務(wù)中心的服務(wù)接口進(jìn)行統(tǒng)籌設(shè)計(jì),即不是按照單一應(yīng)用場(chǎng)景,如僅從電商或僅從CRM系統(tǒng)的角度,進(jìn)行服務(wù)接口設(shè)計(jì)。雖然這些前臺(tái)系統(tǒng)都是按照步驟逐步建設(shè)起來的,但服務(wù)中心的接口設(shè)計(jì)首先需要在全局的業(yè)務(wù)視角下進(jìn)行規(guī)劃和設(shè)計(jì),有了清晰的接口設(shè)計(jì),前臺(tái)和服務(wù)中心就有了清晰而相對(duì)穩(wěn)定的交互邊界,就能大大降低后期實(shí)現(xiàn)和運(yùn)營(yíng)期的協(xié)作成本,總體效率更高。
          由于服務(wù)的用戶范圍很廣,在服務(wù)契約公開發(fā)布之后就要保證良好的穩(wěn)定性,不能隨便重構(gòu),即使升級(jí)也要考慮盡可能地向下兼容性。
          2、服務(wù)功能內(nèi)聚
          服務(wù)功能內(nèi)聚幾乎是任何服務(wù)化設(shè)計(jì)中最基本的要求。要?jiǎng)?chuàng)建功能內(nèi)聚的服務(wù)接口,應(yīng)該使功能相關(guān)的一組操作聚合到一起,同時(shí)必須將可能影響到業(yè)務(wù)正確性的邏輯在對(duì)應(yīng)的服務(wù)中提供,而不能依賴服務(wù)調(diào)用方遵循正確邏輯。
          比如,用戶注冊(cè)的服務(wù),其中包含了對(duì)于用戶郵箱格式、用戶名稱以及密碼強(qiáng)度的校驗(yàn)邏輯,雖然這些邏輯在前臺(tái)應(yīng)用的Web頁(yè)面或者App中都進(jìn)行了相關(guān)的校驗(yàn),但前臺(tái)應(yīng)用最終調(diào)用用戶中心的用戶注冊(cè)服務(wù)時(shí),依然要在該服務(wù)中實(shí)現(xiàn)對(duì)這些用戶屬性的校驗(yàn)工作,而不能寄希望于前臺(tái)應(yīng)用做這些校驗(yàn)工作,這樣才能避免因?yàn)榍芭_(tái)應(yīng)用遺漏校驗(yàn)而導(dǎo)致不合規(guī)則的用戶能成功進(jìn)行注冊(cè)。
          一個(gè)典型的服務(wù)功能內(nèi)聚的例子如圖4-13所示。
          3、服務(wù)粗粒度
          服務(wù)的使用者對(duì)特定業(yè)務(wù)流程的了解一般比不上服務(wù)中心內(nèi)部的人,所以服務(wù)的接口設(shè)計(jì)通常需要粗粒度,一個(gè)操作有可能對(duì)應(yīng)一個(gè)完整的業(yè)務(wù)用例或者業(yè)務(wù)流程,這樣既能減少遠(yuǎn)程調(diào)用次數(shù),又能降低學(xué)習(xí)成本和耦合度。
          例如,文檔服務(wù)要給前臺(tái)應(yīng)用提供批量刪除文章的支持,已有接口中提供deleteArticle(long id)方法,可以供用戶自己做循環(huán)調(diào)用來實(shí)現(xiàn)批量刪除文章的目的。此時(shí),服務(wù)中心最好提供deleteArticles(Set ids)方法供前臺(tái)應(yīng)用調(diào)用,將N次遠(yuǎn)程調(diào)用減少為一次。
          再例如,用戶下訂單的用例,要有一系列操作: 
          addItem(累計(jì)商品)→addTax(計(jì)算稅)→calculateTotalPrice(計(jì)算總價(jià))→ placeOrder (創(chuàng)建訂單)
          交易中心當(dāng)然可以將這些服務(wù)以單個(gè)接口方法的方式提供給前臺(tái)應(yīng)用,這樣不僅需要前臺(tái)應(yīng)用對(duì)于訂單創(chuàng)建流程和邏輯有更高的要求,而且會(huì)增加出現(xiàn)服務(wù)調(diào)用錯(cuò)誤的概率,最好封裝一個(gè)粗粒度的方法供用戶做一次性遠(yuǎn)程調(diào)用,同時(shí)也隱藏了內(nèi)部業(yè)務(wù)的很多復(fù)雜性。服務(wù)調(diào)用方也從依賴4個(gè)方法變成了依賴1個(gè)方法,從而大大降低了程序耦合度。
          另外,從服務(wù)和接口方法的數(shù)量角度來看,服務(wù)將通常作為測(cè)試和發(fā)布的單位,如果粒度過粗,將大量操作分組到單個(gè)服務(wù)中,則可能增加單個(gè)服務(wù)的使用者,這樣就為服務(wù)使用者快速找到正確的操作帶來了挑戰(zhàn),從而導(dǎo)致服務(wù)使用體驗(yàn)不佳。要更改服務(wù),勢(shì)必需要重新發(fā)布整個(gè)服務(wù),從而影響較多使用者。
          所以要避免服務(wù)粒度的兩個(gè)極端:
          • 提供僅有幾個(gè)方法的很多服務(wù)。
          • 數(shù)十或數(shù)百個(gè)操作均集中在幾個(gè)服務(wù)中。
          應(yīng)考慮多個(gè)因素,如可維護(hù)性、可操作性和易用性,并進(jìn)行折中。
          還有一種劃分服務(wù)粒度的方法是,創(chuàng)建反映業(yè)務(wù)對(duì)象生命周期的狀態(tài)的服務(wù)接口。例如,費(fèi)用申領(lǐng)中,每筆費(fèi)用申領(lǐng)的生命周期都包含四個(gè)狀態(tài),如圖4-14所示。
          由于業(yè)務(wù)對(duì)象狀態(tài)常常能同時(shí)反映業(yè)務(wù)和技術(shù)兩方面的內(nèi)容,因此完全可以將ExpenseClaimService(費(fèi)用申領(lǐng)服務(wù))拆分為適應(yīng)每個(gè)狀態(tài)的多個(gè)服務(wù):ClaimEntryService(費(fèi)用構(gòu)建服務(wù))、ClaimApprovalService(費(fèi)用審批服務(wù))、ClaimPaymentService(費(fèi)用支付服務(wù)),得到如下所示的服務(wù)代碼:
          ClaimEntryService {
          createClaim(String userId);
          ClaimItemDetails[] getClaimItems(int );
          ClaimErrors[] validateClaim(int claimId);
          void removeClaimItem(int claimId, int itemId);
          int addClaimItem(int claimId, ClaimItemDetails details)
          int submitClaim(int claimId);
          }

          ClaimApprovalService {
          int approveClaimItem(int claimId, int itemId, String comment);
          void approveClaim(claimId)
          void returnClaim(claimId)
          ClaimItemDetails[] getClaimItems(int );
          ClaimErrors[] validateClaim(int claimId);
          }

          ClaimPaymentService {
          void payClaim(int claimId);
          }
          通過這種方式,能更方便地理解每個(gè)服務(wù)。而且,將接口這樣劃分非常適合服務(wù)的開發(fā)、部署、維護(hù)和使用方式。總結(jié)來說,通過將劃分邏輯放在對(duì)象生命周期上,我們就可以建立具有恰當(dāng)粒度的服務(wù)。
          4、消除冗余數(shù)據(jù)
          由于服務(wù)的遠(yuǎn)程調(diào)用需要網(wǎng)絡(luò)開銷,特別是在并發(fā)量很大的場(chǎng)景下,這樣的開銷就不是一個(gè)可以忽略的因素了。所以在服務(wù)的輸入?yún)?shù)和返回結(jié)果中,要盡量避免攜帶當(dāng)前業(yè)務(wù)場(chǎng)景不需要的冗余字段,來減少序列化和傳輸?shù)拈_銷。同時(shí),去掉冗余字段也可以簡(jiǎn)化接口,避免給外部用戶帶來不必要的困惑。
          比如“文檔服務(wù)”中有個(gè)返回文章列表的方法:

          List <Article> getArticles(...)

          如果業(yè)務(wù)需求僅僅是要列出文章的標(biāo)題,那么在返回的文章對(duì)象中就要避免攜帶它的內(nèi)容等字段。
          這里有一個(gè)經(jīng)典解決方案,就是引入前面提到的DTO模式,專門針對(duì)前臺(tái)業(yè)務(wù)應(yīng)用定制要傳輸?shù)臄?shù)據(jù)字段,這里需要添加一個(gè)AriticleSummary(文章概要)的額外數(shù)據(jù)傳輸對(duì)象:

          List<ArticleSummary> getArticleSummaries(...)

          ArticleSummary能很好地避免服務(wù)中心與前臺(tái)應(yīng)用間的冗余數(shù)據(jù)傳輸。
          5、通用契約
          由于服務(wù)不假設(shè)用戶的范圍,所以一般要支持不同語言和平臺(tái)的客戶端。但各種語言和平臺(tái)在功能豐富性上有很大差異,這就決定了服務(wù)契約必須取常見語言、平臺(tái)以及序列化方式的最大公約數(shù),才能保證服務(wù)具備廣泛兼容性。因此,服務(wù)契約中不能有某些語言才具備的高級(jí)特性,參數(shù)和返回值也必須是被廣泛支持的較簡(jiǎn)單的數(shù)據(jù)類型(比如不能有對(duì)象循環(huán)引用)。
          例如,原有對(duì)象模型如下:
          Class Foo {
          private Pattern regex;
          }
          其中,Pattern是Java特有的預(yù)編譯,可序列化正則表達(dá)式(可提高性能),但在沒有特定框架支持的情況下,其他開發(fā)語言可能識(shí)別不了,所以最好采用DTO的方式改成常用的數(shù)據(jù)類型,如下所示:
          Class FooDto {
          private String regex;
          }

          6、隔離變化原則

          當(dāng)服務(wù)中心核心領(lǐng)域模型的對(duì)象進(jìn)入前臺(tái)應(yīng)用中,要避免服務(wù)中心內(nèi)部的重構(gòu)或者模型變更導(dǎo)致前臺(tái)應(yīng)用也跟著變化。

          比如前面描述的“文檔服務(wù)”,其中Article對(duì)象在服務(wù)中心內(nèi)部可能作為核心建模的領(lǐng)域模型,甚至作為對(duì)象和數(shù)據(jù)庫(kù)映射(O/R mapping)等。如果文檔服務(wù)給服務(wù)消費(fèi)者直接返回Article,即使沒有前面所說的冗余字段、復(fù)雜類型等問題,也可能讓服務(wù)外部用戶與服務(wù)內(nèi)部系統(tǒng)的核心領(lǐng)域模型產(chǎn)生一定的關(guān)聯(lián),甚至可能與O/R mapping機(jī)制、數(shù)據(jù)表結(jié)構(gòu)等產(chǎn)生關(guān)聯(lián),這樣一來,內(nèi)部的重構(gòu)很可能影響到服務(wù)外部的用戶。

          同樣,可采用外觀模式和DTO作為中介者和緩沖帶,隔離內(nèi)外系統(tǒng),把內(nèi)部系統(tǒng)變化對(duì)外部的沖擊降到最低。

          7、契約包裝

          雖然使用了DTO和外觀模式將服務(wù)生產(chǎn)端的變化與服務(wù)消費(fèi)端進(jìn)行了隔離,但DTO和外觀模式可能被服務(wù)消費(fèi)端的程序到處引用,這樣消費(fèi)端程序就較強(qiáng)地耦合在服務(wù)契約上了。一旦契約更改,或者消費(fèi)端要選擇完全不同的服務(wù)提供方(有不同的契約),修改時(shí)工作量可能就非常大了。在較理想的面向服務(wù)設(shè)計(jì)中,可以考慮包裝遠(yuǎn)程服務(wù)訪問邏輯,也稱為服務(wù)代理(Delegate Service)模式,由消費(fèi)端自己主導(dǎo)定義接口和參數(shù)類型,并將服務(wù)調(diào)用轉(zhuǎn)發(fā)給真正的服務(wù)客戶端,從而讓服務(wù)使用者完全屏蔽服務(wù)契約。

          服務(wù)代理示例如下:

          //ArticlesService是消費(fèi)端自定義的接口
          class ArticlesServiceDelegate implements ArticlesService {
          //假設(shè)是某種自動(dòng)生成的service客戶端stub類
          private ArticleFacadeStub stub;

          public void deleteArticles(List<Long> ids) {
          stub.deleteArticles(ids);
          }
          }

          在此示例的前臺(tái)應(yīng)用中,所有有關(guān)文檔服務(wù)調(diào)用的地方引用的都是ArticlesService,而不是“文檔服務(wù)”提供的ArticleFacadeStub,這樣就算服務(wù)提供端的ArticleFacadeStub發(fā)生了變更或者重構(gòu),也只需要在ArticlesService類中進(jìn)行相應(yīng)的調(diào)整,而無須更改更多的代碼。

          8、服務(wù)無狀態(tài)原則

          為了保證服務(wù)中心的服務(wù)穩(wěn)定性以及可擴(kuò)展性,必須將服務(wù)設(shè)計(jì)為可伸縮的且可部署到高可用的基礎(chǔ)結(jié)構(gòu)中。此重要原則的一個(gè)推論就是,服務(wù)不應(yīng)為“有狀態(tài)型”的。即服務(wù)不應(yīng)依賴于服務(wù)使用者和服務(wù)生產(chǎn)者之間長(zhǎng)期存在的關(guān)系,服務(wù)調(diào)用也不應(yīng)顯式或隱式地依賴于前一次調(diào)用。為了說明這一點(diǎn),我們舉一個(gè)簡(jiǎn)單的例子,下面是一個(gè)電話對(duì)話:
          問:小明的賬號(hào)余額是多少?
          答:320元。
          問:他的信用額度是多少?
          答:2000元。
          此示例演示了典型的有狀態(tài)模式。第二個(gè)問題通過使用“他的”引用第一個(gè)問題。這個(gè)示例中的操作依賴于轉(zhuǎn)換上下文。現(xiàn)在讓我們考慮一下所提供的應(yīng)答,請(qǐng)注意,回答中沒有上下文信息。只有在被詢問者知道所詢問的問題時(shí),這個(gè)回答才有意義。在此示例中,要求使用者維護(hù)對(duì)話狀態(tài),以便解釋所得到的應(yīng)答。
          首先,我們考慮一下依賴于前一操作建立的上下文的操作。假如這是一個(gè)與呼叫中心的交互,只要與同一個(gè)操作人員對(duì)話,對(duì)話就可以有效地結(jié)束。但我們假設(shè)呼叫被中斷了,如下所示:
          問:小明的賬號(hào)余額是多少?
          話務(wù)員1:320元。
          此時(shí)通話中斷,被轉(zhuǎn)接到另一個(gè)話務(wù)員:
          問:他的信用額度是多少?
          話務(wù)員2:誰?
          中斷導(dǎo)致上下文丟失,因此第二個(gè)問題是沒有意義的。就這個(gè)電話對(duì)話而言,我們可以通過重新建立上下文而抵消中斷帶來的后果:“我在問小明的銀行賬戶的信息,您能告訴我他的信用額度嗎?”不過,在可擴(kuò)展服務(wù)調(diào)用領(lǐng)域,有狀態(tài)對(duì)話通常更為麻煩,重新建立上下文也許在技術(shù)上可行,但很可能帶來很大的性能開銷。
          是否要求使用關(guān)聯(lián)性。即相同的服務(wù)使用者發(fā)出的連續(xù)請(qǐng)求是否必須交付到相同的服務(wù)提供者實(shí)例,要求使用關(guān)聯(lián)性是一種有狀態(tài)性與可伸縮性及可靠性沖突的情況。為了保持服務(wù)中心各服務(wù)能力的服務(wù)質(zhì)量,我們必須優(yōu)先考慮最終服務(wù)架構(gòu)的可伸縮性和可靠性。所以筆者強(qiáng)烈建議,將服務(wù)設(shè)計(jì)為可避免維護(hù)會(huì)話上下文的需求。
          回到上面電話對(duì)話的示例,我們可以通過將服務(wù)設(shè)計(jì)為在響應(yīng)中包含合適的關(guān)聯(lián)信息,從而避免對(duì)會(huì)話狀態(tài)的需求,如下所示:
          問:小明的信用額度是多少?
          答:小明的信用額度是2000元。
          在響應(yīng)中包含關(guān)聯(lián)信息是很好的做法,原因很多。首先,它簡(jiǎn)化了可伸縮解決方案的構(gòu)造,還能提供更多的診斷幫助,且在不可能向原始請(qǐng)求程序交付錯(cuò)誤響應(yīng)時(shí)非常重要??傊?,仔細(xì)地進(jìn)行服務(wù)設(shè)計(jì)可以避免對(duì)狀態(tài)的需求,從而簡(jiǎn)化可靠的、可伸縮服務(wù)結(jié)構(gòu)的實(shí)現(xiàn)。
          9、服務(wù)命名原則
          我們?cè)谶x擇服務(wù)、操作、數(shù)據(jù)類型和參數(shù)的名稱時(shí)有一個(gè)指導(dǎo)原則:希望最大化服務(wù)的易用性。我們希望幫助業(yè)務(wù)應(yīng)用開發(fā)人員標(biāo)識(shí)實(shí)現(xiàn)業(yè)務(wù)流程所需的服務(wù)和操作,因此,強(qiáng)烈建議對(duì)服務(wù)使用者定義專業(yè)領(lǐng)域內(nèi)有意義的名稱,優(yōu)先選用業(yè)務(wù)概念而不是技術(shù)概念。建議就是:應(yīng)使用名詞對(duì)服務(wù)進(jìn)行命名,使用動(dòng)詞對(duì)操作進(jìn)行命名。例如,以下是使用動(dòng)詞短語和IT構(gòu)造的服務(wù)定義:
          ManageCustomerData { 
          insertCustomerRecord();
          updateCustomerRecord();
          //etc ... }

          接下來是使用名詞和動(dòng)詞短語及業(yè)務(wù)概念的服務(wù)定義:

          CustomerService {
          createNewCustomer();
          changeCustomerAddress();
          correctCustomerAddress();
          // etc ... }

          比較明顯,第二個(gè)示例的易用性更好一些。在第二個(gè)示例中,服務(wù)的業(yè)務(wù)用途非常清楚,而不僅僅指示其輸出。因此,建議不要使用“update-CustomerRecord”(可以為出于任何原因進(jìn)行的任何更新),而使用“enable-OverdraftFacility(啟用透支能力)”。

          與此類似,在客戶搬遷時(shí),我們使用“changeCustomerAddress”方法更改客戶地址;而在希望更正無效數(shù)據(jù)時(shí)使用“correctCustomerAddress”更正客戶地址,因?yàn)檫@樣很容易看出這兩個(gè)操作采用了不同的服務(wù)邏輯。

          10、服務(wù)操作設(shè)計(jì)原則

          這是對(duì)于服務(wù)操作命名設(shè)計(jì)原則的進(jìn)一步深化:應(yīng)當(dāng)使用具體的業(yè)務(wù)含義而不是泛型操作對(duì)操作進(jìn)行定義。例如,不要使用泛泛的update-CustomerDetails操作,而要?jiǎng)?chuàng)建changeCustomerAddress、recordCustomer-Marriage和addAlternativeCustomerContactNumber之類的操作。

          此方法具有以下好處:

          • 操作與具體業(yè)務(wù)場(chǎng)景對(duì)應(yīng)。此類場(chǎng)景可能不僅是簡(jiǎn)單地更新數(shù)據(jù)庫(kù)中的記錄。例如,更改地址或婚姻狀況可能需要更改其他業(yè)務(wù)模塊中的相關(guān)信息,比如婚姻狀況的修改可能會(huì)引起會(huì)員權(quán)益的改變。如果使用不太具體的操作(如UpdateCustomerDetails),則不適合實(shí)現(xiàn)此類業(yè)務(wù)場(chǎng)景。

          • 各個(gè)操作接口將非常簡(jiǎn)單,且易于理解,從而提高易用性。

          • 每個(gè)操作的更新單元有清楚的定義(在我們的示例中為地址、婚姻狀況和電話號(hào)碼)。在實(shí)現(xiàn)具有高并發(fā)性要求的系統(tǒng)時(shí),我們可以基于操作的要求采用更細(xì)粒度的鎖定策略,從而減少資源爭(zhēng)用。

          針對(duì)操作中參數(shù)的設(shè)計(jì),應(yīng)采用粗粒度和靈活性強(qiáng)的參數(shù),目的是盡量減少因?yàn)樾枨笞兏鼛淼膮?shù)結(jié)構(gòu)變化。

          以CreateNewCustomer操作的兩個(gè)接口為例。

          • 采用細(xì)粒度參數(shù)的CreateNewCustomer操作接口如下:

          int CreateNewCustomer(String familyName,String givenName,
          String initials, int age,String address1,
          String address2, String postcode // ... )
          • 采用單個(gè)粗粒度參數(shù)的CreateNewCustomer操作接口如下:

          int CreateNewCustomer( CustomerDetails newDetails)
          以上兩段示例代碼顯示了一個(gè)具有很多細(xì)粒度參數(shù)的操作和采用結(jié)構(gòu)化類型作為單個(gè)粗粒度參數(shù)的操作。之所以建議使用粗粒度參數(shù),是因?yàn)檫@樣能夠在很大程度上避免因?yàn)榧?xì)粒度參數(shù)變化帶來服務(wù)整體版本升級(jí)。
          從參數(shù)靈活性的角度看,要考慮服務(wù)需求的多樣性和靈活性。比如,在查詢商品信息時(shí),商品定義的字段很多,不同的業(yè)務(wù)關(guān)注的字段不一樣,所以在定義接口時(shí),可通過傳入業(yè)務(wù)方需要返回的商品的字段,將這些字段保存在List對(duì)象中,服務(wù)獲取對(duì)應(yīng)字段的值后封裝成對(duì)應(yīng)的Map對(duì)象返回。這樣通過一個(gè)商品查詢的操作方法就能滿足不同應(yīng)用系統(tǒng)對(duì)商品字段的信息獲取需求。
          11、重要的服務(wù)不能依賴非重要的服務(wù)
          中臺(tái)建設(shè)是以服務(wù)為中心,即整個(gè)體系間的交互均以服務(wù)的形式進(jìn)行。不僅前臺(tái)應(yīng)用和中臺(tái)的各服務(wù)中心會(huì)以服務(wù)的方式進(jìn)行交互,而且各服務(wù)中心之間也會(huì)這樣交互。在有些情況下,前臺(tái)應(yīng)用在業(yè)務(wù)復(fù)雜度發(fā)展到一定程度后,也會(huì)建立起在該應(yīng)用系統(tǒng)內(nèi)部的服務(wù)體系。比如,天貓和淘寶這樣的業(yè)務(wù)前端應(yīng)用已經(jīng)非常復(fù)雜,其內(nèi)部就構(gòu)建起了一個(gè)多層的服務(wù)體系。業(yè)務(wù)中臺(tái)的各服務(wù)中心為這個(gè)服務(wù)體系的最下層,之上的各前端業(yè)務(wù)系統(tǒng)中又會(huì)按照自身業(yè)務(wù)的特點(diǎn)建立起自己的服務(wù)層級(jí)。
          在整個(gè)服務(wù)體系中,有交易、商品、訂單相關(guān)等這一類非常核心和重要的服務(wù),也有相對(duì)不重要的服務(wù),如運(yùn)費(fèi)計(jì)算或者前端應(yīng)用中所創(chuàng)建的服務(wù)。從服務(wù)對(duì)業(yè)務(wù)的影響程度、服務(wù)范圍就會(huì)體現(xiàn)出服務(wù)重要性不同,而且服務(wù)重要性的不同也直接決定了能得到的支持和保障資源會(huì)有差異,從而最終會(huì)體現(xiàn)在服務(wù)的穩(wěn)定和可靠性方面。所以越在下層的服務(wù)會(huì)越穩(wěn)定,越往上層的服務(wù)則不管是穩(wěn)定性還是業(yè)務(wù)兼容性方面都不如下層服務(wù)。
          “重要的服務(wù)不能依賴非重要的服務(wù)”這一原則可以更加細(xì)化,如下所示:
          • 上可依賴下。越上層的服務(wù)實(shí)現(xiàn)可以依賴下層的服務(wù),也可跨級(jí)依賴。
          • 下不可依賴上。下層的服務(wù)實(shí)現(xiàn)和運(yùn)行一定不能依賴上層的服務(wù),否則就會(huì)出現(xiàn)因?yàn)樯蠈臃?wù)質(zhì)量問題和不穩(wěn)定的表現(xiàn)影響到下層的重要服務(wù),而下層服務(wù)的故障將會(huì)影響到依賴這一服務(wù)的所有平級(jí)服務(wù)中心和前臺(tái)應(yīng)用的情況,會(huì)出現(xiàn)嚴(yán)重的“雪崩”效應(yīng)。
          • 平級(jí)可依賴,避免循環(huán)依賴。這一原則最典型的體現(xiàn)是業(yè)務(wù)中臺(tái)的各服務(wù)中心在服務(wù)層級(jí)中均屬于平級(jí),它們均有同級(jí)別的服務(wù)運(yùn)營(yíng)要求,是可以互相依賴的。
          • 高級(jí)別不可依賴低級(jí)別。業(yè)務(wù)重要性明顯高的服務(wù)不能依賴業(yè)務(wù)重要性低的服務(wù),應(yīng)做好相應(yīng)的服務(wù)降級(jí),或者通過前臺(tái)業(yè)務(wù)隔離這種情況的服務(wù)依賴。

           總 結(jié)



          簡(jiǎn)單就是美,過多的原則可能會(huì)讓整體的設(shè)計(jì)變得臃腫,在什么情況下采用什么樣的原則,需要建立在對(duì)業(yè)務(wù)理解的基礎(chǔ)上,而且需要在實(shí)踐過程中不斷練習(xí),從而能更從容地應(yīng)對(duì)服務(wù)設(shè)計(jì)相關(guān)的問題。
          “有過DevOps黑客馬拉松的人生,才算完整!”
          7月24-25日,IDCF DevOps黑客馬拉松·北京,等你來挑戰(zhàn)??!??
          瀏覽 70
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  a 在线免费观看 | 91天天爱天天射天天干天天 | 国精产品乱码一区一区三区四区 | 99在线视频免费 | 杨思敏一级A片婬片 |