流量控制服務(wù)降級神器之Sentinel
說到流量服務(wù)控制,那么肯定有很多人都不太了解這個內(nèi)容,因為如果對服務(wù)要求不是那么嚴(yán)格的情況下,基本是不會使用到這個東西的,但是,如果想要通過多個維度來保護服務(wù)和維持系統(tǒng)穩(wěn)定性的話,那么就一定離不開Sentinel。
什么是 Sentinel
Sentinel是阿里巴巴公司開源的面向分布式環(huán)境的輕量級流量控制框架。
Sentinel 主要是用來做什么的
Sentinel是以流量為切入點,通過多個維度來保護服務(wù)和維持系統(tǒng)穩(wěn)定性的工具。
主要功能:
- 流量控制
- 熔斷降級
- 系統(tǒng)負(fù)載保護
我們來分別的看一下都是什么意思,首先這個流量控制,
什么是流量控制呢?
就比如說,我們的請求,堆積起來成批次的時候,就相當(dāng)于是流量,當(dāng)有大批的請求流量過來的時候,Sentinel就得起到一些作用了,它就相當(dāng)于是一個調(diào)配器,將隨機的請求變成順序的請求,將不同格式的請求格式化為統(tǒng)一的格式的請求。
那么什么是熔斷降級呢?
實際上熔斷降級就是在調(diào)用鏈路中的某個資源出現(xiàn)了不穩(wěn)定,最終會導(dǎo)致請求發(fā)生堆積,然后為了避免這種情況,就有了熔斷降級。
發(fā)生熔斷降級時,系統(tǒng)這時候所處的狀態(tài)可能為:
- 調(diào)用(響應(yīng))超時
- 異常比例升高
所以熔斷降級會進行處理,通過并發(fā)線程數(shù)進行限制,還有就是通過響應(yīng)時間對資源進行降級。
那么過載保護又體現(xiàn)在哪些方面呢?
其實主要就是體現(xiàn)在系統(tǒng)資源占用比例過高,讓系統(tǒng)的入口流量和系統(tǒng)的負(fù)載達(dá)到一個平衡,保證系統(tǒng)在能力范圍之內(nèi)處理最多的請求。
為什么使用 Sentinel
我們來看看這個 Sentinel 都有哪些優(yōu)點,為什么這么人都使用呢?
我們都知道這個 Sentinel 是阿里開源的,甚至在雙十一大促的時候,也起到了關(guān)鍵性的作用。
比如其中的秒殺,集群流量控制,消息削峰填谷,所以第一個優(yōu)點就出來了,
1.應(yīng)用場景豐富。
如果你使用過 Sentinel ,那么一定登陸過 Sentinel 的后臺,它的后臺十分完善,服務(wù)流量的實時顯示,集群匯總的運行情況,都是非常完美的,所以第二個優(yōu)點也有了。
2.完善的實時監(jiān)控
第三個優(yōu)點,其實其他很多的工具都是有的,那就開源,那么我們就來看看這個 Sentinel 在 Windows 下是如何使用的。
Sentinel 控制臺
畢竟我們剛才已經(jīng)說了他有完善的實時監(jiān)控了,而這個實時監(jiān)控也能體現(xiàn)在我們的頁面上,那么他就是控制臺程序,我們直接來整一下。
1.下載 Windows 的安裝包
Windows下的jar
了不起已經(jīng)把jar包已經(jīng)下載下來了,接下來我們看看如何啟動,其實啟動jar包的方式那我都不需要說,肯定都知道,但是啟動 Sentinel 的 Jar 包也是需要有些參數(shù)的,比如如下需要你了解的參數(shù)。
- -Dserver.port:指定啟動的端口,默認(rèn)8080
- -Dproject.name:指定本服務(wù)的名稱
- -Dcsp.sentinel.dashboard.server:指定sentinel控制臺的地址,用于將自己注冊進入實現(xiàn)監(jiān)控自己
- -Dsentinel.dashboard.auth.username=sentinel 用于指定控制臺的登錄用戶名為 "sentinel",默認(rèn)值為 “sentinel”
- -Dsentinel.dashboard.auth.password=123456 用于指定控制臺的登錄密碼為 "123456",默認(rèn)值為 "sentinel"
- -Dserver.servlet.session.timeout=7200 用于指定 Spring Boot 服務(wù)端 session 的過期時間,如 7200 表示 7200 秒;60m 表示 60 分鐘,默認(rèn)為 30 分鐘,需要注意的是,部署多臺控制臺時,session 默認(rèn)不會在各實例之間共享,這一塊需要自行改造。
了解這么多也不錯了,然后我們來弄個比較簡單的啟動
我們直接用比較簡單的命令來啟動。
java -Dserver.port=9999 -Dcsp.sentinel.dashboard.server=localhost:9999 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar
默認(rèn)賬號和密碼都是 sentinel
我們直接登陸,然后看到的就是他的控制面板了。
我們看到了控制臺,接下來我們就得去看看整合到項目中,是如何實現(xiàn)限流的。
Sentinel 整合入SpringBoot中
創(chuàng)建 SpringCloud的項目,了不起就不再說了,直接說怎么引入這個 Sentinel 吧。
依賴引入:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
其實往上還有很多博主說需要引入一些不如 actuator 的依賴,其實不需要,原因顯而易見,這和個包肯定是包含這些依賴的,比如::
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
<version>2.4.2</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
<version>2.4.2</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.4.2</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
在 spring-cloud-starter-alibaba-sentinel中實際上已經(jīng)都引入過了,所以不需要再單獨的去引入依賴。
依賴引入了,接下來就得看看怎么配置這個配置文件
spring:
application:
name: xxxxx
cloud:
nacos:
config:
username: nacos
password: nacos
context-path: /nacos
server-addr: 127.0.0.1:8848
file-extension: yml
group: DEFAULT_GROUP
discovery:
username: nacos
password: nacos
server-addr: 127.0.0.1:8848
sentinel:
# sentinel看板的地址
transport:
dashboard: localhost:9999
# 開啟對sentinel看板的饑餓式加載。sentinel默認(rèn)是懶加載機制,只有訪問過一次的資源才會被監(jiān)控,通過關(guān)閉懶加載,在項目啟動時就連接sentinel控制臺
eager: true
了不起就截圖了一些內(nèi)容,主要看sentinel 的配置就可以,
當(dāng)我們啟動的時候,然后訪問一下swagger的文檔,
此時查看sentinel控制臺,將會看見這個服務(wù)已經(jīng)被監(jiān)控了。
Sentinel 限流使用方法
Sentinel 可以簡單分為 Sentinel 核心庫和 Dashboard,核心庫不依賴 Dashboard,但是結(jié)合 Dashboard 可以獲得更好的效果。使用 Sentinel 來進行資源保護,主要分為幾個步驟:
(1)定義資源:資源可以是程序中的任何內(nèi)容,例如一個服務(wù),服務(wù)里的方法,甚至是一段代碼。
(2)定義規(guī)則:Sentinel 支持以下幾種規(guī)則:流量控制規(guī)則、熔斷降級規(guī)則、系統(tǒng)保護規(guī)則、來源訪問控制規(guī)則 和 熱點參數(shù)規(guī)則。
(3)檢驗規(guī)則是否生效
由于 Sentinel 中所有的規(guī)則都可以在動態(tài)地查詢和修改,并且修改后立即生效,并且 Sentinel 中資源定義和規(guī)則的配置是分離的。因此在編碼時,我們先把需要保護的資源定義好(埋點),之后便可以在需要的時候動態(tài)配置規(guī)則了。也可以理解為,只要有了資源,我們就能在任何時候靈活地定義各種規(guī)則。
實現(xiàn)方式有兩種,第一種是通過硬編碼的方式,但是這種方式很少有人使用,侵入性太高了呀,改代碼還得改一堆東西,了不起就不說了,我們主要來說說這個使用注解的方式,這種方式方便而且還簡單。
@SentinelResource注解方式(推薦)
我們先看看注解源碼都寫了啥?
package com.alibaba.csp.sentinel.annotation;
import com.alibaba.csp.sentinel.EntryType;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface SentinelResource {
/**
* @return name of the Sentinel resource
*/
String value() default "";
/**
* @return the entry type (inbound or outbound), outbound by default
*/
EntryType entryType() default EntryType.OUT;
/**
* @return the classification (type) of the resource
* @since 1.7.0
*/
int resourceType() default 0;
/**
* @return name of the block exception function, empty by default
*/
String blockHandler() default "";
/**
* The {@code blockHandler} is located in the same class with the original method by default.
* However, if some methods share the same signature and intend to set the same block handler,
* then users can set the class where the block handler exists. Note that the block handler method
* must be static.
*
* @return the class where the block handler exists, should not provide more than one classes
*/
Class<?>[] blockHandlerClass() default {};
/**
* @return name of the fallback function, empty by default
*/
String fallback() default "";
/**
* The {@code defaultFallback} is used as the default universal fallback method.
* It should not accept any parameters, and the return type should be compatible
* with the original method.
*
* @return name of the default fallback method, empty by default
* @since 1.6.0
*/
String defaultFallback() default "";
/**
* The {@code fallback} is located in the same class with the original method by default.
* However, if some methods share the same signature and intend to set the same fallback,
* then users can set the class where the fallback function exists. Note that the shared fallback method
* must be static.
*
* @return the class where the fallback method is located (only single class)
* @since 1.6.0
*/
Class<?>[] fallbackClass() default {};
/**
* @return the list of exception classes to trace, {@link Throwable} by default
* @since 1.5.1
*/
Class<? extends Throwable>[] exceptionsToTrace() default {Throwable.class};
/**
* Indicates the exceptions to be ignored. Note that {@code exceptionsToTrace} should
* not appear with {@code exceptionsToIgnore} at the same time, or {@code exceptionsToIgnore}
* will be of higher precedence.
*
* @return the list of exception classes to ignore, empty by default
* @since 1.6.0
*/
Class<? extends Throwable>[] exceptionsToIgnore() default {};
}
- value:資源名稱,必需項
- entryType:entry 類型,可選項(默認(rèn)為 EntryType.OUT)
- blockHandler / blockHandlerClass:blockHandler 指定函數(shù)負(fù)責(zé)處理 BlockException 異常,可選項。blockHandler 函數(shù)默認(rèn)需要和原方法在同一個類中,通過指定 blockHandlerClass 為對應(yīng)類的 Class 對象,則可以指定其他類中的函數(shù),但注意對應(yīng)的函數(shù)必需為 static 函數(shù),否則無法解析
- fallback /fallbackClass:fallback 指定的函數(shù)負(fù)責(zé)處理業(yè)務(wù)運行的異常,可選項,fallback 函數(shù)可以針對所有類型的異常(除了exceptionsToIgnore里面排除掉的異常類型)進行處理。
- defaultFallback(since 1.6.0):默認(rèn)的 fallback 函數(shù)名稱,可選項,通常用于通用的 fallback 邏輯。defaultFallback 函數(shù)默認(rèn)需要和原方法在同一個類中,通過指定 fallbackClass 為對應(yīng)類的 Class 對象,則可以指定指定為其他類的函數(shù),但注意對應(yīng)的函數(shù)必需為 static 函數(shù),否則無法解析。defaultFallback 函數(shù)可以針對所有類型的異常(除了 exceptionsToIgnore 里面排除掉的異常類型)進行處理。若同時配置了 fallback和 defaultFallback,則只有 fallback會生效。
- exceptionsToIgnore(since 1.6.0):用于指定哪些異常被排除掉,不會計入異常統(tǒng)計中,也不會進入 fallback 邏輯中,而是會原樣拋出。
其中不常用的可以了解就可以了,你說呢?