Spring Cloud Gateway -- 熔斷限流

微服務(wù)系統(tǒng)中熔斷限流環(huán)節(jié)坟乾,對保護系統(tǒng)的穩(wěn)定性起到了很大的作用径缅,作為網(wǎng)關(guān),Spring Cloud Gateway也提供了很好的支持菠赚。先來理解下熔斷限流概念:

  • 熔斷降級:在分布式系統(tǒng)中驳阎,網(wǎng)關(guān)作為流量的入口抗愁,大量請求進(jìn)入網(wǎng)關(guān)馁蒂,向后端遠(yuǎn)程系統(tǒng)或服務(wù)發(fā)起調(diào)用,后端服務(wù)不可避免的會產(chǎn)生調(diào)用失斨╇纭(超時或者異常)沫屡,失敗時不能讓請求堆積在網(wǎng)關(guān)上,需要快速失敗并返回回去撮珠,這就需要在網(wǎng)關(guān)上做熔斷沮脖、降級操作。
  • 限流:網(wǎng)關(guān)上有大量請求芯急,對指定服務(wù)進(jìn)行限流勺届,可以很大程度上提高服務(wù)的可用性與穩(wěn)定性,限流的目的是通過對并發(fā)訪問/請求進(jìn)行限速娶耍,或?qū)σ粋€時間窗口內(nèi)的請求進(jìn)行限速來保護系統(tǒng)免姿。一旦達(dá)到限制速率則可以拒絕服務(wù)、排隊或等待榕酒、降級胚膊。

下文就網(wǎng)關(guān)如何進(jìn)行超時熔斷、異常熔斷和訪問限流進(jìn)行示例說明想鹰。示例包含兩個模塊項目紊婉,一個為網(wǎng)關(guān)項目gateway,一個為下游業(yè)務(wù)項目downstream辑舷。

1.png

超時異常熔斷

構(gòu)建網(wǎng)關(guān)目:

pom.xml

  <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>io.spring.platform</groupId>
                <artifactId>platform-bom</artifactId>
                <version>${spring.platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

 <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>

application.yml

server:
  port: 8089

spring:
  application:
    name: spring-cloud-gateway
  cloud:
    gateway:
      routes:
        - id: service_customer
          #下游服務(wù)地址
          uri: http://127.0.0.1:8083/
          order: 0
          #網(wǎng)關(guān)斷言匹配
          predicates:
            - Path=/gateway/**
          filters:
            #熔斷過濾器
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/defaultfallback
            - StripPrefix=1

#熔斷器配置
hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE
          thread:
            timeoutInMilliseconds: 3000
  shareSecurityContext: true

#網(wǎng)關(guān)日志輸出
logging:
  level:
    org.springframework.cloud.gateway: TRACE
    org.springframework.http.server.reactive: DEBUG
    org.springframework.web.reactive: DEBUG
    reactor.ipc.netty: DEBUG

以上配置的意思是:

  • 網(wǎng)關(guān)服務(wù)以端口8089暴露
  • 訪問http://127.0.0.1:8089/gateway/開頭的請求喻犁,將都被路由到下游http://127.0.0.1:8083/下,且gateway部分將被移除(StripPrefix=1)何缓。比如http://127.0.0.1:8089/gateway/test ----> http://127.0.0.1:8083/test
  • 超時異常熔斷采用hystrix的SEMAPHORE策略肢础,超時時間為3秒,如果下游服務(wù)不可達(dá)(異常)歌殃,將由fallbackcmd處理乔妈,路由到本地http://127.0.0.1:8089/defaultfallback 處理蝙云。

構(gòu)建defaultfallback處理器

@RestController
public class SelfHystrixController {

    @RequestMapping("/defaultfallback")
    public Map<String,String> defaultfallback(){
        System.out.println("請求被熔斷.");
        Map<String,String> map = new HashMap<>();
        map.put("Code","fail");
        map.put("Message","服務(wù)異常");
        map.put("result","");
        return map;
    }

}

先不構(gòu)建下游服務(wù)氓皱,直接運行網(wǎng)關(guān),訪問地址http://127.0.0.1:8089/gateway/test勃刨,出現(xiàn)如下情況:

2.png

構(gòu)建下游服務(wù)項目波材,該項目為簡單的spring boot web項目,具體配置不詳述身隐,添加服務(wù)類:

@RestController
public class TestController {
    @RequestMapping("/timeout")
    public String timeout(String name) {
        try {
            Thread.sleep(5000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "timeout params:" + name;
    }
}

可以發(fā)現(xiàn)廷区,網(wǎng)關(guān)熔斷策略是超時3秒就熔斷,而下游服務(wù)需要用時5秒+贾铝。運行下游服務(wù)隙轻,繼續(xù)在瀏覽器內(nèi)訪問地址http://127.0.0.1:8089/gateway/timeout,如果正確配置埠帕,3秒后,仍將顯示以上結(jié)果:

3.png

--------------------------------------小總結(jié)------------------------------------------------
可見玖绿,通過簡單配置敛瓷,在服務(wù)不可達(dá)和下游服務(wù)超時的情況下,Spring Cloud Gateway成功進(jìn)行了熔斷斑匪。

限流

擴充網(wǎng)關(guān)項目

pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>

添加基于redis令牌桶機制的限流支持

當(dāng)然網(wǎng)關(guān)還需要配置redis地址呐籽,以本地redis為例:

server:
  redis:
    host: localhost

添加限流鍵參數(shù)

通過該鍵來判斷服務(wù)用戶身份,比如一個客戶端IP為一個用戶蚀瘸,一個usrid為一個用戶狡蝶,添加配置類:

@Configuration
public class RateLimiterConfig {
    @Bean(value = "remoteAddKeyResolver")
    public KeyResolver remoteAddKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }
}

添加限流策略

spring:
  application:
    name: spring-cloud-gateway
  cloud:
    gateway:
      routes:
        - id: service_customer
          #下游服務(wù)地址
          uri: http://127.0.0.1:8083/
          order: 0
          #網(wǎng)關(guān)斷言匹配
          predicates:
            - Path=/gateway/**
          filters:
            #熔斷過濾器
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/defaultfallback
            - StripPrefix=1
            #限流過濾器
            - name: RequestRateLimiter
              args:
                key-resolver: '#{@remoteAddKeyResolver}'
                # 每秒最大訪問次數(shù)(放令牌桶的速率)
                redis-rate-limiter.replenishRate: 10
                # 令牌桶最大容量(令牌桶的大小)
                redis-rate-limiter.burstCapacity: 10

主要是兩個參數(shù)redis-rate-limiter.replenishRate: 10贮勃、redis-rate-limiter.burstCapacity: 10,前者控制往令牌桶丟令牌的速率贪惹,后者標(biāo)識令牌桶的最大容量。
具體令牌桶算法可以參考下圖:

5.jpg

算法描述
假如用戶配置的平均發(fā)送速率為r衙猪,則每隔1/r秒一個令牌被加入到桶中
假設(shè)桶中最多可以存放b個令牌馍乙。如果令牌到達(dá)時令牌桶已經(jīng)滿了,那么這個令牌會被丟棄
當(dāng)流量以速率v進(jìn)入垫释,從桶中以速率v取令牌丝格,拿到令牌的流量通過,拿不到令牌流量不通過棵譬,執(zhí)行熔斷邏輯

當(dāng)然這個只是概念显蝌,具體可以參考令牌桶算法

添加下游正常方法

    @RequestMapping("/hello")
    public String hello(String name) {
        return "hi " + name;
    }

Jmeter壓測

修改限流參數(shù):

                # 每秒最大訪問次數(shù)(放令牌桶的速率)
                redis-rate-limiter.replenishRate: 2
                # 令牌桶最大容量(令牌桶的大小)
                redis-rate-limiter.burstCapacity: 10

配置Jmeter參數(shù):

6.png
7.png

測試結(jié)果

8.png

200次請求订咸,成功返回的大概有14次曼尊,異常請求的返回值為:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Remaining: 0
X-RateLimit-Burst-Capacity: 10
X-RateLimit-Replenish-Rate: 2
content-length: 0

修改限流參數(shù),重新測試

                # 每秒最大訪問次數(shù)(放令牌桶的速率)
                redis-rate-limiter.replenishRate: 20
                # 令牌桶最大容量(令牌桶的大性嗳隆)
                redis-rate-limiter.burstCapacity: 20

查看匯總結(jié)果骆撇,發(fā)現(xiàn)正常返回結(jié)果的數(shù)量明顯變多(100%-26.5%=84%

9.png

限流功能正常!

-------------------------------------------慣例給源碼---------------------------------------------
https://gitee.com/BeautifulHao/Spring-Cloud-Gateway-Demo.git

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末父叙,一起剝皮案震驚了整個濱河市神郊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趾唱,老刑警劉巖涌乳,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異甜癞,居然都是意外死亡夕晓,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門悠咱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蒸辆,“玉大人征炼,你說我怎么就攤上這事」保” “怎么了柒室?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長逗宜。 經(jīng)常有香客問我雄右,道長,這世上最難降的妖魔是什么纺讲? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任擂仍,我火速辦了婚禮,結(jié)果婚禮上熬甚,老公的妹妹穿的比我還像新娘逢渔。我一直安慰自己,他們只是感情好乡括,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布肃廓。 她就那樣靜靜地躺著,像睡著了一般诲泌。 火紅的嫁衣襯著肌膚如雪盲赊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天敷扫,我揣著相機與錄音哀蘑,去河邊找鬼。 笑死葵第,一個胖子當(dāng)著我的面吹牛绘迁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卒密,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼缀台,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哮奇?” 一聲冷哼從身側(cè)響起膛腐,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屏镊,沒想到半個月后依疼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痰腮,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡而芥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了膀值。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棍丐。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡误辑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出歌逢,到底是詐尸還是另有隱情巾钉,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布秘案,位于F島的核電站砰苍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏阱高。R本人自食惡果不足惜赚导,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赤惊。 院中可真熱鬧吼旧,春花似錦、人聲如沸未舟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽裕膀。三九已至员串,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昼扛,已是汗流浹背昵济。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留野揪,地道東北人访忿。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像斯稳,于是被迫代替她去往敵國和親海铆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 背景 在之前的文章中挣惰,我們介紹過微服務(wù)網(wǎng)關(guān)Spring Cloud Netflix Zuul卧斟,前段時間有兩篇文章專...
    aoho閱讀 7,606評論 0 39
  • 在開發(fā)高并發(fā)系統(tǒng)時有三把利器用來保護系統(tǒng):緩存、降級和限流憎茂。緩存的目的是提升系統(tǒng)訪問速度和增大系統(tǒng)能處理的容量珍语,可...
    高級java架構(gòu)師閱讀 692評論 0 5
  • 本文講述基于Redis的限流系統(tǒng)的設(shè)計,主要會談及限流系統(tǒng)中限流策略這個功能的設(shè)計竖幔;在實現(xiàn)方面板乙,算法使用的是令牌桶...
    Java黎先生閱讀 1,325評論 0 18
  • 盼星星,盼月亮終于盼來了,我們期待的胡陳之行募逞。 我們?nèi)w來到胡陳夢鼎培訓(xùn)學(xué)校開展了三天兩夜的挑戰(zhàn)蛋铆。...
    曹大熊閱讀 948評論 0 2
  • 4月3號 星期二 天氣陰轉(zhuǎn)大風(fēng) 親子日記第30天 不知不覺寫親子日記已一個月了,記錄了這一個月當(dāng)中每天...
    syl飄雪閱讀 100評論 0 1