close

點擊關注公眾號,實用技術文章及時了解


前言什麼是雪崩問題?

微服務之間相互調用,因為調用鏈中的一個服務故障,引起整個鏈路都無法訪問的情況。

解決雪崩問題的常見方式有四種:
超時處理:設定超時時間,請求超過一定時間沒有響應就返回錯誤信息,不會無休止等待
艙壁模式:限定每個業務能使用的線程數,避免耗盡整個tomcat的資源,因此也叫線程隔離。
熔斷降級:由斷路器統計業務執行的異常比例,如果超出閾值則會熔斷該業務,攔截訪問該業務的一切請求。
流量控制:限制業務訪問的QPS,避免服務因流量的突增而故障。

前三種是一種已經出現後的應對措施可以避免因服務故障引起的雪崩問題;後一種是一個預防方案,可以避免因瞬間高並發流量而導致服務故障

與Hystrix對比

簇點鏈路:就是項目內的調用鏈路,鏈路中被監控的每個接口就是一個資源。默認情況下sentinel會監控SpringMVC的每一個端點(Endpoint),因此SpringMVC的每一個端點(Endpoint)就是調用鏈路中的一個資源。

流控、熔斷等都是針對簇點鏈路中的資源來設置的,因此我們可以點擊對應資源後面的按鈕來設置規則:

Sentinel概述

Sentinel (分布式系統的流量防衛兵) 是阿里開源的一套用於服務容錯的綜合性解決方案。它以流量為切入點, 從流量控制、熔斷降級、系統負載保護等多個維度來保護服務的穩定性。

Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景, 例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峰填谷、集群流量控制、實時熔斷下游不可用應用等。

Sentinel核心分為兩個部分:
核心庫(Java 客戶端):能夠運行於所有 Java 運行時環境,同時對Dubbo /Spring Cloud 等框架也有較好的支持。
控制台(Dashboard):基於 Spring Boot 開發,打包後可以直接運行。
Sentinel的使用分為兩部分:
entinel-dashboard:與hystrix-dashboard類似,但是它更為強大一些。除了與hystrix-dashboard一樣提供實時監控之外,還提供了流控規則、熔斷規則的在線維護等功能。
客戶端整合:每個微服務客戶端都需要整合sentinel的客戶端封裝與配置,才能將監控信息上報給dashboard展示以及實時的更改限流或熔斷規則等。
安裝Sentinel服務

Sentinel 提供一個輕量級的控制台, 它提供機器發現、單機資源實時監控以及規則管理等功能,其控制台安裝步驟如下:

第一步:打開sentinel下載網址

https://github.com/alibaba/Sentinel/releases

第二步:下載Jar包(可以存儲到一個sentinel目錄)

第三步:在sentinel對應目錄,打開命令行(cmd),啟動運行sentinel

java-Dserver.port=8180-Dcsp.sentinel.dashboard.server=localhost:8180-Dproject.name=sentinel-dashboard-jarsentinel-dashboard-1.8.1.jar

檢測啟動過程,如圖所示:

訪問Sentinal服務

第一步:假如Sentinal啟動ok,通過瀏覽器進行訪問測試,登陸sentinel,默認用戶和密碼都是sentinel,如圖所示:

sentinel-dashboard不像Nacos的服務端那樣提供了外置的配置文件,比較容易修改參數。不過不要緊,由於sentinel-dashboard是一個標準的spring boot應用,所以如果要自定義端口號等內容的話,可以通過在啟動命令中增加參數來調整,比如:-Dserver.port=8888。

默認情況下,sentinel-dashboard以8080端口啟。

對於用戶登錄的相關配置可以在啟動命令中增加下面的參數來進行配置:

-Dsentinel.dashboard.auth.username=sentinel: 用於指定控制台的登錄用戶名為 sentinel;
-Dsentinel.dashboard.auth.password=123456: 用於指定控制台的登錄密碼為 123456;
如果省略這兩個參數,默認用戶和密碼均為 sentinel
-Dserver.servlet.session.timeout=7200: 用於指定 Spring Boot 服務端 session 的過期時間,如 7200 表示 7200 秒;60m 表示 60 分鐘,默認為 30 分鐘;
Sentinel快速入門

第一步:Sentinel 應用於服務提供方(provider),在服務提供方添加依賴如下:

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>

第二步:打開服務提供方配置文件xxx.yml,添加sentinel配置,代碼如下:

spring:cloud:sentinel:transport:dashboard:localhost:8180#指定sentinel控制台地址。

第三步:創建一個用於演示限流操作的Controller對象,例如:

importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/provider")publicclassProviderSentinelController{@GetMapping("/sentinel01")publicStringdoSentinel01(){return"sentinel01test...";}}

啟動sca-provider服務,然後對指定服務進行訪問,如圖所示:

Sentinel限流入門實踐

我們設置一下指定接口的流控(流量控制),QPS(每秒請求次數)單機閾值為1,代表每秒請求不能超出1次,要不然就做限流處理,處理方式直接調用失敗。

第一步:選擇要限流的鏈路,如圖所示:

第二步:設置限流策略,如圖所示:

第三步:反覆刷新訪問消費端端服務,檢測是否有限流信息輸出,如圖所示:

Sentinel流控規則分析閾值類型
QPS(Queries Per Second) :當調用相關url對應的資源時,QPS達到單機閾值時,就會限流。
線程數:當調用相關url對應的資源時,線程數達到單機閾值時,就會限流。
設置限流模式

Sentinel的流控模式代表的流控的方式,默認【直接】,還有關聯,鏈路。

直接模式

Sentinel默認的流控處理就是【直接->快速失敗】。

關聯模式

當關聯的資源達到指定閾值,就限流自己。

例如設置了關聯資源為ur2時,假如關聯資源url2的QPS閥值超過1時,就限流url1接口(是不是感覺很霸道,關聯資源達到閥值,是本資源接口被限流了)。

這種關聯模式有什麼應用場景呢?我們舉個例子,訂單服務中會有2個重要的接口,一個是讀取訂單信息接口,一個是寫入訂單信息接口。在高並發業務場景中,兩個接口都會占用資源,如果讀取接口訪問過大,就會影響寫入接口的性能。

業務中如果我們希望寫入訂單比較重要,要優先考慮寫入訂單接口。那就可以利用關聯模式;在關聯資源上面設置寫入接口,資源名設置讀取接口就行了;這樣就起到了優先寫入,一旦寫入請求多,就限制讀的請求。例如

第一步:在ProviderSentinelController中添加一個方法,例如:

@GetMapping("/sentinel02")publicStringdoSentinel02(){return"sentinel02test...";}

第二步:在sentinel中做限流設計,

例如

第三步:打開兩個測試窗口,對/provider/sentinel02進行訪問,檢查/provider/sentinel01的狀態,例如:

鏈路模式

鏈路模式只記錄指定鏈路入口的流量。也就是當多個服務對指定資源調用時,假如流量超出了指定閾值,則進行限流。

被調用的方法用@SentinelResource進行註解,然後分別用不同業務方法對此業務進行調用,假如A業務設置了鏈路模式的限流,在B業務中是不受影響的。現在對鏈路模式做一個實踐,例如:

第一步:在指定service包創建一個ResourceService類,代碼如下:

@ServicepublicclassResourceService{@SentinelResource("doGetResource")publicStringdoGetResource(){return"doGetResource";}}

第二步:在ProviderSentinelController中添加一個方法,例如:

@AutowiredprivateResourceServiceresourceService;@GetMapping("/sentinel03")publicStringdoSentinel03()throwsInterruptedException{resourceService.doGetResource();return"sentinel03test";}

第三步:在sentinel中配置限流規則,例如:

設置鏈路流控規則後,再頻繁對限流鏈路進行訪問,檢測是否會出現500異常,例如

說明,流控模式為鏈路模式時,假如是sentinel 1.7.2以後版本,Sentinel Web過濾器默認會聚合所有URL的入口為sentinel_spring_web_context,因此單獨對指定鏈路限流會不生效,需要在springboot配置文件application.yml中,添加如下語句來關閉URL PATH聚合,例如:

sentinel:web-context-unify:false

當設置了這個配置後,啟動服務,就可以對指定的特定鏈路進行限流了。

還有,當我們也可以基於@SentinelResource註解描述的方法進行限流後的異常進行自定義處理,其步驟如下:

第一步:定義blockHandlerClass,例如:

packagecom.jt.provider.service;importcom.alibaba.csp.sentinel.slots.block.BlockException;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Component;@Slf4j@ComponentpublicclassResourceBlockHandler{/***限流後的異常處理方法,應用於@SentinelResource註解中,*此方法在編寫時有如下幾個要求:*1)方法修飾符為public*2)必須為static方法*3)返回值類型與@SentinelResource註解描述的方法相同*4)參數類型為BlockException*5)方法名自己定義*@paramex*@return*/publicstaticStringdoHandle(BlockExceptionex){log.error("blockexception{}",ex.getMessage());return"訪問太頻繁了,稍等片刻再訪問";}}

第二步:修改@SentinelResource註解中的屬性定義,例如:

@SentinelResource(value="doGetResource",blockHandlerClass=ResourceBlockHandler.class,blockHandler="doHandle")publicStringdoGetResource(){return"dogetresource";}

第三步:在controller方法中,調用@Sentinel註解描述的方法,例如:

/***演示鏈路限流*@return*/@GetMapping("/sentinel03")publicStringdoSentinel03(){returnresourceService.doGetResource();//return"sentinel03test";}Sentinel 熔斷降級

除了流量控制以外,對調用鏈路中不穩定的資源進行熔斷降級也是保障高可用的重要措施之一。由於調用關係的複雜性,如果調用鏈路中的某個資源不穩定,最終會導致請求發生堆積。

Sentinel 熔斷降級會在調用鏈路中某個資源出現不穩定狀態時(例如調用超時或異常比例升高),對這個資源的調用進行限制,讓請求快速失敗,避免影響到其它的資源而導致級聯錯誤。當資源被降級後,在接下來的降級時間窗口之內,對該資源的調用都自動熔斷(默認行為是拋出DegradeException)。

準備工作

在ProviderController 類中添加doSentinel05方法,基於此方法演示慢調用過程下的限流,代碼如下:

//AtomicLong類支持線程安全的自增自減操作privateAtomicLongatomicLong=newAtomicLong(1);@GetMapping("/sentinel05")publicStringdoSentinel05()throwsInterruptedException{//獲取自增對象的值,然後再加1longnum=atomicLong.getAndIncrement();if(num%2==0){//模擬50%的慢調用比例Thread.sleep(200);}return"sentinel04test";}

說明,我們在此方法中設置休眠,目的是為了演示慢調用(響應時間比較長).

Sentinel降級入門

接下來,我們基於一個請求鏈路,進行服務降級及應用實踐,例如:

第一步:服務啟動後,選擇要降級的鏈路,如圖所示:

第二步:選擇要降級的鏈路,如圖所示:

這裡表示熔斷策略選擇"慢調用比例",表示請求數超過3時,假如平均響應時間超過200毫秒的有30%,則對請求進行熔斷,熔斷時長為20秒鐘,10秒以後恢復正常。

第三步:對指定鏈路進行刷新,多次訪問測試,檢測頁面上是否會出現限流(默認異常為DegradeException)

我們也可以進行斷點調試,在DefaultBlockExceptionHandler中的handle方法內部加斷點,分析異常類型,假如異常類型DegradeException 則為降級熔斷。

Sentinel 異常處理

系統提供了默認的異常處理機制,假如默認處理機制不滿足我們需求,我們可以自己進行定義。定義方式上可以直接或間接實現BlockExceptionHandler接口,並將對象交給spring管理。

packagecom.jt.provider.controller;importcom.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;importcom.alibaba.csp.sentinel.slots.block.BlockException;importcom.fasterxml.jackson.databind.ObjectMapper;importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Component;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.PrintWriter;importjava.util.HashMap;importjava.util.Map;/***自定義限流,降級等異常處理對象*/@Slf4j@ComponentpublicclassServiceBlockExceptionHandlerimplementsBlockExceptionHandler{/***用於處理BlockException類型以及子類類型異常*/@Overridepublicvoidhandle(HttpServletRequestrequest,HttpServletResponseresponse,BlockExceptione)throwsException{//設置響應數據編碼response.setCharacterEncoding("utf-8");//告訴客戶端響應數據的類型,以及客戶端顯示內容的編碼response.setContentType("text/html;charset=utf-8");//向客戶端響應一個json格式的字符串//Stringstr="{\"status\":429,\"message\":\"訪問太頻繁了\"}";Map<String,Object>map=newHashMap<>();map.put("status",429);map.put("message","訪問太頻繁了");StringjsonStr=newObjectMapper().writeValueAsString(map);PrintWriterout=response.getWriter();out.print(jsonStr);out.flush();out.close();}}Sentinel熱點規則分析
何為熱點?熱點即經常訪問的數據。比如:
商品 ID 為參數,統計一段時間內最常購買的商品 ID 並進行限制。
用戶 ID 為參數,針對一段時間內頻繁訪問的用戶 ID 進行限制。
熱點參數限流會統計傳入參數中的熱點數據,並根據配置的限流閾值與模式,對包含熱點參數的資源調用進行限流。熱點參數限流可以看做是一種特殊的流量控制,僅對包含熱點參數的資源調用生效。其中,Sentinel會利用 LRU 策略統計最近最常訪問的熱點參數,結合令牌桶算法來進行參數級別的流控。
注意的是,熱點參數限流對默認的SpringMVC資源無效,只有使用SentinelResource標註的資源有用。

第一步:在sca-provider中添加如下方法,例如:

@GetMapping("/sentinel/findById")@SentinelResource("resource")publicStringdoFindById(@RequestParam("id")Integerid){return"resourceidis"+id;}

第二步:服務啟動後,選擇要限流的熱點鏈路,如圖所示:

第三步:設置要限流的熱點,如圖所示:

熱點規則的限流模式只有QPS模式(這才叫熱點)。參數索引為@SentinelResource註解的方法參數下標,0代表第一個參數,1代表第二個參數。單機閾值以及統計窗口時長表示在此窗口時間超過閾值就限流。

第四步:多次訪問熱點參數方法,前端會出現如下界面,如圖所示:

然後,在後台出現如下異常表示限流成功。

com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException:2

其中,熱點參數其實說白了就是特殊的流控,流控設置是針對整個請求的;但是熱點參數他可以設置到具體哪個參數,甚至參數針對的值,這樣更靈活的進行流控管理。

一般應用在某些特殊資源的特殊處理,如:某些商品流量大,其他商品流量很正常,就可以利用熱點參數限流的方案。

特定參數【熱點限流中的某個參數值的閾值設計】設計

配置參數例外項,如圖所示:

其中,這裡表示參數值為5時閾值為100,其它參數值閾值為1.

Sentinel系統規則
系統在生產環境運行過程中,我們經常需要監控服務器的狀態,看服務器CPU、內存、IO等的使用率;主要目的就是保證服務器正常的運行,不能被某些應用搞崩潰了;而且在保證穩定的前提下,保持系統的最大吞吐量。
sentinel中的系統規則,是對所有鏈路的控制規則,是一種系統保護策略,Sentinel系統保護規則被觸發以後底層會拋出SystemBlockException異常。
Sentinel的系統保護規則是從應用級別的入口流量進行控制,從單台機器的總體 Load(負載)、RT(響應時間)、入口 QPS 、線程數和CPU使用率五個維度監控應用數據,讓系統儘可能跑在最大吞吐量的同時保證系統整體的穩定性。如圖所示:

系統規則是一種全局設計規則,其中,

Load(僅對 Linux/Unix-like 機器生效):當系統 load1 超過閾值,且系統當前的並發線程數超過系統容量時才會觸發系統保護。系統容量由系統的 maxQps * minRt 計算得出。設定參考值一般是 CPU cores * 2.5。
CPU使用率:當系統 CPU 使用率超過閾值即觸發系統保護(取值範圍 0.0-1.0)。
RT:當單台機器上所有入口流量的平均 RT 達到閾值即觸發系統保護,單位是毫秒。
線程數:當單台機器上所有入口流量的並發線程數達到閾值即觸發系統保護。
入口 QPS:當單台機器上所有入口流量的 QPS 達到閾值即觸發系統保護。

說明,系統保護規則是應用整體維度的,而不是資源維度的,並且僅對入口流量生效。入口流量指的是進入應用的流量(EntryType.IN),比如 Web 服務。

Sentinel授權規則

很多時候,我們需要根據調用方來限制資源是否通過,這時候可以使用 Sentinel 的黑白名單控制的功能。黑白名單根據資源的請求來源(origin)限制資源是否通過,若配置白名單則只有請求來源位於白名單內時才可通過;若配置黑名單則請求來源位於黑名單時不通過,其餘的請求通過。例如微信中的黑名單。

快速入門

sentinel可以基於黑白名單方式進行授權規則設計,如圖所示:

黑白名單規則(AuthorityRule)非常簡單,主要有以下配置項:

資源名:即限流規則的作用對象
流控應用:對應的黑名單/白名單中設置的規則值,多個值用逗號隔開.
授權類型:白名單,黑名單(不允許訪問).
案例實現:

定義請求解析器,用於對請求進行解析,並返回解析結果,sentinel底層在攔截到用戶請求以後,會對請求數據基於此對象進行解析,判定是否符合黑白名單規則,例如:

第一步:定義RequestOriginParser接口的實現類,在接口方法中解析請求參數數據並返回,底層會基於此返回值進行授權規則應用。

@ComponentpublicclassDefaultRequestOriginParserimplementsRequestOriginParser{@OverridepublicStringparseOrigin(HttpServletRequestrequest){Stringorigin=request.getParameter("origin");//這裡的參數名會與請求中的參數名一致returnorigin;}}

第二步:定義流控規則,如圖所示:

第三步:執行資源訪問,檢測授權規則應用,當我們配置的流控應用值為app1時,假如規則為黑名單,則基於http://ip:port/path?origin=app1的請求不可以通過,其請求處理流程如圖下:

拓展:嘗試基於請求ip等方式進行黑白名單的規則設計,例如:

第一步: 修改請求解析器,獲取請求ip並返回,例如:

@ComponentpublicclassDefaultRequestOriginParserimplementsRequestOriginParser{//解析請求源數據@OverridepublicStringparseOrigin(HttpServletRequestrequest){//獲取訪問請求中的ip地址,基於ip地址進行黑白名單設計(例如在流控應用欄寫ip地址)Stringip=request.getRemoteAddr();System.out.println("ip="+ip);returnip;}//授權規則中的黑白名單的值,來自此方法的返回值}

第二步:在sentinel控制台定義授權規則,例如:

第三步:規則定義後以後,基於你的ip地址,進行訪問測試,檢測黑白名單效果.

Sentinel中的授權規則: 對指定資源的訪問給出的一種簡易的授權策略
Sentinel如何識別白名單和黑名單?(在攔截器中通過調用RequestOriginParser對象的方法檢測具體的規則)
授權規則中RequestOriginParser類的做用是什麼?(對流控應用值進行解析,檢查服務訪問時傳入的值是否與RequestOriginParser的parseOrigin方法返回值是否相同。)
來源:blog.csdn.net/qq_25447799/article/
details/123122820

推薦

Java面試題寶典

技術內卷群,一起來學習!!

PS:因為公眾號平台更改了推送規則,如果不想錯過內容,記得讀完點一下「在看」,加個「星標」,這樣每次新文章推送才會第一時間出現在你的訂閱列表里。點「在看」支持我們吧!

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()