我是和耳朵,很久沒有寫文了,今天趁着和你們聊聊分佈式
。html
前段時間一直沒有寫文是由於忙於面試~,沒錯😂離職了換了一家公司工做,新公司的系統都是分佈式的,入職一個月且寫了點東西上線以後我才勇於寫寫這個分佈式主題,否則怕本身沒有生產經驗誤人子弟了。面試
今天呢,主要是和你們聊一聊分佈式系統的相關概念及其常見分佈式組件和設計思想(不涉及計算機科學中分佈式系統的技術理論之類的東西),以前爲了準備此次的面試我是把市面上的不少分佈式組件都看了一遍,咱們公司所用的分佈式組件基本也沒出我瞭解的那個知識圈(公司用了Apollo
我沒提早了解,大E了),若是對分佈式相關技術棧不太瞭解,也能夠當我這篇徵文作你的掃盲貼,不過別忘了點贊👍算法
單體應用、集羣和微服務
,這個標題一出大家可能就知道我想說啥了,emm,就是架構的演進過程,不少人可能都看過相關知識,不過我爲了文章的完整性仍是打算簡單講一講。spring
首先是單體應用,在一個業務的起步階段,每每是用戶量不大且訪問請求少的階段,這個時候咱們通常只須要部署一個Web應用和一臺數據庫就能知足咱們的業務需求,且隨着SpringBoot
的流行,Web服務器能夠內置在應用裏面,可以更加方便快捷的部署應用。數據庫
同時由於項目規模小,業務流程簡單,維護和迭代起來也很方便,因此在當前這個階段單體應用是很是適合的。編程
可是隨着業務增加,單體應用不可避免的會出現瓶頸,我舉個例子:後端
假如咱們如今的單體Tomcat應用只能支撐QPS200
,隨着用戶量的增大併發隨之增大,慢慢超出了單臺應用能承受的極限,假如如今達到了QPS300
,那麼多出來的100請求就只能等着前面的請求處理完了以後才能請求進去,這樣帶來的後果就是響應時間變長,影響用戶體驗。設計模式
或者咱們應用中的業務比較複雜,單次請求響應時間比較長,這樣的話大量請求擠壓也會致使用戶的體驗不好,他們能明顯的感受到點擊某個按鈕以後隔了1~2s纔有結果返回。服務器
這個時候咱們就能夠引入集羣架構了,咱們能夠將單體應用同時部署兩份,並經過Nginx
進行反向代理和負載均衡進行流量分流,這樣每一個單體應用承受的QPS就是150了,就在能夠接受的範圍內,並且維護集羣應用和維護單機應用區別不大,只是在涉及到鎖的時候可能要藉助分佈式鎖來作。網絡
至此,每當訪問量增大系統到達瓶頸時咱們就能夠經過加機器這種方式進行橫向擴容,不斷的擴大應用的負載能力,可是若是這種方式天衣無縫,咱們也就不須要微服務的架構了~~~
從單體應用過渡到集羣架構,解決的實際上是性能的問題,單臺機器已經沒法知足人民日益增加的訪問需求,因此出現了集羣架構。
那麼從集羣過渡到微服務架構的更多緣由確定就不在性能了,這裏我說說我本身的見解與感悟:
首先既然項目已是集羣了證實業務量也不會很是小,這也就表明了代碼必定有一些規模了,這時候要面臨的第一個問題就是全部開發人員都會在這一個項目裏面修改代碼,極大狀況下是衝突不斷。
其次這麼多代碼聚合在一塊,當你進行一處功能修改的時候,若是須要進行全量回歸測試的話那簡直太要命了。
再者說,全部業務塊都在一個系統這會致使資源沒法最大化利用,好比一個電商系統確定是商品搜索/推薦系統爲最經常使用的系統,理所固然在資源方面他們應該佔有更多的機器資源,可是業務不進行拆分想進行橫向擴展只能將全部業務一塊兒擴展。
最後是有可能會引發雪崩效應,舉個例子你的系統中假若有一塊很是不重要的業務(好比簽到)代碼寫的有問題在生產環境中引起了OOM
,那麼它必然會連累到整個系統中的全部業務都變成不可用,由於不一樣業務之間並無物理隔離。
經過這幾條能夠知道過渡到微服務更多的考慮的已經不是性能瓶頸,而是人,是業務,也是應用系統最重要的高可用。
微服務是一種面向服務的軟件架構模式,自2014年Martin Fowler與James Lewis寫了一篇微服務架構
的文章以後(微服務這個概念在此以前就有),微服務就被大量的討論以及實踐到生產項目中:Netflix、Amazon這些商業公司都有微服務的成功案例,商業公司最會考慮的一件事就是成本,他們不會由於Martin Fowler是軟件工程的名人(巨佬)就對他提出的某個概念迅速披掛上馬,必定是通過了不少權衡以後,纔對他們的項目使用微服務的架構模式。
上一節中我已經簡要說了說集羣架構的缺點,微服務則是解決了那些缺點才變得如此受歡迎,微服務的相關定義,這裏我引用一段Martin Fowler原文的配圖和翻譯來講明:
簡而言之,微服務架構風格,就像是把一個單獨的應用程序開發爲一套小服務,每一個小服務運行在本身的進程中,並使用輕量級機制通訊,一般是 HTTP API。
這些服務圍繞業務能力來構建,並經過徹底自動化部署機制來獨立部署。這些服務使用不一樣的編程語言書寫,以及不一樣數據存儲技術,並保持最低限度的集中式管理。
若是非要我用本身的語言來理解一下就是:將一個大型系統分爲一個個的小型服務系統,共同支撐大型系統,每一個小服務系統均可以獨立開發/測試/迭代/部署/擴容。
將大系統拆分爲小服務以後既擁有了小服務的相關優勢(利於團隊協做/測試/迭代),又能在面對大流量時進行集羣擴容,能夠說是集二者優勢於一身,可能這就是所謂的」天下大勢,合久必分,分久必合。」
我新入職的這家公司也是在今年初全面轉入微服務架構,咱們部門中全部的業務都已經拆成了微服務在跑,微服務拆分這事算是見仁見智把,要根據具體業務具體分析,咱們的拆分過程當中感受比較好的一點是:有一些在將來一兩年內將要中止運營的業務也單獨拆出來放在一個服務裏跑。
其實微服務的概念不難理解,但真正動手起來作的話遇到的則通常不是微服務的問題而是分佈式問題,有不少人常常把這兩個概念搞混淆,認爲他倆說的是一個東西,實際上是兩個東西,咱們作出來的東西每每是涵蓋了這兩個概念。
微服務是指的一種面向服務的軟件架構方式,而分佈式則是一種爲了某個共同目標而協調多臺計算機節點進行工做的軟件系統。
在上一節的講解中,有一句話一直出現:隨着業務量/訪問量增大
,這個日益增加的訪問量/業務量/數據量是咱們使用微服務和分佈式系統的主要緣由:
業務的增長咱們經過業務拆分來解決其帶來的問題,這能夠算是微服務的範疇。
不一樣的服務部署在不一樣的機器上,可是對於用戶來講卻和訪問一個系統沒什麼區別,依靠網絡將多個計算機節點組成一個統一的總體,這能夠算是分佈式系統的範疇。
因爲數據量的不斷增長咱們能夠經過增長機器節點來分攤數據量,這算是分佈式系統中分佈式存儲的範疇。好比咱們的Redis數據一臺機器已經存不下了,就要考慮使用RedisCluster
將數據分散到多臺機器上面,其餘例如Kafaka、ES都是分佈式架構的中間件均可以進行分佈式存儲。
若是應用中某些計算量比較大的任務使用一臺機器執行會耗時過長,這時咱們能夠拆分任務給多臺節點同時執行,這算是分佈式系統中分佈式計算的範疇。最近我在接手項目的時候就遇到了相似的問題,原任務單機執行時間太久,讓我改成全部在線節點同時執行,共同分攤任務,而且要能動態根據在線節點數量進行任務拆分。
經過上面四點的說明,我想你們對微服務和分佈式應該有個簡單的區分了把,再次總結一下:
微服務是指的一種面向服務的軟件架構方式,而分佈式則是一種爲了某個共同目標而協調多臺計算機節點進行工做的軟件系統。
那爲何微服務和分佈式系統老放在一塊討論,致使不少人對他倆的定義模糊不清呢,由於每每咱們要實現一個微服務架構的應用時,咱們就在實現一個分佈式系統。
若是你不明白我這句話,請好好想一想使用微服務架構組成的應用是否是也同時符合分佈式的定義。
Tips: 分佈式計算/存儲也是一門計算機科學中的研究方向,因此它們其實仍是能夠挺深奧的一堆東西。
看了上一節你們應該已經明白了微服務和分佈式的關係了吧,我這篇文章的重點實際上是分佈式,由於微服務只是一個面向服務的軟件架構概念,讓我理解起來它的主要做用就是提出了服務拆分、獨立開發部署這些概念,emm~概念,可是一個分佈式系統卻有不少各類各樣的實際問題須要解決,因此個人重點是在分佈式。
先來講說分佈式的CAP原則
,但凡對分佈式有點了解的,都不能不知道這個CAP,先來看看它的定義:
CAP原則又稱CAP定理,指的是在一個分佈式系統中,一致性(Consistency)、可用性(Availability)、分區容錯性(Partition tolerance)。
CAP 原則指的是,這三個要素最多隻能同時實現兩點,不可能三者兼顧。
分區容錯性: 是指在分佈式系統中部署在不一樣地點的機器可能出現網絡鏈接失敗的狀況,這就像個人推薦服務會請求商品服務裏面的數據,但有可能發生了網絡波動致使我推薦服務發起的請求網絡鏈接超時。
可用性: 是指用戶的請求必須返回結果,要作到這個程度就須要咱們在不一樣機房部署應用避免出現某些地方機房遭遇了事故致使服務宕機的狀況。
一致性: 是指數據被修改後,以後讀到的數據必定是最新的數據。
上面的定義已經說了,CAP只能最多同時實現兩點,由於咱們是分佈式系統,因此多臺服務節點是沒法避免的,也就是分區容錯性咱們必需要保證,因此咱們只能保證明現CP或者AP。
爲何不能同時實現CAP呢?緣由很簡單,由於可用性這個要求須要每一個節點的數據都要有幾個冗餘的副本,用來保證有一個節點掛掉以後副本能頂上去。然而副本節點和主機節點之間由於有網絡通訊因此每每這個數據的傳輸是有延遲的,這也就不能保證主機的數據被修改後副本能當即收到修改,而是通過一頓延遲後才能收到主機修改的數據。
爲了方便你們理解,我再舉一個例子來講明一下,好比說分佈式中間件Redis
:
它在單機的狀況下能夠保證CP,由於只有一臺Redis節點因此數據被修改後以後的請求所訪問到的數據都是最新的。
它在集羣的狀況下能夠保證AP,AP是強調可用性,集羣架構下若是主節點掛掉以後,副本節點還能夠接着響應請求。
既然CAP沒法同時保證,那咱們就要退而求其次,這裏將會引出一個新的理論:BASE
。
BASE是Basically Available(基本可用)、Soft state(軟狀態)和Eventually consistent(最終一致性)的簡寫。
BASE是對CAP中一致性和可用性權衡的結果,契合性思想是即便沒法作到強一致性,但每一個應用均可以根據自身的業務特色,採用適當的方式來使得系統達到最終一致性。
基本可用: 是指某些狀況下容許部分可用性的丟失,好比咱們的雙十一大促,可能會因爲下單量激增致使你下不了單,這就屬於下單服務不可用了,可是並不會持久過久,而是短暫的。
軟狀態: 是指容許副本同步過程當中出現延遲而致使副本不一致的狀況。
最終一致性: 是指系統的全部系統數據副本能夠通過一段延遲後最終達到數據的一致性,不須要保證明時的數據一致。
咱們既想要可用性也想要一致性,然而兩者沒法兼得,因此BASE理論就提出了這樣一種兼顧的思想,代價是強可用和強一致的損失。
現實中的不少系統中都是BASE理論這種思想,達到系統的一個基本可用和最終一致。
這節咱們來聊聊咱們分佈式系統的常見的各類組件以及相關特性,你們接觸過度布式開發的話就會發現分佈式開發中有一大籮筐的名詞等着你:註冊中心、配置中心、網關、熔斷、遠程調用等等。
初來乍到,不要被這些名詞嚇住,別人能會的你也能,這一節我會自頂向下的講解一下分佈式開發的基本組成,你能夠先忘記這些名詞,慢慢看個人講解,看完這一章後我相信對這些都不會再迷茫。
前面我已經說過,分佈式系統是多個節點組成一個總體,那不一樣節點的IP確定不一樣,想要感受像是一個總體,就得有一個部件在全部節點的最前面承擔一個請求分發的做用,這個東西就叫:網關
。
通常的網關有兩層,第一層是服務器的Nginx+LVS這種,第二層是分佈式應用的網關,我這裏說的是分佈式應用的網關。
這個網關的做用有點像Nginx,能夠幫你作反向代理幫你作負載均衡,可是比它更強大,分佈式應用的全部請求第一站就是應用的網關層,在這裏能夠校驗請求是否合法,阻擋網絡攻擊,也能夠進行動態的請求分發。
請求被網關轉發到對應的服務以後,就由對應的服務來處理了,這個時候問題又來了,咱們同一個服務可能部署了三四臺節點,這個時候我該往哪一個服務器轉發呢?
咱們要想轉發首先要知道各個節點的IP和端口號,這個信息咱們不能寫死,寫死的話不利於動態加機器,因此這個時候咱們須要用到一箇中間價:註冊中心
。
咱們全部的服務都會註冊到註冊中心上面去,固然這個註冊中心也要是一個集羣,這樣能夠保證高可用。
舉個例子:我有一個商品服務給它起了個名字叫作goods-service,我給他起了三臺服務器,這三臺服務器都會註冊到註冊中心上去,而後咱們就能夠在註冊中心上看到有一個叫goods-service的東西下面又三臺節點,每臺節點的IP端口號都會在註冊中心上面保存。
這時候咱們網關來轉發的時候是經過goods-service這個名稱去註冊中心拿到三臺節點的地址,而後根據不一樣的策略最終決定咱們是要將請求發到哪一臺節點。
請求發送到服某某服務的這個過程,咱們能夠稱做爲服務通訊
,這個通訊方式通常有兩種:HTTP和RPC,這個其實我以爲沒啥好說的,主要就是通訊的協議不同,協議的不一樣也形成了效率的不一樣。
上面說了三個比較重要的組件,還有兩個比較重要的聽我娓娓道來。
第一個是配置中心
,這個實際上是屬於用不用都行的東西,可是用起來仍是更方便的,它的主要做用是將分佈式應用的配置都放在一個地方管理,咱們須要更改的時候就可讓全部引用這些配置的應用感知到並在運行的過程當中動態加載到這些被修改的配置。
好比咱們有六個微服務應用,咱們能夠統一的把配置都放在配置中心中間件上,這個數據通常是放在配置中心所連的數據庫裏,因此等於把咱們全部項目的配置抽出來都放在數據庫了,一旦線上運行有什麼須要動態修改的配置,咱們均可以直接在中間件上修改而後全部應用都會收到修改的通知,就會對修改的配置進行從新加載。
它對於某些公共的配置也很方便,好比六個微服務用的是一個Redis集羣,咱們只須要配置一份就夠了,並且集羣配置有變化咱們也只須要修改一次,六個微服務應用都能感知到。
第二個是熔斷器
,所謂熔斷器,就是爲了保護應用而設計的中間件,好比淘寶雙十一下單服務器頂不住的時候就會給你提示一個哎呀,服務器太火爆了,請稍後再試呢」 這種提示,這個東西就是爲了保護淘寶服務不被沖垮而使用的一種限流措施,這種措施叫作服務降級。
使用熔斷器還有一些場景,好比下單經歷了商品服務和下單服務和庫存服務,走到最後一步時庫存服務崩掉了,這個時候下單服務這裏會報錯,進而引發羊羣效應,全部和崩掉的節點有通訊的節點都會發生錯誤,這個時候就須要熔斷器出場了,發現那個服務不會響應以後會給一個提示,防止羊羣效應的產生。
這兩個概念表現方式很像,可是不要被表象迷惑,他倆很主要的一個區別是引發的內因不同,你們有機會寫一次相關的代碼就能明白了。
以上介紹的這些都是分佈式開發中比較基礎的中間件,還有其餘可選的中間件鏈路追蹤我會在下一節提一下,在這就很少說了。
上一節大概講了五個分佈式相關的組件,通常也就這五種:微服務網關、註冊中心、配置中心、服務通訊組件、熔斷組件。
這一節要給你們說說相關的實現,給你們認認臉熟,由於咱們搞Java應用開發的通常都是用Spring全家桶的,在微服務開發這塊Spring推出了它的SpringCloud全家桶用來作微服務分佈式開發。
通過這幾年的發展其實大體能夠分爲兩套開發套件:SpringCloud開發套件和SpringCloudAlibaba開發套件,這個只是我我的的分法,還有一些其餘家的我也會提一下。
咱們先來看看SpringCloud這一套,這一套相關的組件一開始基本都是Netflix
公司開發的,這是一個作流媒體應用的,能夠理解爲國外的愛奇藝。
這張導圖右邊的是三個註冊中心中間件,Eureka
就是Netflix公司開發的,Zookeeper
這個功能比較強不是簡簡單單隻作註冊中心,它還能夠作註冊中心和分佈式鎖,Consul
則是一個Go語言開發的註冊中心中間件(也能夠用做配置中心),這幾個裏面Eureka是這兩年用的比較多的,更早以前國內可能Zookeeper用的更多。
左邊第一個SpringCloudGateway
則是網關中間件,由Spring開發,以前Netflix還有一個Zuul,也是用來作網關中間件的。
Feign/OpenFeign/Rabbon
這三個我放在一塊說,Feign和OpenFeign實際上是一個東西,OpenFeign是在Feign停更以後在其基礎上開發的,都是用來作服務間通訊的,他們使用HTTP作通訊協議,其實就是Spring中的RestTemplate,而Rabbon是一個作服務轉發策略的中間件,前文咱們提到網關進行服務轉發時能夠根據必定的策略好比:輪詢、隨機、權重這些策略,這塊其實就是Rabbon在起效,咱們用Eureka的時候如今都是自帶Rabbon不須要額外去引入相關JAR包了,畢竟都是Netflix一家的東西。
SpringCloudConfig
是Spring開發的配置中心中間件,功能比起其餘的後起之秀好比攜程的Apollo,阿里的Nacos稍弱,因此不推薦用。
Hystrix
也是Netflix公司開發的中間件,它的做用就是熔斷器,是一款很是經典的熔斷器中間件,這些中間件裏面它是相對來講最複雜的。
Sleuth
是一款鏈路追蹤中間件,能夠記錄你的請求會通過哪些鏈路,Zipkin
則能夠以可視化的形式將其表現出來。
上面這一套東西在我如今的公司裏面除了配置中心用的Apollo以外其餘都用到了,算是比較流行的套件了。
不一樣於上面的基本都是由Netflix開發的套件,下面我要介紹的套件是SpringCloudAlibaba套件,由於是由Alibaba開發的因此通常都這樣稱呼。
上面這幅圖相比上一張就要簡單的多了。
Nacos
是一個多功能中間件,同時能夠作註冊中心和配置中心,這個組件我本身也用過感受仍是蠻好用的,並且自帶一套比較美觀的可視化界面。
Duubo
這個可能你們比較熟悉,原來是由阿里開發後來捐給Apache,如今是Apache的頂級項目之一,它是一個服務通訊的組件,使用RPC通訊方式。
Sentinel
阿里開發的熔斷器,名字翻譯過來就是哨兵能夠說是很貼切了,而且擁有鏈路追蹤的功能,還配有配套的可視化界面,能夠說是一我的幹了Hystrix+Sleuth+Zipkin的活。
像阿里這套中間件我是比較推薦的,由於第一套Netflix公司基本都已經宣佈中止更新了,好比Feign不更新以後Spring又接手進行二次開發搞了一個OpenFeign。
這裏在提一下Apollo,攜程開發的配置中心中間件,如今也有不少公司在用,咱們公司也在用我的用起來感受仍是能夠的,很方便上手也簡單。
其實別看這裏羅列了這麼多的中間件,每中學一種,剩下的看看文檔也就上手了,大同小異吧,開源界的東西就是喜歡弄的簡單易上手,這對你們來講也是減小學習成本。
框架學的越多用的越多,你越會發現其實大部分都是大同小異,越能明白學好Java基礎的做用,越能知道設計模式、算法纔是一個軟件工程師必備的技能。
下個月我應該會把這些中間件也逐一寫文章寫個入門夠用的程度吧,你們一塊兒加油🎉。
我是和耳朵,歡迎關注個人公衆號,加入後端相關交流羣: