主頁 > 後端開發 > Java生鮮電商平臺-微服務生鮮電商系統設計(小程式/APP)

Java生鮮電商平臺-微服務生鮮電商系統設計(小程式/APP)

2020-11-24 22:30:22 後端開發

Java生鮮電商平臺-微服務生鮮電商系統設計(小程式/APP)

說明:本文章主要是講解-微服務生鮮電商系統設計與架構,希望對大家有所幫助

          在實際業務場景中如何設計一套電商系統呢?

  1.   我們簡單想象一下,既然是一個電商系統,有用戶去購買,就肯定得有一個用戶模塊,購買什么東西總不是西北風吧,購買肯定是商品吧,省掉購物車,就得有商品模塊吧,
  2.  商品總得有庫存吧,庫存就暫時跟商品放一起吧,什么倉儲物流先別管,就當作是虛擬商品好了,反正題目也沒說不能是虛擬商品,_
  3.  購買成功了,那就必須有訂單吧,加個訂單模塊,下完單總得支付吧,不付錢人家憑什么把東西給你,那就得有個支付模塊,
   

簡單粗暴,四個模塊,如上圖:

  • 用戶模塊

  • 商品模塊(庫存)

  • 訂單模塊

  • 支付模塊

好,幾個模塊搞定,外加下單流程圖:

   

等等,貌似題目說是微服務,既然是微服務就涉及到拆分服務的問題,

DDD 領域驅動設計

剛剛確實是梳理了一下模塊,既然是微服務,就得進行服務的拆分,服務怎么進行拆分呢?

貌似按照剛次梳理模塊來劃分也是可以的,不過這樣好像顯得我很是不專業,聽說現在很多人都要使用 DDD(領域驅動設計)來指導微服務的拆分,

   

參考 DDD 的設計,DDD 官方的架構草圖,總體架構分為四層:

  • Infrastructure(基礎實施層)

  • Domain(領域層)

  • Application(應用層)

  • Interfaces(表示層,也叫用戶界面層或是介面層)

微服務結合 DDD

不過對于領域設計而言,代碼層其實不是最重要,最重要的是如何去劃分領域,劃分好邊界,

而對于微服務而言,非常適合從業務上去劃分各個 Modules,劃分好各個業務板塊,微服務 + DDD,個人覺得首先從微服務的角度考慮去劃分大的業務模塊,每個微服務都應該是一個可以獨立部署,各司其職的模塊,

簡單的說,在微服務實際的開發中,結合 DDD 的思想去劃分所有屬于自己的領域,

實施 DDD 的關鍵

第一點是使用通過的語言建立所有的聚合,物體,值物件,

第二點也就是最關鍵的“建模”:

  • 劃分“戰略建模”,從一種宏觀的角度去審核整個專案,劃分出“界限背景關系”,形成具有上帝視角的“背景關系映射圖”,

  • 還有一個建模是“戰術建模”,在我們的“戰略建模”劃分出來的“界限背景關系”中進行“聚合”,“物體”,“值物件”,并按照模塊分組,

構建電商系統的背景關系映射圖

先來確定我們的戰略核心的領域是什么?我們的目的是什么?

作為一個電商系統,我們的核心肯定是賣出更多的商品,獲取更多訂單更多的利潤,那么銷售可以作為我們的一個核心的領域,

這個作為一個明確核心域確立下來:

   

確定完核心子域后,根據對這個領域的理解劃分出各個背景關系,然后根據背景關系再確定其他的相關領域,

   

初步我們可以看出圍繞銷售核心域的包含的幾大塊內容,價格,銷售方式,購買的方式,已經購買,

然后我們對支撐著核心域的子域也做了劃分,支撐著核心域的有商品域,用戶域,通用域有訂單域,物流域,支付域,

回到我們的主題,我們這次沒有購物車,也沒有各個會員銷售價格,把一些背景關系拿掉,并建立映射,

   

領域驅動設計看似簡單,其實很難實施,因為在各個環節中都需要對應的領域專家的參加或指導,這樣才能設計出最符合實際的背景關系映射圖,

而且我們花費的精力可能相比以后的資料驅動開發模式更多,但在整體對專案的把控性能上說,領域比資料驅動更加抽象,更加的頂層設計,在對應互聯網的多變情況看得更遠,

我們將微服務拆分為 5 個領域,分別是:

  • 銷售域

  • 商品域

  • 用戶域

  • 訂單域

  • 支付域

完美,接下來就可以開始開發了,^?_?^

 

等等,兵馬未動,糧草先行;代碼未動,圖先行,先把時序圖畫出來,

時序圖

一個簡單的下單流程,涵蓋了幾個領域:

   

完美,接下來就可以開發微服務了,^?_?^

 

等等,微服務的技術堆疊還未選型,

微服務技術堆疊選型

服務拆分完了,時序圖也畫完了,可以開始我們的微服務之旅了,目前主流的微服務有阿里大名鼎鼎的 Dubbo 和 Spring Cloud 全家桶,還有新浪的 Motan,

比較熟悉的還是 Dubbo 和 Spring Cloud,也都使用過,究竟應該選用哪一個呢?

因為之前都使用過,做點簡單,粗暴的總結,Dubbo 在很早之前就開始使用,當時的微服務還沒有現在這么火,很多理論體系也未完善,Dubbo 更像是一套 RPC 整合框架,Spring Cloud 則更傾向微服務架構的生態,

相比 Dubbo,Spring Cloud 可以說是微服務一整套的解決方案,在功能上是 Dubbo 的一個超級,

Dubbo 和 Spring Cloud 比喻,Dubbo 架構的微服務就像組裝電腦,各個環節自由度很高,Spring Cloud 更像品牌機,

基于不折騰,簡單快捷,更傾向選擇 Spring Cloud,OK,就定下來技術堆疊使用 Spring Cloud,愉快的決定

 

等等,就這么草率就決定用 Spring Cloud 做為微服務,難道不需要把微服務的利弊先弄清楚嗎?

微服務的利和弊

既然選擇了微服務,就得知道微服務的利和弊,特別是弊,引入了微服務,就等于引入了一套復雜的體系,一套復雜的體系帶來的各種挑戰必須事先了解清楚,

   

①強模塊化邊界

我們知道做軟體架構,軟體設計,模塊化是非常重要的一點,一開始我們寫程式做軟體,我們采用類的方式來做模塊化,后面開始采用組件或類別庫的方式做模塊化,可以做到工程上的重用和分享給其他團隊來使用,

微服務在組件的層次上面又高了一層,以服務的方式來做模塊化,每個團隊獨立開始和維護自己的服務,有明顯的一個邊界,

開發完一個服務,其他團隊可以直接呼叫這個服務,不需要像組件通過 Jar 或原始碼的方式去進行分享,所以微服務的邊界是比較清晰的,

②可獨立部署
③技術多樣性

弊(或者說挑戰)

①分布式復雜性

在原來單塊應用就是一個應用,一個對單塊應用的架構比較熟悉的人可以對整個單塊應用有一個很好的把控,

但是到了分布式系統,微服務化了以后可能涉及到的服務有好幾十個,一些大公司可能涉及到的服務上百個,服務與服務之間是通過相互溝通來實作業務,

那么這個時候整個系統就變成非常復雜,一般的開發人員或一個團隊都無法理解整個系統是如何作業的,這個就是分布式帶來的復雜性,

②最終一致性

微服務的資料是分散式治理的,每個團隊都有自己的資料源和資料拷貝,比方說團隊 A 有訂單資料,B 團隊也有訂單資料,團隊 A 修改了訂單資料是否應該同步給團隊 B 的資料呢?

這里就涉及到資料一致性問題,如果沒有很好的解決一致性問題,就可能造成資料的不一致,這個在業務上是不可以接受的,

③運維復雜性

以往的運維需要管理的是機器+單塊的應用,分布式系統和單塊應用不一樣的是,分布式系統需要很多的服務,服務與服務之間相互協同,

那么對分布式系統的資源,容量規劃,監控,對整個系統的可靠性穩定性都非常具備挑戰的,

只有在清楚了解微服務帶來的挑戰,明知道山有虎偏向虎山行,才能夠真正的勝任挑戰,最重要的是,要清楚明了里面有什么坑,怎么避免踩坑,

完美,已經了解微服務帶來的好處和挑戰,接下來就可以開始開發了,^?_?^

 

等等,微服務還沒有做邏輯分層,

微服務怎么做邏輯分層

目前我們的微服務里面有幾個服務,分別是訂單,商品,用戶,

如果客戶端向查看 “我的訂單” 這么一個介面;如果客戶端假定是 PC 端,就需要請求三次介面,分別對接訂單,商品,用戶三個服務,分別拿完三次呼叫資料,再將三次呼叫資料進行整合輸出展示,

要知道 PC 呼叫后端服務是走外網,這無疑大大增加了網路的開銷,而且讓 PC 端變成更為復雜,

假定在中間加多一個層為聚合服務層,即對網路開銷進行減少,因為微服務內部是通過內網進行資料傳輸,也讓 PC 端的業務變得比較簡單,

   

圖中的 “PC 聚合服務” 也是一個微服務,只不過它是屬于聚合服務中間層,我們將為微服務進行邏輯劃分,分為 2 個層:

 
①微服務基礎服務層

基礎服務一般屬于互聯網平臺基礎性的支撐服務,比方說,電商網站的基礎服務有訂單服務,商品服務,用戶服務等,

這些都屬于比較基礎和原子性,下沉一個公司的基礎設施的低層,向下承接存盤,向上提供業務能力,有些公司叫基礎服務,中間層服務,公共服務,Netflix 成為中間層服務,我們暫且統稱為基礎服務,

②微服務聚合服務層

已經有了基礎服務能提供業務能力,為什么還需要聚合服務,因為我們有不同的接入端,如 App 和 H5,PC 等等,它們看似呼叫大致相同的資料,但其實存在很多差異,

例如 PC 需要展示更多資訊,App 需要做資訊裁剪等等,一般低層服務都是比較通用的,基礎服務應該對外輸出相對統一的服務,在抽象上做得比較好,

但是對不同的外界 App 和 PC 的接入,我們需要作出不同的適配,這個時候需要有一個層去做出聚合裁剪的作業,

例如一個商品詳情在 PC 端展示和 App 端的展示,PC 可能會展示更多的資訊,而 App 則需要對資訊作出一些裁剪,

如果基礎服務直接開放介面給到 PC 和 App,那么基礎服務也需要去做成各種設配,這個很不利于基礎服務的抽象,

所以我們在基礎層之上加入聚合服務層,這個層可以針對 PC 和 App 做成適當的設配進行相應的裁剪,

那么我們的微服務中,又增加了一個服務,屬于聚合服務,

   

好了,接下來可以愉快的 Coding...

 

等等,貌似不對,如果是單塊應用加上事務應該沒問題,這里是分布式,恐怕得考慮加分布式事務,

分布式事務

我們來理一理創建訂單和扣件庫存模塊之間的關系:

 

可以發現,因為微服務的原因,我們把服務進行了分布式,隨著各個資料庫也隨著變成分布式每個資料庫不一定存在相同的物理機中,

那么這個時候單個資料庫的 ACID 已經不能適應這種情況,而在這種集群中想去保證集群的 ACID 幾乎很難達到,或者即使能達到那么效率和性能會大幅下降,最為關鍵的是再很難擴展新的磁區了,

這個時候如果再追求集群的 ACID 會導致我們的系統變得很差,這時我們就需要引入一個新的理論原則來適應這種集群的情況,就是 CAP,

CAP 定理

CAP 必須滿足以下的 3 個屬性:

  • 一致性(C):在分布式系統中的所有資料備份,在同一時刻是否同樣的值,(等同于所有節點訪問同一份最新的資料副本)

  • 可用性(A):在集群中一部分節點故障后,集群整體是否還能回應客戶端的讀寫請求,(對資料更新具備高可用性)

  • 磁區容錯性(P):以實際效果而言,磁區相當于對通信的時限要求,系統如果不能在時限內達成資料一致性,就意味著發生了磁區的情況,必須就當前操作在 C 和 A 之間做出選擇,

簡單的來說,在一個分布式系統中,最多能支持上面的兩種屬性,但顯然既然是分布式注定我們是必然要進行磁區,既然磁區,我們就無法百分百避免磁區的錯誤,因此,我們只能在一致性和可用性去作出選擇,

在分布式系統中,我們往往追求的是可用性,它的重要性比一致性要高,那么如何實作高可用,這里又有一個理論,就是 BASE 理論,它給 CAP 理論做了進一步的擴充,

BASE 理論

BASE 理論指出:

  • Basically Available(基本可用)

  • Soft state(軟狀態)

  • Eventually consistent(最終一致性)

BASE 理論是對 CAP 中的一致性和可用性進行一個權衡的結果,理論的核心思想就是:我們無法做到強一致,但每個應用都可以根據自身的業務特點,采用適當的方式來使系統達到最終一致性,

好了,說了一大頓理論,程式員們都等急了,趕快來看看分布式事務的解決方案有哪些,可以進行接下去的 Coding...

來吧,討論技術方案:

   

幾個方案拿出來了,因為我們不是專門來講解分布式事務的機制和原理,主要還是來做分布式事務的技術選型,

先排除掉我們應該不會選擇的方案,一個是 XA 兩階段提交,這個在很多傳統型公司會被使用,但不適合互聯網微服務的分布式系統,鎖定資源時間長,性能影響大,排除,

另一個是阿里的 GTS,并沒有開源,目前已經開源了 Fescar,不過目前尚缺少調研,可能在下個階段研究后會使用,目前先排除,

剩下的是 TCC 和 MQ 訊息事務兩種,

MQ 訊息事務:RocketMQ

先說說 MQ 的分布式事務,RocketMQ 在 4.3 版本已經正式宣布支持分布式事務,在選擇 RokcetMQ 做分布式事務請務必選擇 4.3 以上的版本,

事務訊息作為一種異步確保型事務, 將兩個事務分支通過 MQ 進行異步解耦,RocketMQ 事務訊息的設計流程同樣借鑒了兩階段提交理論,整體互動流程如下圖所示:

 

這個時候我們基本可以認為,只有 MQ 發送方自己的本地事務執行完畢,那么 MQ 的訂閱方必定百分百能夠接收到訊息,我們再對下單減庫存的步驟進行改造,

這里涉及到一個異步化的改造,我們理一下,如果是同步流程中的各個步驟:

  • 查看商品詳情(或購物車)

  • 計算商品價格和目前商品存在庫存(生成訂單詳情)

  • 商品扣庫存(呼叫商品庫存服務)

  • 訂單確認(生成有效訂單)

訂單創建完成后,發布一個事件“orderCreate” 到訊息佇列中,然后由 MQ 轉發給訂閱該訊息的服務,因為是基于訊息事務,我們可以認為訂閱該訊息的商品模塊是百分百能收到這個訊息的,

  image    

商品服務接受到 orderCreate 訊息后就執行扣減庫存的操作,注意??,這里可能會有一些不可抗的因素導致扣減庫存失敗,

無論成功或失敗,商品服務都將發送一個扣減庫存結果的訊息“stroeReduce”到訊息佇列中,訂單服務會訂閱扣減庫存的結果,

訂單服務收到訊息后有兩種可能:

  • 如果扣減庫存成功,將訂單狀態改為 “確認訂單” ,下單成功,

  • 如果扣減庫存失敗,將訂單狀態改為 “失效訂單” ,下單失敗,

   

這種模式將確認訂單的流程變成異步化,非常適合在高并發的使用,但是,切記了,這個需要前端用戶體驗的一些改變,要配合產品來涉及流程,

完美,使用 MQ 分布式事務就可以解決調一致性問題,

   

等等,MQ 訊息事務方案的風險了解一下,

上面使用 MQ 的方式確實是可以完成 A 和 B 操作,但是 A 和 B 并不是嚴格一致性,而是最終一致性,

我們犧牲掉嚴格一致性,換來性能的提升,這種很適合在大促高并發場景使用,

但是如果 B 一直執行不成功,那么一致性也會被破壞,后續應該考慮到更多的兜底方案,方案越細系統就將越復雜,

TCC 方案

TCC 是服務化的二階段變成模型,每個業務服務都必須實作 Try,Confirm,Calcel 三個方法,

這三個方式可以對應到 SQL 事務中 Lock,Commit,Rollback:

  • Try 階段:Try 只是一個初步的操作,進行初步的確認,它的主要職責是完成所有業務的檢查,預留業務資源,

  • Confirm 階段:Confirm 是在 Try 階段檢查執行完畢后,繼續執行的確認操作,必須滿足冪等性操作,如果 Confirm 中執行失敗,會有事務協調器觸發不斷的執行,直到滿足為止,

  • Cancel:是取消執行,在 Try 沒通過并釋放掉 Try 階段預留的資源,也必須滿足冪等性,跟 Confirm 一樣有可能被不斷執行,

接下來看看,我們的下單扣減庫存的流程怎么加入 TCC:

 

在 Try 的時候,會讓庫存服務預留 n 個庫存給這個訂單使用,讓訂單服務產生一個“未確認”訂單,同時產生這兩個預留的資源,

在 Confirm 的時候,會使用在 Try 預留的資源,在 TCC 事務機制中認為,如果在 Try 階段能正常預留的資源,那么在 Confirm 一定能完整的提交:

   

在 Try 的時候,有任務一方為執行失敗,則會執行 Cancel 的介面操作,將在 Try 階段預留的資源進行釋放,

完美,可以把我們的系統引入 TCC,^?_?^

 

等等,有同學提問:

  • 有同學可能會問了,如果在 Confirm 或 Cancel 中,有一方的操作失敗了,可能出現例外等情況該怎么解決,

    這個就涉及 TCC 的事務協調器了,事務協調器就 Confirm 或 Cancel 沒有得到回傳的時候,會啟用定時器不斷的進行 Confirm 或 Cancel 的重試,

    這個也就是我們強調,Confirm,Cancel 介面必須是冪等性的一個原因了,

  • 還有同學會問了,為什么事務協調器知道 Confirm,或 Cancel 沒有完成,

    這個就涉及到了 TCC 也做了一張本地訊息表,會記錄一次事務,包括主事務,子事務,事務的完成情況都會記錄在這種表中(當然未必是表,可能是 ZK,Redis 等等介質),然后啟用一個定時器去檢查這種表,

  • 還有同學會問,事務怎么傳遞,這個就涉及使用的 TCC 的框架了,一般來說用的都是隱式傳參的方式,

    在主事務創建的時候用隱式傳參呼叫子事務,子事務包含 Try,Confirm,Cancel 都會記錄到事務表里面,

這里推薦 TCC 的開源框架使用 mengyun 的 TCC,然后也可以其他的,無所謂,

完美,下單的流程開發完畢了,可以讓 QA 接入,^?_?^

 

等等,微服務的保護措施做了嗎?

熔斷限流隔離降級

微服務分布式依賴關系錯綜復雜,比方說前端的一個請求,這來到后端會被轉為為很多個請求,

這個時候后臺的服務出現不穩定或者延遲,如果沒有好的限流熔斷措施,可能會造成用戶體驗的下降,嚴重的時候會出現雪崩效應,把整個網站給搞垮,

如果像阿里巴巴在雙 11 等活動中,如果沒有一套好的限流熔斷措施,這是不可想象的,可能是根本無法支撐那么大的并發容量,

Netflix 在 2012 年前也沒有設計好的限流容錯,當時也是飽受著系統穩定性的困擾,好幾次網站因為沒有好的熔斷措施把網站搞垮,

在 2012 年 Netflix 啟動了彈性工程專案,其中有一個產品叫 Hystrix,這個產品主要用來解決微服務的可靠性,

有了這個系統之后,Netflix 在系統穩定性上上了一個大的臺階,在此之后就沒有出現過大規模的雪崩事故,

下面使用 Hystrix 例子來講解一下限流熔斷,

幾個概念:熔斷,隔離,限流,降級,這幾個概念是分布式容錯最重要的概念和模式,

①熔斷:如果說房子里面安裝了電路熔斷器,當你使用超大功率的電路時,有熔斷設備幫你保護不至于出問題的時候把問題擴大化,
②隔離:我們知道計算資源都是有限的,CPU,記憶體,佇列,執行緒池都是資源,
他們都是限定的資源數,如果不進行隔離,一個服務的呼叫可能要消耗很多的執行緒資源,把其他服務的資源都給占用了,那么可能出現因為一個服務的問題連帶效應造成其他服務不能進行訪問,
③限流:讓大流量的訪問沖進去我們的服務時,我們需要一定的限流措施,比方說我們規則一定時間內只允許一定的訪問數從我們的資源過,如果再大的話系統會出現問題,那么就需要限流保護,
④降級:如果說系統后臺無法提供足夠的支撐能力,那么需要一個降級能力,保護系統不會被進一步惡化,而且可以對用戶提供比較友好的柔性方案,例如告知用戶暫時無法訪問,請在一段時候后重試等等,

Hystrix

Hystrix 就把上面說的熔斷,隔離,限流,降級封裝在這么一個組件里面,下圖是 Hystrix 內部設計和呼叫流程:

 

大致的作業流如下:

  • 構建一個 HystrixCommand 物件,用于封裝請求,并在構造方法配置請求被執行需要的引數,

  • 執行命令,Hystrix 提供了幾種執行命令的方法,比較常用到的是 Synchrous 和 Asynchrous,

  • 判斷電路是否被打開,如果被打開,直接進入 Fallback 方法,

  • 判斷執行緒池/佇列/信號量是否已經滿,如果滿了,直接進入 Fallback 方法,

  • 執行 Run 方法,一般是 HystrixCommand.run(),進入實際的業務呼叫,執行超時或者執行失敗拋出未提前預計的例外時,直接進入 Fallback 方法,

  • 無論中間走到哪一步都會進行上報 Metrics,統計出熔斷器的監控指標,

  • Fallback 方法也分實作和備用的環節,

  • 最后是回傳請求回應,

完美,把 Hystrix 加入我們系統吧,這樣突然有洪峰流量也不至于我們的系統一下就沖垮,^?_?^

 

等等,Hystrix 的限流數值,錯誤數熔斷,超時熔斷,嘗試恢復比率這些需要我們配置的數值應該怎么定呢?

這個就取決你的系統壓測的指標和你部署的規模了,這里還涉及到一個容量設計的問題,一會我們將系統部署上線的時候再來詳細說道,

剛剛提到一個問題,就是這些限流數值,錯誤數熔斷這些數字,我們現在都寫在組態檔里面,

例如說寫在 Properties,YML 里面,當有一天突然需要把限流數下調(可能是系統遭受到什么壓力打擊),那我們只能把代碼拉下來,巴拉巴拉改了,

然后重新上傳打包,發布重啟,一個流程下來,不說個把小時吧,十來分鐘總少不了吧,

想辦法我們把這些配置項放到一個集中式配置中心,

集中式配置中心

自己寫配置中心還挺麻煩的,去菜市場逛逛吧,菜市場里面有,Spring Cloud Config,百度的 Disconf,阿里的 Diamond,還有攜程的 Apollo,

基本上他們的原理都差不多,配置中心可以簡單的理解為一個服務模塊,開發人員或運維人員可以通過界面對配置中心進行配置,

下面相關的微服務連接到配置中心上面就可以實時連接獲取到配置中心上面修改的引數,

更新的方式一般有兩種:

  • Pull 模式,服務定時去拉取配置中心的資料,

  • Push 模式,服務一直連接到配置中心上,一旦配置有變成,配置中心將把變更的引數推送到對應的微服務上,

   

Pull 和 Push 兩種模式各有優缺點:

  • Pull 一般使用定時器拉取,就算某一個網路抖動沒有 Pull 成功,在下一次定時器的時候,終將能保證獲取最新的配置,

  • Push 可以避免 Pull 定時器存在的延時,基本可以做到實時獲取資料,但也有問題就是網路抖動的時候可能會丟失更新,

攜程的 Apollo

   

攜程的 Apollo 比較有特色的是融合了 Pull 和 Push 兩種模式,把兩者的優點進行了結合,開發或運維人員在配置中心進行修改,配置中心服務將實時將修改推送 Push 到 Apollo 的客戶端,

但考慮到可能由于某些網路抖動沒有推送成功,客戶端還具備了定時向 Apollo 服務端拉取 Pull 資料的功能,

就算推送沒成功,但是只要一定時間周期,客戶端還是會主動去拉取同步資料,保證能把最終配置同步到服務中,這個也是 Apollo 在高可用方面上非常有特色的設計,

Apollp 在高可用上也做了保證,客戶端獲取到資料會把資料快取在記憶體,還會 Sync 到本地磁盤,

就算 Apollo 服務器掛掉了,就算客戶端服務重啟了,也可以從本地磁盤中拉取回來資料,繼續提供對外服務,從這點來看 Apollo 的配置中心在高可用上考慮還是比較周到的,

把配置中心配置上去后,我們就可以把 Hystrix 還有 MySQL 的用戶密碼,還有一些業務開關等等的配置引數放上去了,

完美,開發基本完工了,其實就幾個模塊,一個簡單的下單購物流程,當我們把系統交付給運維,運維喊道,日志呢,做微服務怎么可以沒有呼叫鏈日志呢?

呼叫鏈監控&日志

確實,微服務是一個分布式非常復雜的系統,如果沒有一套呼叫鏈監控,如果服務之間依賴出現問題就很難進行定位,

下圖是阿里在鷹眼系統給出的微服務之“熵”:

  image

目前各大主流互聯網公司中,阿里有非常出色的鷹眼系統,點評也有一套很出名的呼叫鏈監控系統 CAT,

呼叫鏈監控其實最早是 Google 提出來的,2010 年 Google 發表了一篇呼叫鏈的論文,論文以它內部的呼叫鏈系統 Dapper 命名,

這個論文中講解呼叫鏈在 Google 使用的經驗和原理,大致的原理如下圖:

  image

這里可以采用 ELK 的方式去記錄和展示呼叫鏈監控日志,當我們一條呼叫為一行記錄存盤下來,

   

通過 TraceId 和 ParentSpanId 就可以串聯起來為一個整體的鏈路,并可以從這個鏈路去分析錯誤或者呼叫延時和呼叫次數等等,

 

目前市面主流的呼叫鏈選型有 Zipkin,Pinpoint,Cat,Skywalking,他們之間各有一些偏重點,

值得一說的是 Skywalking 是國人出品的一款新的呼叫鏈工具,采用開源的基于位元組碼注入的呼叫鏈分析,接入段無代碼入侵,

而且開源支持多種插件,UI 在幾款工具來說比較功能比較強大,而且 UI 也比較賞心悅目,目前已經加入了 Apache 范訓器,

采用 Skywalking 作為呼叫鏈工具

為何會采用 Skywaling,在低層原理的實作,這幾款產品都差不多,但在實作和使用的細節相別還是很大:

  • 首先在實作方式上,Skywalking 基本對于代碼做到了無入侵,采用 Java 探針和位元組碼增強的方式,而在 Cat 還采用了代碼埋點,而 Zipkin 采用了攔截請求,Pinpoint 也是使用 Java 探針和位元組碼增強,

  • 其次在分析的顆粒度上,Skywaling 是方法級,而 Zipkin 是介面級,其他兩款也是方法級,

  • 在資料存盤上,Skywalking 可以采用日志體系中比較出名的 ES,其他幾款,Zipkin 也可以使用 ES,Pinpoint 使用 Hbase,Cat 使用 MySQL 或 HDFS,相對復雜,

    由于目前公司對 ES 熟悉的人才比較有保證,選擇熟悉存盤方案也是考慮技術選型的重點,

  • 還有就是性能影響,根據網上的一些性能報告,雖然未必百分百準備,但也具備參考價值,Skywalking 的探針對吞吐量的影響在 4 者中間是最效的,經過對 Skywalking 的一些壓測也大致證明,

完美,把微服務的包打好,上傳到服務器就可以運行了,^?_?^

 

等等,微服務包都打好了,剩下就是 Jar 包或 War 包一個一個上傳到服務器上,然后用個腳本 Start,在以前單塊應用還好,現在微服務幾十幾百個應用,請問,運營人員怕不怕?

聽說,Docker + Kubernetes 和微服務更配喔,

Docker + Kubernetes

就幾個服務,先不用容器化部署了...乍一看,沒完沒了,還有 CICD,灰度發布...容易編排...

下次再講吧,先把服務部署上去吧,

部署到生產,預估容量

該把服務部署上線了,一個服務上線肯定得評估下或者預估下訪問量有多少用戶,有多少訪問,這個涉及到該配置多少的機器資源,這應該怎么去估算呢,反正程式員在家里怎么算都算不出來,

評估訪問量

①問運營,如果是一個已經上線的產品,肯定存在已有的用戶數和訪問資料,就算存在偏差,也是可控的范圍,

②問產品,確定一個什么樣形態的產品,例如是拼團,例如是秒殺,各種處理方式都不同,

評估平均訪問量 QPS

一天 86400 秒,一般認為請求大部分發生在白天,就按照 40000 計算,日平均訪問量=日總訪問量/40000,

評估高峰 QPS

可以把之前每日的訪問曲線圖拉出來看看,峰值是根據業務不同而定的,例如,有些業務是白天早上 10 點的流量偏多,有些業務是晚上人家休閑類的流量偏多,

總之,根據業務去估算出日均的峰值,類似于電商類的服務,一般峰值是日均流量的 5 倍左右,

還有例如一些大促活動可能會更高,這個都要跟運營人員提前溝通好的,還有一些活動例如,秒殺,這個就不是靠預估出來,秒殺是另一種的考慮情況,采取的應對策略跟普通訂單是完全不同,

評估系統,單機極限 QPS

在上線之前需要跟測驗人員一起做壓力測驗,針對每個服務每臺機器去做,一般來說,會把一個服務一臺機器壓到極限,在逐步的進行優化,

思考一個問題,假定單臺機器最大的 QPS 是 1000,我們峰值是 5000,那需要用多少臺機器去抗?答案是大于等于 6 臺,最少的容錯不得少于 1 臺,

貌似一個非常簡單的微服務就差不多了,不過貌似還是差了很多,數一下:

  • 監控系統哪去了(基礎設施監控,系統監控,應用監控,業務監控)

  • 網關哪里去了

  • 統一的例外處理哪里去了

  • API 檔案哪里去了

  • 容器化哪里去了

  • 服務編排哪里去了

  • ...

QQ:137071249

共同學習QQ群:793305035

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/227053.html

標籤:Java

上一篇:Idea實作SpringBoot外置Tomcat的Web專案熱部署(包含靜態檔案)

下一篇:【Java Spring Cloud 實戰之路】- 使用Nacos和網關中心的創建

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more