文章知識(shí)來(lái)源主要來(lái)源于:趙俊夫先生的博客 以下為原文鏈接
https://blog.csdn.net/u011177064/category_9572944.html
1:什么是服務(wù)限流
我們后端的接口調(diào)用頻次(QPS/TPS)動(dòng)輒上百萬(wàn),甚至達(dá)到千萬(wàn)級(jí)別块蚌,
這對(duì)于服務(wù)端的承受能力是一個(gè)巨大的考驗(yàn)府寒。
那么限流在這個(gè)問(wèn)題中起到什么作用呢?
其實(shí)就是對(duì)于流量進(jìn)行有策略的管理和限制。 比如說(shuō)在一個(gè)系統(tǒng)中氢架,有訂單查詢服務(wù)郭毕,商品查詢服務(wù),積分查詢等刘急,
如果一個(gè)系統(tǒng)能支持的QPS(每秒查詢次數(shù))是100棚菊,那么這100該如何如何分配就是限流功能所考慮的事情。
根據(jù)這些服務(wù)的重要性叔汁,我們可能會(huì)把商品查詢服務(wù)的QPS設(shè)置的比較高统求,
因?yàn)檫@類用戶查詢到商品是有購(gòu)買意向的检碗,而訂單查詢、積分查詢啥的
在用戶訪問(wèn)量過(guò)大時(shí)码邻,我們就能盡量保證有購(gòu)買意向的用戶正常使用系統(tǒng)折剃。
2:什么是Sentinel
在SpringCloud GateWay服務(wù)網(wǎng)關(guān)中集成Sentinel來(lái)實(shí)現(xiàn)服務(wù)的限流功能。
主要以流量為切入點(diǎn)像屋,從流量控制怕犁、熔斷降級(jí)、系統(tǒng)負(fù)載保護(hù)等多個(gè)維度保護(hù)服務(wù)的穩(wěn)定性己莺。
3:Pom配置
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
4:GatewayFlowRule 的字段詳解
網(wǎng)關(guān)限流規(guī)則 GatewayFlowRule 的字段解釋如下:
resource:資源名稱奏甫,可以是網(wǎng)關(guān)中的 route 名稱或者用戶自定義的 API 分組名稱。
resourceMode:
規(guī)則是針對(duì) API Gateway 的 route(RESOURCE_MODE_ROUTE_ID)
還是用戶在 Sentinel 中定義的 API 分組(RESOURCE_MODE_CUSTOM_API_NAME)凌受,默認(rèn)是 route阵子。
grade:限流指標(biāo)維度,同限流規(guī)則的 grade 字段胜蛉。
count:限流閾值
intervalSec:統(tǒng)計(jì)時(shí)間窗口挠进,單位是秒,默認(rèn)是 1 秒誊册。
controlBehavior:
流量整形的控制效果领突,同限流規(guī)則的 controlBehavior 字段,
目前支持快速失敗和勻速排隊(duì)兩種模式案怯,默認(rèn)是快速失敗攘须。
burst:應(yīng)對(duì)突發(fā)請(qǐng)求時(shí)額外允許的請(qǐng)求數(shù)目。
maxQueueingTimeoutMs:勻速排隊(duì)模式下的最長(zhǎng)排隊(duì)時(shí)間殴泰,單位是毫秒于宙,僅在勻速排隊(duì)模式下生效。
paramItem:參數(shù)限流配置悍汛。
若不提供捞魁,則代表不針對(duì)參數(shù)進(jìn)行限流,該網(wǎng)關(guān)規(guī)則將會(huì)被轉(zhuǎn)換成普通流控規(guī)則离咐;
否則會(huì)轉(zhuǎn)換成熱點(diǎn)規(guī)則谱俭。
其中的字段:
1:parseStrategy:從請(qǐng)求中提取參數(shù)的策略,目前支持提取來(lái)源 (四種模式)
1:IP(PARAM_PARSE_STRATEGY_CLIENT_IP)
2:Host(PARAM_PARSE_STRATEGY_HOST)
3:任意 Header(PARAM_PARSE_STRATEGY_HEADER)
4:任意 URL 參數(shù)(PARAM_PARSE_STRATEGY_URL_PARAM)
2: fieldName:若提取策略選擇 Header 模式或 URL 參數(shù)模式宵蛀,則需要指定對(duì)應(yīng)的 header 名稱或 URL 參數(shù)名稱昆著。
3:pattern:參數(shù)值的匹配模式,只有匹配該模式的請(qǐng)求屬性值會(huì)納入統(tǒng)計(jì)和流控术陶;若為空則統(tǒng)計(jì)該請(qǐng)求屬性的所有值凑懂。(1.6.2 版本開始支持)
4: matchStrategy:參數(shù)值的匹配策略支持:
1:精確匹配(PARAM_MATCH_STRATEGY_EXACT)、
2:子串匹配(PARAM_MATCH_STRATEGY_CONTAINS)
3: 正則匹配(PARAM_MATCH_STRATEGY_REGEX)梧宫。(1.6.2 版本開始支持)
加載網(wǎng)關(guān)規(guī)則方式:
1:用戶可以通過(guò) GatewayRuleManager.loadRules(rules) 手動(dòng)加載網(wǎng)關(guān)規(guī)則接谨,
2:通過(guò) GatewayRuleManager.register2Property(property) 注冊(cè)動(dòng)態(tài)規(guī)則源動(dòng)態(tài)推送(推薦方式)
5:注入Sentinel配置
/**
* 設(shè)置進(jìn)行限流的Api集合
*/
private void initCustomizedApis() {
/*
ApiDefinition:用戶自定義的 API 定義分組摆碉,可以看做是一些 URL 匹配的組合。
比如我們可以定義一個(gè) API 叫 myGateway脓豪,
請(qǐng)求 path 模式為
/nacos-provider/loadBanlance/print 默認(rèn)為準(zhǔn)確的 URL_MATCH_STRATEGY_EXACT
/nacos-provider/loadBanlance/** 如需/**需要設(shè)置成 URL_MATCH_STRATEGY_PREFIX
的都?xì)w到 myGateway 這個(gè) API 分組下面巷帝。
*/
//限流的時(shí)候可以針對(duì)這個(gè)自定義的 API 分組維度進(jìn)行限流。
Set<ApiDefinition> definitions = new HashSet<>();
//設(shè)置限流路徑
ApiDefinition api = new ApiDefinition("myGateway")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem()
// .setPattern("/nacos-provider/loadBanlance/print")
.setPattern("/nacos-provider/loadBanlance/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)
);
}});
definitions.add(api);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
/**
* 設(shè)置限流的Api集合的具體限流
*/
private void initGatewayRules() {
/*
GatewayFlowRule:網(wǎng)關(guān)限流規(guī)則扫夜,
針對(duì) API Gateway 的場(chǎng)景定制的限流規(guī)則楞泼,可以針對(duì)不同 route 或自定義的 API 分組進(jìn)行限流,
支持針對(duì)請(qǐng)求中的參數(shù)笤闯、Header堕阔、來(lái)源 IP 等進(jìn)行定制化的限流。
*/
Set<GatewayFlowRule> rules = new HashSet<>();
/*設(shè)置限流規(guī)則
count: QPS即每秒鐘允許的調(diào)用次數(shù)
intervalSec: 每隔多少時(shí)間統(tǒng)計(jì)一次匯總數(shù)據(jù)望侈,統(tǒng)計(jì)時(shí)間窗口,單位是秒勋桶,默認(rèn)是 1 秒脱衙。
*/
//針對(duì)上面的 自定義ApiDefinition分組進(jìn)行限流
rules.add(new GatewayFlowRule("myGateway")
.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
.setCount(5)
.setIntervalSec(1)
);
GatewayRuleManager.loadRules(rules);
}
6:測(cè)試 重復(fù)請(qǐng)求
方法一:
設(shè)置 允許調(diào)用次數(shù)少點(diǎn)(直接設(shè)置成0) 然后在postman不斷進(jìn)行點(diǎn)擊請(qǐng)求
方法二:
使用postman進(jìn)行并發(fā)測(cè)試
1:設(shè)置三個(gè)完全一樣的請(qǐng)求路徑 然后存到集合里面
2:在0秒的延遲(delay)內(nèi) 開啟 10個(gè)線程(Interation) 進(jìn)行對(duì)集合進(jìn)行請(qǐng)求
3:點(diǎn)擊請(qǐng)求 查看結(jié)果 發(fā)現(xiàn)該路徑限制1秒內(nèi) 只能請(qǐng)求5次
7:自定義異常返回
public class MyBlockRequestHandler implements BlockRequestHandler {
private static final String DEFAULT_BLOCK_MSG_PREFIX = "Blocked by Sentinel: ";
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable ex) {
// 返回http狀態(tài)碼為200
return ServerResponse.status(200).contentType(MediaType.APPLICATION_JSON_UTF8)
.body(fromObject(buildErrorResult(ex)));
}
private ErrorResult buildErrorResult(Throwable ex) {
return new ErrorResult(200,
DEFAULT_BLOCK_MSG_PREFIX + ex.getClass().getSimpleName());
}
private static class ErrorResult {
private final int code;
private final String message;
ErrorResult(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
}
8:限流日志
默認(rèn)sentinel的限流日志會(huì)存放在這里
有興趣的話可以自己查看 后續(xù)會(huì)講到sentinel的可視化日志界面
C:\Users\HSJ\logs\csp
項(xiàng)目連接
請(qǐng)配合項(xiàng)目代碼食用效果更佳:
項(xiàng)目地址:
https://github.com/hesuijin/spring-cloud-alibaba-project
Git下載地址:
https://github.com.cnpmjs.org/hesuijin/spring-cloud-alibaba-project.git
在gateway 模塊下