分布式與微服務


分布式

CAP

C:consistency 一致性 分布式系統能夠同時訪問同一份數據副本

A:availability 可用性 非故障節點能夠在合理時間內獲得合理的結果

P:Partition Tolerance 分區容錯性 分布式系統當發生網絡分區時,服務仍然可用

網絡分區:分布式網絡中,由於某些節點故障,導致系統分成了幾個區域。比如調用鏈A->B->C,其中B節點故障,那么A,B分成了兩個分區。

而是在P為條件下,只能實現A或者C。也就是說,在發生網絡分區后,我們只能保證一致性或者可用性。

當沒有發生網絡分區時,也就是沒有P為條件,那么自然可以同時滿足A和C。

zookeeper:保證CP,zookeeper有leader節點,寫操作只能由leader來做,Follower只能處理讀操作,這樣就保證數據的一致性。

Eureka:保證AP,Eureka各個服務器節點都是平等的,只要有至少一個節點,就能夠保證可用。

Nacos:保證AP和CP,默認支持AP,通過命令進行切換為CP。

BASE理論

  • 基本可用(Basically Available)

    當系統發生不可預知的故障時,允許損失部分可用性。

    • 響應時間的損失:原先0.5s就能返回的結果,允許2s內返回
    • 系統功能的損失:可以損失非核心功能,而保證核心功能的可用
  • 軟狀態(Soft State)

    允許存在中間狀態,允許在多個節點的數據副本存在時延

  • 最終一致性(Eventually Consistent)

    在一個時間期限后,要保證數據的最終一致性

分布式ID

對於單個數據庫我們使用id自增就能保證,id不重復。

對於兩個數據庫,我們分別設置起始值和步長就能避免id重復,但是這時在添加一個數據庫,則要重新修改初始值和步長。

號段模式:我們可以先從數據庫中取出一段數據,比如id為100到200,當需要使用時,在本地直接提取使用,使用完這100個id后,再從數據庫中取200到300的id。

redis:通過redis,在redis中使用incr自增,也能夠保證id的不重復。

雪花算法:對分布式id的bit進行分配,比如64bit的一個id,從左到右,第一位符號位,接下來41bit為時間戳,接下來10bit為工作機器id,接下來12bit為序列號。這樣就能夠保證id的不重復。

限流算法

固定窗口計數機算法

規定一分鍾之內只能有100個請求,如果多了則丟棄該請求。該方法無法防止突增的請求,比如前30秒只有1個請求,后30秒突然進來99個請求,無法保證限流的速率。

滑動窗口計數機算法

將一分鍾划分成60個格子,大小為30的窗口不斷移動,每秒的請求放到格子中,如果窗口中的請求超過閾值,就不再處理其他請求。

漏桶算法

輸出的水流是一定的,這樣就能保證輸出速率穩定。把請求比作水,當請求來時,則將水輸入到水桶上方,即使上方的水是突然激增的,那輸出也仍然是穩定的。如果木桶大小固定,上方水滿了,則水將溢出,也就是說請求丟棄。

缺點是,我們總是以固定的速率流出,我們希望當請求少時,固定速率流出自然沒問題,但是當請求到峰值,我們希望流出速率大一些。

令牌桶算法

仍然是一個固定大小的桶,我們以固定速率生產令牌,當請求來時,對於大的請求,消耗多點的令牌,小請求就少點令牌。如果桶內令牌沒有了,則丟棄請求。這個算法就能解決動態去做“流出速率”,峰值時流出速度快,平時呢流出速率平穩。

RPC

做為遠程調用框架,目的是希望調用遠程方法就像本地方法一樣簡單。

客戶端:通過簡單注解或者使用類調用遠程方法

客戶端代理類:通過動態代理,讓客戶端執行的方法最終讓代理類來執行。代理類拿到服務名/方法名,參數等信息封裝到request中,然后通過網絡調用發送給服務端

網絡調用:最簡單的可以用socket,當然netty更流行,編寫Netty的客戶端與服務端

服務端:Netty中拿到request,知道了方法名,可以通過反射創建實現了該方法的類,然后調用之,得到結果后,再通過Netty服務端傳送給客戶端

注冊中心:我們可以用zk,創建節點,節點為服務名,節點下數據為機器ip地址。服務端啟動時,首先將自己能夠提供的服務注冊到zk上。客戶端根據服務名從zk中找到具體的ip地址,然后根據ip地址發送訪問。

網關

微服務下多個服務,對於權限管理,流量控制,日志,監控等和業務無關的東西提取出來,統一管理,因此就有網關。

網關可以做:鑒權,限流,請求路由,日志,監控。

微服務

服務注冊與發現:Eureka,nacos

微服務有很多消費者,提供者,我們不希望將他們之間的調用寫死,因為針對某個服務,可能有多個機器去運行他,那么我們希望有一個人能夠統一管理,那么注冊中心可以解決我們的問題。服務提供者將自己的服務注冊到注冊中心,消費者只需根據服務名從注冊中心拿到提供者地址。並且對於網關,負載均衡,熔斷降級,消息隊列等等組件,他們都希望自己能夠獲得注冊在注冊中心的某些信息,從而進行操作。

比如監控功能,就需要拿到注冊中心的所有提供者消費者信息,來判斷他們的健康情況。

總之,注冊中心統一對服務的管理,當我們需要使用或者查看這些服務狀態時,只需訪問注冊中心即可。

負載均衡:Ribbon

nacos自己集成了Ribbon,要使用負載均衡,首先我們要講restTemplate通過@Bean注解注冊到spring中,然后或者使用注解,或者通過代碼指定負載均衡策略即可,然后調用restTemplate.getForObject或者restTemplate.postForObject即可調用另一個服務的方法。

Openfeign:有人覺得直接寫restTemplate.postForObject,這樣不美觀,我就是想調用另一個服務就跟調用本地方法一樣,那么這個Openfeign就可以幫助我們。我們寫一個接口,接口中方法指明另一個服務的接口,然后我們在controller調用的時候,加個注解,直接調用接口的方法,看起來多像在本地調用方法啊!

熔斷和降級:Hystrix,sentinel

當服務調用鏈路A->B->C,其中服務C發生故障,導致B有大量請求堆積,最終耗盡B的所有資源,B掛掉,然后A也堆積大量請求,A也掛掉,這就是服務雪崩。

為了防止服務雪崩,我們需要熔斷器,當某個服務故障時,切斷調用鏈路,告知上一個服務,當前服務已經故障了。

服務降級,比如某服務訪問量過大,我們一次處理不了那么多請求,我們可以做服務降級。比如突然有1000訂單,我們一下子處理不了,那么我們可以讓一部分請求走降級,返回稍后重試的提示信息。

sentinel不僅僅有熔斷降級等功能,他還提供了多種其他功能,如限流,負載保護,實時監控,調用鏈路等。

網關:gateway,zuul

網關可以做路由映射,過濾器。

鏈路跟蹤:zipkin

每個服務是一個圓點,服務調用之間有連線,做出來的效果,真好看。。。😄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM