sentinel集群限流
1、概述
1.1、背景
第三方接口有限流,需要根據(jù)第三方的限流提前控制流量,防止調(diào)用第三方接口被限流。
1.2、目的
研究sentinel中間件的限流是否符合我們需要的業(yè)務(wù)場(chǎng)景。主要從以下幾個(gè)方面考慮:
1、限流需要支持集群(分布式服務(wù)下,需要支持多節(jié)點(diǎn)的限流)
2、限流規(guī)則的持久化(不同三方接口限流規(guī)則不一致,需要限流的方法繁多且規(guī)則不一致,規(guī)則最好支持?jǐn)?shù)據(jù)庫(kù)的持久化)
3、限流參數(shù)的靈活性(限流的方法可以通過(guò)參數(shù)來(lái)自定義,比如大部分三方接口是根據(jù)應(yīng)用id來(lái)進(jìn)行限流,另外關(guān)注限流的時(shí)間窗口可配置)
4、限流之后的異常處理(異常處理要支持自定義,比如對(duì)于三方接口的異常處理,我們需要進(jìn)行休眠操作,而不是直接失?。?/p>
針對(duì)以上四點(diǎn),著重看一下sentinel這這些方面是否有比較友好的支持:
項(xiàng)目地址:https://gitee.com/ershuai8614/sentinel.git
2、嵌入式集群流控
2.1 、通過(guò)控制臺(tái)添加規(guī)則
2.1.1、項(xiàng)目配置啟動(dòng)
sentinel本身就是支持集群的,由于官網(wǎng)文檔已經(jīng)對(duì)集群流控已經(jīng)介紹的比較詳細(xì)(官方文檔:https://sentinelguard.io/zh-cn/docs/cluster-flow-control.html),這里不再贅述,下面主要講解集群限流在項(xiàng)目中的應(yīng)用。
down下來(lái)上面的項(xiàng)目地址,我們需要啟動(dòng)兩個(gè)項(xiàng)目,一個(gè)是sentinel的控制臺(tái)(控制臺(tái)中可以手動(dòng)對(duì)限流的規(guī)則進(jìn)行自定義,只不過(guò)這些規(guī)則只在內(nèi)存中,不能持久化),另一個(gè)是sentinel的嵌入式集群測(cè)試demo。
1)找到sentinel-dashboard中的DashboardApplication,啟動(dòng)的jvm參數(shù):-Dserver.port=8088
?
?
2)找到sentinel-demo中 sentinel-demo-cluster中 sentinel-demo-cluster-embedded項(xiàng)目中的ClusterDemoApplication
同一個(gè)項(xiàng)目分別啟動(dòng)三個(gè)項(xiàng)目,jvm啟動(dòng)參數(shù)分別如下:
-Dcsp.sentinel.log.use.pid=true -Dproject.name=sentinle.cluster.demo.embedded -Dserver.port=8083 -Dcsp.sentinel.dashboard.server=localhost:8088 -Dcsp.sentinel.api.port=8283
-Dcsp.sentinel.log.use.pid=true -Dproject.name=sentinle.cluster.demo.embedded -Dserver.port=8084 -Dcsp.sentinel.dashboard.server=localhost:8088 -Dcsp.sentinel.api.port=8284
-Dcsp.sentinel.log.use.pid=true -Dproject.name=sentinle.cluster.demo.embedded -Dserver.port=8085 -Dcsp.sentinel.dashboard.server=localhost:8088 -Dcsp.sentinel.api.port=8285
啟動(dòng)參數(shù)解釋如下:
-Dcsp.sentinel.log.use.pid=true? ? ? ? ? ? ? ? ? ? ? ? ? ? --若在本地啟動(dòng)多個(gè) Demo 示例,需要加上此啟動(dòng)參數(shù),否則控制臺(tái)顯示監(jiān)控會(huì)不準(zhǔn)確
-Dproject.name? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?--指定項(xiàng)目名稱
-Dserver.port=8083? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?--指定啟動(dòng)項(xiàng)目端口號(hào)
-Dcsp.sentinel.dashboard.server=localhost:8088? --指定seneinel控制臺(tái)的地址和端口(與sentinel控制臺(tái)啟動(dòng)的端口保持一致)
-Dcsp.sentinel.api.port=8283? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? --指定控制臺(tái)監(jiān)控客戶端API 的端口
?
?
兩個(gè)項(xiàng)目啟動(dòng)之后,我們打開控制臺(tái)(默認(rèn)賬號(hào)密碼為sentinel/sentinel),發(fā)現(xiàn)此時(shí)控制臺(tái)沒(méi)有相關(guān)的項(xiàng)目配置,我們需要先分別調(diào)用一下配置了限流的接口,localhost:8083/hello/world ,localhost:8084/hello/world ,localhost:8085/hello/world??(hello的接口在項(xiàng)目中加了限流的注解)
sentinel的接口限流相關(guān)配置實(shí)現(xiàn)類是懶加載的,在第一次調(diào)用后,限流相關(guān)的資源以及配置信息才會(huì)在控制臺(tái)顯示。
控制臺(tái)的機(jī)器列表(我們分別啟動(dòng)了三個(gè)服務(wù),剛好對(duì)應(yīng)上)
?
?
2.1.2、集群配置
因?yàn)槲覀冄芯康氖羌毫艨?,所以在給接口配置流控規(guī)則之前,需要先配置集群信息
1、應(yīng)用內(nèi)機(jī)器指的就是嵌入模式,嵌入模式下(token和client均可以分?jǐn)偭髁?,而外部指定機(jī)器指的是獨(dú)立模式,具體看官方集群流控文檔:https://sentinelguard.io/zh-cn/docs/cluster-flow-control.html)
2、選擇token和client機(jī)器組成流控的集群,最大允許qps為1
?
?
配置完成之后我們可以點(diǎn)擊tokenClient列表查看全部client客戶端
?
?
這里需要注意的是,我們需要手動(dòng)編輯一下client客戶端的配置,默認(rèn)客戶端和服務(wù)端請(qǐng)求超時(shí)時(shí)間是20ms,這里改成2000ms,不然后面測(cè)試流控可能會(huì)出問(wèn)題。
?
?
2.1.3、流控規(guī)則配置
在配置完集群信息之后我們?cè)诖攸c(diǎn)鏈路列表給sayHello資源添加流控的規(guī)則(需要給三臺(tái)服務(wù)均添加流控規(guī)則)
1、資源名指的就是需要進(jìn)行流量限制的接口名
2、針對(duì)來(lái)源是可以對(duì)調(diào)用該接口的來(lái)源進(jìn)行限流配置,默認(rèn)default全部
3、閾值類型有 qps和并發(fā)線程數(shù),我們這里選qps,集群閾值填1,表示1s只能有一個(gè)請(qǐng)求,集群閾值模式可以選單機(jī)均攤和總體閾值,單機(jī)均攤會(huì)根據(jù)服務(wù)的總連接數(shù)計(jì)算總的閾值,而總體閾值是針對(duì)于整個(gè)集群而言,這里我們選總體閾值,失敗退化是指token服務(wù)不可用之后自動(dòng)轉(zhuǎn)換成單機(jī)限流。
?
?
?
?
規(guī)則添加完成之后,找到com.alibaba.csp.sentinel.demo.cluster.ClusterDemoTest,分別調(diào)用者三個(gè)接口,返現(xiàn)在1s之內(nèi),只有第一個(gè)接口可以響應(yīng)成功,后面兩個(gè)服務(wù)響應(yīng)會(huì)失敗。
?
?
初步來(lái)看,sentinel集群限流是支持的。但是上面我們是通過(guò)控制臺(tái)手動(dòng)添加規(guī)則,在文章的開始我們也說(shuō)明了,我們的業(yè)務(wù)場(chǎng)景需要支持規(guī)則持久化,最好是能通過(guò)db的方式來(lái)讀取我們的規(guī)則。下面我們來(lái)看sentinel的規(guī)則持久化相關(guān)的支持。
2.2、sentinel流控規(guī)則持久化
官方文檔說(shuō)明:https://sentinelguard.io/zh-cn/docs/dynamic-rule-configuration.html
從官方文檔上可以看出,sentinel對(duì)規(guī)則的持久化只適配了nacos,我們可以通過(guò)nacos來(lái)定義需要限流的資源和具體限流的規(guī)則。同樣是以嵌入集群模式下為例,我們來(lái)嘗試不再使用sentinel控制臺(tái)實(shí)現(xiàn)相關(guān)的規(guī)則定義,而是采用讀取nacos中的配置來(lái)動(dòng)態(tài)加載資源規(guī)則。
同樣是在sentinel-demo中 sentinel-demo-cluster中 sentinel-demo-cluster-embedded項(xiàng)目中,官方已經(jīng)為我們適配了nacos的限流規(guī)則。采用spi的機(jī)制,代碼入口在 com.alibaba.csp.sentinel.demo.cluster.init.DemoClusterInitFunc
?
?
以上是主要的代碼邏輯,每個(gè)方法點(diǎn)進(jìn)去都可以看到,基本就是從nacos中讀取相關(guān)配置然后注入到擴(kuò)展的接口點(diǎn)中去。我們著重看一下nacos都有哪些配置屬性
我這里建了一個(gè)nacos的命名空間sentinle.cluster.demo.embedded ,id為??0fa80e91-7804-446a-99a4-ae5a82f841cb(代碼里需要對(duì)應(yīng))
?
?
主要是以上四條配置,Data id 都是項(xiàng)目啟動(dòng)時(shí)指定的項(xiàng)目名稱?project.name? ?加上指定的后綴組成,分別是流控規(guī)則、集群相關(guān)的配置、熱點(diǎn)規(guī)則以及客戶端配置。Group也指定的SENTINEL_GROUP.
下面分別來(lái)看一下 這四個(gè)配置的內(nèi)容、
sentinle.cluster.demo.embedded-flow-rules
[
????{
????????"resource":"sayHello",? ? ? ? ? ? ?--需要限流的資源名稱
????????"grade":1,? ? ? ? ? ? ? ? ? ? ?--限流閾值類型,QPS 或線程數(shù)模式,默認(rèn)為QPS
????????"count":60,? ? ? ? ? ? ? ? ? ??--限流閾值
????????"strategy":0,? ? ? ? ? ? ? ? ? ?--調(diào)用關(guān)系限流策略:直接、鏈路、關(guān)聯(lián),默認(rèn)直接
????????"controlBehavior":0,? ? ? ? ? ? ?--流控效果(直接拒絕 / 排隊(duì)等待 / 慢啟動(dòng)模式),不支持按調(diào)用關(guān)系限流,默認(rèn)直接拒絕
????????"clusterMode":true,? ? ? ? ? ? ??--標(biāo)識(shí)是否為集群限流配置
????????"clusterConfig":{
????????????"flowId":9959231232121334,? ? ?--全局唯一的規(guī)則 ID,由集群限流管控端分配
????????????"thresholdType":1,? ? ? ? ??--閾值模式,默認(rèn)(0)為單機(jī)均攤,1 為全局閾值
????????????"fallbackToLocalWhenFail":true,?--在 client 連接失敗或通信失敗時(shí),是否退化到本地的限流模式
????????????"strategy":0,? ? ? ? ? ? ??--調(diào)用關(guān)系限流策略:直接、鏈路、關(guān)聯(lián),默認(rèn)直接
????????????"windowIntervalMs":1000? ? ? ?--滑動(dòng)窗口時(shí)間,默認(rèn)1s
????????}
????}
]
sentinle.cluster.demo.embedded-param-rules
[
????{
????????"resource":"sayHello",
????????"grade":1,
????????"paramIdx":0,? ? ? ? ? ? ? ? ? ??--參數(shù)索引位置
????????"count":1,? ? ? ? ? ? ? ? ? ? ??--閾值
????????"durationInSec":60,? ? ? ? ? ? ? ??--統(tǒng)計(jì)窗口時(shí)間長(zhǎng)度(單位為秒)
????????"controlBehavior":0,
????????"clusterMode":true,
????????"clusterConfig":{
????????????"flowId":9959231435454,
????????????"thresholdType":1,
????????????"fallbackToLocalWhenFail":true,
????????????"strategy":0,
????????????"windowIntervalMs":1000
????????}
????}
]
sentinle.cluster.demo.embedded-cluster-map
[
????{
????????"machineId":"192.168.244.168@8283",? ??--token服務(wù)器地址@api監(jiān)控端口
????????"ip":"192.168.244.168",? ? ? ? ? ?--token服務(wù)器ip?
????????"port":18730,? ? ? ? ? ? ? ? ? ?--token服務(wù)器暴露給sentinel控制臺(tái)的端口??
????????"clientSet":[
????????????"192.168.244.168@8284",? ? ? ?--client 端地址、端口
????????????"192.168.244.168@8285"
????????]
????}
]
sentinle.cluster.demo.embedded-client-config
{
? ? ?"requestTimeout":2000? ? --client請(qǐng)求服務(wù)端超時(shí)時(shí)間,單位ms
}
配置好以上nacos配置后,指定nacos的命名空間和地址即可。項(xiàng)目啟動(dòng)之后,我們發(fā)現(xiàn),在sentinel控制臺(tái)中已經(jīng)存在了和我們之前手動(dòng)添加的規(guī)則一樣的配置,而這些配置就是我們?cè)趎acos中的配置(具體規(guī)則的正確性可自行測(cè)試)
通過(guò)以上分析,我們可以看出sentinel已經(jīng)適配了nacos的規(guī)則持久化, 如果我們需要,完全可以自己通過(guò)spi機(jī)制實(shí)現(xiàn)一個(gè)基于db的規(guī)則持久化,和nacos不同的僅僅只是規(guī)則來(lái)源的不同而已。
2.3、熱點(diǎn)參數(shù)限流
上面我們分析了sentinel對(duì)集群、規(guī)則持久化的支持,下面來(lái)看一下規(guī)則定義的靈活性,文章開始已經(jīng)提到,最好是能能夠根據(jù)接口參數(shù)來(lái)限流,這一部分屬于sentinel的熱點(diǎn)參數(shù)限流,官方文檔:https://sentinelguard.io/zh-cn/docs/parameter-flow-control.html
?
?
對(duì)比以上兩種設(shè)置發(fā)現(xiàn),對(duì)于單機(jī)的熱點(diǎn)規(guī)則是可以支持設(shè)置統(tǒng)計(jì)窗口時(shí)長(zhǎng)的,但是對(duì)于集群模式下的熱點(diǎn)規(guī)則,則設(shè)置不了統(tǒng)計(jì)窗口時(shí)長(zhǎng)的。
我們可以通過(guò)上面的測(cè)試用來(lái)進(jìn)行驗(yàn)證,之前我們?cè)賜acos上配置了流控規(guī)則是1s60的qps,熱點(diǎn)參數(shù)限制的是第一個(gè)參數(shù),60s內(nèi)qps為1。
以下測(cè)試用例,在每次請(qǐng)求完成之后,線程休眠1s,發(fā)現(xiàn)并沒(méi)有拋出限流的異常,說(shuō)明我們?cè)O(shè)置的60s 的時(shí)間統(tǒng)計(jì)窗口是無(wú)效的,對(duì)于集群熱點(diǎn)參數(shù)流控來(lái)說(shuō),只能默認(rèn)統(tǒng)計(jì)時(shí)間窗口是1s。
?
?
3、獨(dú)立集群模式
3.1、nacos配置
這里就不在演示通過(guò)控制臺(tái)來(lái)配置規(guī)則,我們直接通過(guò)nacos來(lái)進(jìn)行限流規(guī)則的配置。
創(chuàng)建一個(gè)??sentinle.cluster.demo.alone 的nacos命名空間,我這里創(chuàng)建的id為:f412be2f-04f1-4a50-9bb2-c60bf8593776(后面在代碼中用到),分別有以下配置:
?
?
1、appA-flow-rules:
[
????{
????????"resource":"sayHello",? ? ? ? ? ? ?--需要限流的資源名稱
????????"grade":1,? ? ? ? ? ? ? ? ? ? ?--限流閾值類型,QPS 或線程數(shù)模式,默認(rèn)為QPS
????????"count":60,? ? ? ? ? ? ? ? ? ??--限流閾值
????????"strategy":0,? ? ? ? ? ? ? ? ? ?--調(diào)用關(guān)系限流策略:直接、鏈路、關(guān)聯(lián),默認(rèn)直接
????????"controlBehavior":0,? ? ? ? ? ? ?--流控效果(直接拒絕 / 排隊(duì)等待 / 慢啟動(dòng)模式),不支持按調(diào)用關(guān)系限流,默認(rèn)直接拒絕
????????"clusterMode":true,? ? ? ? ? ? ??--標(biāo)識(shí)是否為集群限流配置
????????"clusterConfig":{
????????????"flowId":9959231232121334,? ? ?--全局唯一的規(guī)則 ID,由集群限流管控端分配
????????????"thresholdType":1,? ? ? ? ??--閾值模式,默認(rèn)(0)為單機(jī)均攤,1 為全局閾值
????????????"fallbackToLocalWhenFail":true,?--在 client 連接失敗或通信失敗時(shí),是否退化到本地的限流模式
????????????"strategy":0,? ? ? ? ? ? ??--調(diào)用關(guān)系限流策略:直接、鏈路、關(guān)聯(lián),默認(rèn)直接
????????????"windowIntervalMs":1000? ? ? ?--滑動(dòng)窗口時(shí)間,默認(rèn)1s
????????}
????}
]
2、cluster-server-namespace-set:
[
????"appA"
]
3、appA-cluster-map:
[
????{
????????"machineId":"192.168.244.168@8788",? ??--token服務(wù)器地址@api監(jiān)控端口
????????"ip":"192.168.244.168",? ? ? ? ? ??--token服務(wù)器ip?
????????"port":11111,? ? ? ? ? ? ? ? ? ?--token服務(wù)器暴露給sentinel控制臺(tái)的端口??
????????"clientSet":[
????????????"192.168.244.168@8281",? ? ? ?--client 端地址、端口
????????????"192.168.244.168@8282"
????????]
????}
]
4、cluster-server-transport-config:
{
????"port":11111,
????"idleSeconds":600
}
5、appA-cluster-client-config:
{
????"requestTimeout":2000
}
6、appA-param-rules
[
????{
????????"resource":"sayHello",
????????"grade":1,
????????"paramIdx":0,? ? ? ? ? ? ? ? ? ??--參數(shù)索引位置
????????"count":1,? ? ? ? ? ? ? ? ? ? ??--閾值
????????"durationInSec":60,? ? ? ? ? ? ? ??--統(tǒng)計(jì)窗口時(shí)間長(zhǎng)度(單位為秒)
????????"controlBehavior":0,
????????"clusterMode":true,
????????"clusterConfig":{
????????????"flowId":9959231435454,
????????????"thresholdType":1,
????????????"fallbackToLocalWhenFail":true,
????????????"strategy":0,
????????????"windowIntervalMs":1000
????????}
????}
]
3.2、項(xiàng)目啟動(dòng):
1)token服務(wù)端啟動(dòng)
找到?com.alibaba.csp.sentinel.demo.cluster.ClusterServerDemo 啟動(dòng),注釋掉傳輸配置,因?yàn)橐呀?jīng)在nacos中配置過(guò)。
jvm啟動(dòng)參數(shù)如下:-Dserver.port=8720 -Dproject.name=appA -Dcsp.sentinel.dashboard.server=127.0.0.1:8088 -Dcsp.sentinel.api.port=8788 -Dcsp.sentinel.log.use.pid=true
?
?
2)客戶端啟動(dòng):(此客戶端是本人基本嵌入式模式copy過(guò)來(lái)的,為了方便測(cè)試兩種集群模式,sentinel官網(wǎng)項(xiàng)目沒(méi)有獨(dú)立模式的客戶端)
找到com.alibaba.csp.sentinel.demo.cluster.ClusterClientDemo 同一個(gè)項(xiàng)目啟動(dòng)兩次,jvm啟動(dòng)參數(shù)如下:
-Dserver.port=8721 -Dproject.name=appA -Dcsp.sentinel.dashboard.server=127.0.0.1:8088 -Dcsp.sentinel.api.port=8281 -Dcsp.sentinel.log.use.pid=true
-Dserver.port=8722 -Dproject.name=appA -Dcsp.sentinel.dashboard.server=127.0.0.1:8088 -Dcsp.sentinel.api.port=8282 -Dcsp.sentinel.log.use.pid=true
啟動(dòng)完成之后,先調(diào)用接口?http://localhost:8721/hello/world? ??http://localhost:8721/hello/world
后打開控制臺(tái),查看機(jī)器列表,分別有三臺(tái)服務(wù)已連接,一個(gè)為token服務(wù)器,另外兩臺(tái)為客戶端。
?
?
?
?
?
?
簇點(diǎn)鏈路資源如下:
?
?
流控規(guī)則如下(兩個(gè)客戶端均有此流控規(guī)則):
?
?
熱點(diǎn)規(guī)則如下(兩個(gè)客戶端均有此配置):
?
?
找到com.alibaba.csp.sentinel.demo.cluster.ClusterDemoTest 測(cè)試類,驗(yàn)證以上規(guī)則是否生效。
?
?
通過(guò)獨(dú)立模式集群限流發(fā)現(xiàn),集群限流生效,但是同樣對(duì)于熱點(diǎn)參數(shù)中配置的時(shí)間窗口沒(méi)有作用。
對(duì)比sentinel的嵌入式集群和獨(dú)立模式集群,我們發(fā)現(xiàn)。兩種集群的區(qū)別是:
同樣兩種集群都有共同的缺陷,就是token server不支持高可用,用于生產(chǎn)環(huán)境需要注意此點(diǎn)。
嵌入式集群:作為內(nèi)置的 token server 與服務(wù)在同一進(jìn)程中啟動(dòng)。在此模式下,集群中各個(gè)實(shí)例都是對(duì)等的,token server 和 client 可以隨時(shí)進(jìn)行轉(zhuǎn)變,因此無(wú)需單獨(dú)部署,靈活性比較好。但是隔離性不佳,需要限制 token server 的總 QPS,防止影響應(yīng)用本身。嵌入模式適合某個(gè)應(yīng)用集群內(nèi)部的流控。
獨(dú)立集群:token服務(wù)器不參與資源請(qǐng)求的限流,它只負(fù)責(zé)向客戶端發(fā)放token,獨(dú)立部署,隔離性好,但是需要額外的部署操作。獨(dú)立模式適合作為 Global Rate Limiter 給集群提供流控服務(wù)。
4、限流之后的異常處理
sentinel對(duì)于限流之后的自異常處理也是支持的,可以直接定義限流異常處理的方法,和異常處理的類
5、總結(jié)
通過(guò)以上對(duì)sentinel的學(xué)習(xí),我們發(fā)現(xiàn)sentinel對(duì)以下4點(diǎn)的支持如下
1、限流需要支持集群(分布式服務(wù)下,需要支持多節(jié)點(diǎn)的限流)? ??---支持
2、限流規(guī)則的持久化(不同三方接口限流規(guī)則不一致,需要限流的方法繁多且規(guī)則不一致,規(guī)則最好支持?jǐn)?shù)據(jù)庫(kù)的持久化)??--支持
3、限流參數(shù)的靈活性(限流的方法可以通過(guò)參數(shù)來(lái)自定義,比如大部分外三方接口是根據(jù)應(yīng)用id來(lái)進(jìn)行限流,另外關(guān)注限流的時(shí)間窗口可配置)? ?--集群限流時(shí)時(shí)間窗口不可配置
4、限流之后的異常處理(異常處理要支持自定義,比如對(duì)于三方接口的異常處理,我們需要進(jìn)行休眠操作,而不是直接失?。?--支持
鏈接:https://www.dianjilingqu.com/537690.html