国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 深入學習spring cloud gateway 限流熔斷

深入學習spring cloud gateway 限流熔斷

2021-09-10 12:09coding途中 Java教程

這篇文章主要介紹了深入學習spring cloud gateway 限流熔斷,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

目前,spring cloud gateway是僅次于spring cloud netflix的第二個最受歡迎的spring cloud項目(就github上的星級而言)。它是作為spring cloud系列中zuul代理的繼任者而創建的。該項目提供了用于微服務體系結構的api網關,并基于反應式netty和project reactor構建。它旨在提供一種簡單而有效的方法來路由到api并解決諸如安全性,監視/度量和彈性之類的普遍關注的問題。

基于redis限流

spring cloud gateway為您提供了許多功能和配置選項。今天,我將集中討論網關配置的一個非常有趣的方面-速率限制。速率限制器可以定義為一種控制網絡上發送或接收的流量速率的方法。我們還可以定義幾種類型的速率限制。spring cloud gateway當前提供了一個request rate limiter,它負責將每個用戶每秒限制為n個請求。與spring cloud gateway一起 使用時requestratelimiter,我們可能會利用redis。spring cloud實現使用令牌桶算法做限速。該算法具有集中式存儲桶主機,您可以在其中對每個請求獲取令牌,然后將更多的令牌緩慢滴入存儲桶中。如果存儲桶為空,則拒絕該請求。

項目演示源碼地址:https://github.com/1ssqq1lxr/springcloudgatewaytest

引入maven依賴

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
## spring cloud依賴
<parent>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-parent</artifactid>
   <version>2.2.1.release</version>
</parent>
 
<properties>
   <project.build.sourceencoding>utf-8</project.build.sourceencoding>
   <project.reporting.outputencoding>utf-8</project.reporting.outputencoding>
   <java.version>11</java.version>
   <spring-cloud.version>hoxton.rc2</spring-cloud.version>
</properties>
 
<dependencymanagement>
   <dependencies>
      <dependency>
         <groupid>org.springframework.cloud</groupid>
         <artifactid>spring-cloud-dependencies</artifactid>
         <version>${spring-cloud.version}</version>
         <type>pom</type>
         <scope>import</scope>
      </dependency>
   </dependencies>
</dependencymanagement>
 
## gateway 依賴
<dependency>
   <groupid>org.springframework.cloud</groupid>
   <artifactid>spring-cloud-starter-gateway</artifactid>
</dependency>
<dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-data-redis-reactive</artifactid>
</dependency>
<dependency>
   <groupid>org.projectlombok</groupid>
   <artifactid>lombok</artifactid>
</dependency>
<dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-test</artifactid>
   <scope>test</scope>
</dependency>
<dependency>
   <groupid>org.testcontainers</groupid>
   <artifactid>mockserver</artifactid>
   <version>1.12.3</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupid>org.mock-server</groupid>
   <artifactid>mockserver-client-java</artifactid>
   <version>3.10.8</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupid>com.carrotsearch</groupid>
   <artifactid>junit-benchmarks</artifactid>
   <version>0.7.2</version>
   <scope>test</scope>
</dependency>

限流器配置

使用spring cloud gateway默認請求限流gatewayfilter(org.springframework.cloud.gateway.filter.ratelimit.redisratelimiter)。使用默認的redis限流器方案,你可以通過自定義keyresolver類去決定redis限流key的生成,下面舉常用幾個例子:

根據用戶: 使用這種方式限流,請求路徑中必須攜帶userid參數

?
1
2
3
4
@bean
keyresolver userkeyresolver() {
 return exchange -> mono.just(exchange.getrequest().getqueryparams().getfirst("userid"));
}

根據獲uri

?
1
2
3
4
@bean
keyresolver apikeyresolver() {
 return exchange -> mono.just(exchange.getrequest().getpath().value());
}

由于我們已經討論了spring cloud gateway速率限制的一些理論方面,因此我們可以繼續進行實施。首先,讓我們定義主類和非常簡單的keyresolverbean,它始終等于一個。

?
1
2
3
4
5
6
7
8
9
10
11
12
@springbootapplication
public class gatewayapplication {
 
   public static void main(string[] args) {
      springapplication.run(gatewayapplication.class, args);
   }
 
   @bean
   keyresolver userkeyresolver() {
      return exchange -> mono.just("1");
   }
}

gateway默認使用org.springframework.cloud.gateway.filter.ratelimit.redisratelimiter限流器。 現在,如通過模擬http請求,則會收到以下響應。它包括一些特定的header,其前綴為x-ratelimit。

  • x-ratelimit-burst-capacity:最大令牌值,
  • x-ratelimit-replenish-rate:填充的速率值,
  • x-ratelimit-remaining:剩下可請求數。

yaml配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server:
  port: ${port:8085}
 
spring:
  application:
    name: gateway-service
  redis:
    host: localhost
    port: 6379
  cloud:
    gateway:
      routes:
      - id: account-service
        uri: http://localhost:8091
        predicates:
        - path=/account/**
        filters:
        - rewritepath=/account/(?.*), /$\{path}
      - name: requestratelimiter
          args:
            redis-rate-limiter.replenishrate: 10
            redis-rate-limiter.burstcapacity: 20

redis限流器實現

關鍵源碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// routeid也就是我們的服務路由id,id就是限流的key
public mono<response> isallowed(string routeid, string id) {
 // 會判斷redisratelimiter是否初始化了
 if (!this.initialized.get()) {
  throw new illegalstateexception("redisratelimiter is not initialized");
 }
 // 獲取routeid對應的限流配置
 config routeconfig = getconfig().getordefault(routeid, defaultconfig);
 
 if (routeconfig == null) {
  throw new illegalargumentexception("no configuration found for route " + routeid);
 }
 
 // 允許用戶每秒做多少次請求
 int replenishrate = routeconfig.getreplenishrate();
 
 // 令牌桶的容量,允許在一秒鐘內完成的最大請求數
 int burstcapacity = routeconfig.getburstcapacity();
 
 try {
  // 限流key的名稱(request_rate_limiter.{localhost}.timestamp,request_rate_limiter.{localhost}.tokens)
  list<string> keys = getkeys(id);
 
 
  // the arguments to the lua script. time() returns unixtime in seconds.
  list<string> scriptargs = arrays.aslist(replenishrate + "", burstcapacity + "",
    instant.now().getepochsecond() + "", "1");
  // allowed, tokens_left = redis.eval(script, keys, args)
  // 執行lua腳本
  flux<list<long>> flux = this.redistemplate.execute(this.script, keys, scriptargs);
    // .log("redisratelimiter", level.finer);
  return flux.onerrorresume(throwable -> flux.just(arrays.aslist(1l, -1l)))
    .reduce(new arraylist<long>(), (longs, l) -> {
     longs.addall(l);
     return longs;
    }) .map(results -> {
     boolean allowed = results.get(0) == 1l;
     long tokensleft = results.get(1);
 
     response response = new response(allowed, getheaders(routeconfig, tokensleft));
 
     if (log.isdebugenabled()) {
      log.debug("response: " + response);
     }
     return response;
    });
 }
 catch (exception e) {
  log.error("error determining if user allowed from redis", e);
 }
 return mono.just(new response(true, getheaders(routeconfig, -1l)));
}

測試redis限流器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@springboottest(webenvironment = springboottest.webenvironment.defined_port)
@runwith(springrunner.class)
public class gatewayratelimitertest {
 
    private static final logger logger = loggerfactory.getlogger(gatewayratelimitertest.class);
 
    @rule
    public testrule benchmarkrun = new benchmarkrule();
 
    @classrule
    public static mockservercontainer mockserver = new mockservercontainer();
    @classrule
    public static genericcontainer redis = new genericcontainer("redis:5.0.6").withexposedports(6379);
 
    @autowired
    testresttemplate template;
 
    @beforeclass
    public static void init() {
 
        system.setproperty("spring.cloud.gateway.routes[0].id", "account-service");
        system.setproperty("spring.cloud.gateway.routes[0].uri", "http://localhost:" + mockserver.getserverport());
        system.setproperty("spring.cloud.gateway.routes[0].predicates[0]", "path=/account/**");
        system.setproperty("spring.cloud.gateway.routes[0].filters[0]", "rewritepath=/account/(?<path>.*), /$\\{path}");
        system.setproperty("spring.cloud.gateway.routes[0].filters[1].name", "requestratelimiter");
        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.redis-rate-limiter.replenishrate", "10");
        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.redis-rate-limiter.burstcapacity", "20");
        system.setproperty("spring.redis.host", "localhost");
        system.setproperty("spring.redis.port", "" + redis.getmappedport(6379));
        new mockserverclient(mockserver.getcontaineripaddress(), mockserver.getserverport())
                .when(httprequest.request()
                        .withpath("/1"))
                .respond(response()
                        .withbody("{\"id\":1,\"number\":\"1234567890\"}")
                        .withheader("content-type", "application/json"));
    }
 
    @test
    @benchmarkoptions(warmuprounds = 0, concurrency = 6, benchmarkrounds = 600)
    public void testaccountservice() {
        responseentity<account> r = template.exchange("/account/{id}", httpmethod.get, null, account.class, 1);
        logger.info("received: status->{}, payload->{}, remaining->{}", r.getstatuscodevalue(), r.getbody(), r.getheaders().get("x-ratelimit-remaining"));
//  assert.assertequals(200, r.getstatuscodevalue());
//  assert.assertnotnull(r.getbody());
//  assert.assertequals(integer.valueof(1), r.getbody().getid());
//  assert.assertequals("1234567890", r.getbody().getnumber());
    }
}

執行test類: 發現超過20之后會被攔截返回429,運行過程中隨著令牌的放入會不斷有請求成功。

14:20:32.242 --- [pool-2-thread-1] : received: status->200, payload->account(id=1, number=1234567890), remaining->[18]
14:20:32.242 --- [pool-2-thread-4] : received: status->200, payload->account(id=1, number=1234567890), remaining->[16]
14:20:32.242 --- [pool-2-thread-2] : received: status->200, payload->account(id=1, number=1234567890), remaining->[14]
14:20:32.242 --- [pool-2-thread-3] : received: status->200, payload->account(id=1, number=1234567890), remaining->[15]
14:20:32.242 --- [pool-2-thread-6] : received: status->200, payload->account(id=1, number=1234567890), remaining->[17]
14:20:32.242 --- [pool-2-thread-5] : received: status->200, payload->account(id=1, number=1234567890), remaining->[19]
14:20:32.294 --- [pool-2-thread-4] : received: status->200, payload->account(id=1, number=1234567890), remaining->[15]
14:20:32.297 --- [pool-2-thread-6] : received: status->200, payload->account(id=1, number=1234567890), remaining->[19]
14:20:32.304 --- [pool-2-thread-3] : received: status->200, payload->account(id=1, number=1234567890), remaining->[18]
14:20:32.308 --- [pool-2-thread-5] : received: status->200, payload->account(id=1, number=1234567890), remaining->[16]
14:20:32.309 --- [pool-2-thread-1] : received: status->200, payload->account(id=1, number=1234567890), remaining->[17]
14:20:32.312 --- [pool-2-thread-2] : received: status->200, payload->account(id=1, number=1234567890), remaining->[14]
14:20:32.320 --- [pool-2-thread-4] : received: status->200, payload->account(id=1, number=1234567890), remaining->[13]
14:20:32.326 --- [pool-2-thread-6] : received: status->200, payload->account(id=1, number=1234567890), remaining->[12]
14:20:32.356 --- [pool-2-thread-4] : received: status->200, payload->account(id=1, number=1234567890), remaining->[7]
14:20:32.356 --- [pool-2-thread-5] : received: status->200, payload->account(id=1, number=1234567890), remaining->[10]
14:20:32.361 --- [pool-2-thread-6] : received: status->200, payload->account(id=1, number=1234567890), remaining->[6]
14:20:32.363 --- [pool-2-thread-2] : received: status->200, payload->account(id=1, number=1234567890), remaining->[8]
14:20:32.384 --- [pool-2-thread-5] : received: status->200, payload->account(id=1, number=1234567890), remaining->[4]
14:20:32.384 --- [pool-2-thread-3] : received: status->200, payload->account(id=1, number=1234567890), remaining->[11]
14:20:32.386 --- [pool-2-thread-4] : received: status->200, payload->account(id=1, number=1234567890), remaining->[5]
14:20:32.390 --- [pool-2-thread-1] : received: status->200, payload->account(id=1, number=1234567890), remaining->[9]
14:20:32.391 --- [pool-2-thread-6] : received: status->200, payload->account(id=1, number=1234567890), remaining->[3]
14:20:32.392 --- [pool-2-thread-2] : received: status->200, payload->account(id=1, number=1234567890), remaining->[2]
14:20:32.403 --- [pool-2-thread-6] : received: status->429, payload->null, remaining->[0]
14:20:32.403 --- [pool-2-thread-4] : received: status->429, payload->null, remaining->[0]
........
14:20:33.029 --- [pool-2-thread-2] : received: status->200, payload->account(id=1, number=1234567890), remaining->[9]
14:20:33.033 --- [pool-2-thread-1] : received: status->200, payload->account(id=1, number=1234567890), remaining->[8]
14:20:33.033 --- [pool-2-thread-4] : received: status->200, payload->account(id=1, number=1234567890), remaining->[7]
14:20:33.037 --- [pool-2-thread-3] : received: status->200, payload->account(id=1, number=1234567890), remaining->[6]
14:20:33.039 --- [pool-2-thread-5] : received: status->200, payload->account(id=1, number=1234567890), remaining->[5]
14:20:33.046 --- [pool-2-thread-6] : received: status->200, payload->account(id=1, number=1234567890), remaining->[4]
14:20:33.052 --- [pool-2-thread-5] : received: status->429, payload->null, remaining->[0]
14:20:33.058 --- [pool-2-thread-6] : received: status->429, payload->null, remaining->[0]
14:20:33.058 --- [pool-2-thread-1] : received: status->200, payload->account(id=1, number=1234567890), remaining->[2]
14:20:33.060 --- [pool-2-thread-5] : received: status->429, payload->null, remaining->[0]
14:20:33.081 --- [pool-2-thread-4] : received: status->200, payload->account(id=1, number=1234567890), remaining->[1]
14:20:33.082 --- [pool-2-thread-3] : received: status->200, payload->account(id=1, number=1234567890), remaining->[0]
14:20:33.084 --- [pool-2-thread-2] : received: status->200, payload->account(id=1, number=1234567890), remaining->[3]
14:20:33.088 --- [pool-2-thread-5] : received: status->429, payload->null, remaining->[0]
如果默認的限流器不能夠滿足使用,可以通過繼承abstractratelimiter實現自定義限流器,然后通過routelocator方式去注入攔截器。

resilience4j熔斷器

引入依賴

?
1
2
3
4
5
6
7
8
<dependency>
   <groupid>org.springframework.cloud</groupid>
   <artifactid>spring-cloud-starter-gateway</artifactid>
</dependency>
<dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactid>
</dependency>

resilience4j 斷路器介紹

三個一般性狀態

  • closed:關閉狀態,放過所有請求,記錄請求狀態。
  • open:打開,異常請求達到閥值數量時,開啟熔斷,拒絕所有請求。
  • half_open:半開,放開一定數量的請求,重新計算錯誤率。

兩個特定狀態

  • disabled:禁用
  • forced_open:強開

狀態之間轉換

啟動時斷路器為close狀態,在達到一定請求量至后計算請求失敗率,達到或高于指定失敗率后,斷路進入open狀態,阻攔所有請求,開啟一段時間(自定義)時間后,斷路器變為halfopen狀態,重新計算請求失敗率。halfopen錯誤率低于指定失敗率后,斷路進入close狀態,否則進入open狀態。

深入學習spring cloud gateway 限流熔斷

狀態轉換

通過resilience4j啟用spring cloud gateway斷路器

要啟用構建在resilience4j之上的斷路器,我們需要聲明一個customizer傳遞了的bean reactiveresilience4jcircuitbreakerfactory。可以非常簡單地去配置設置,下面使用默認配置進行測試

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@bean
public customizer<reactiveresilience4jcircuitbreakerfactory> defaultcustomizer() {
   return factory -> factory.configuredefault(id -> new resilience4jconfigbuilder(id)
      .circuitbreakerconfig(circuitbreakerconfig.custom()
          //統計失敗率的請求總數
         .slidingwindowsize(5)
         //在半開狀態下請求的次數
         .permittednumberofcallsinhalfopenstate(5)
         //斷路器打開的成功率
         .failureratethreshold(50.0f)
         //斷路器打開的周期
         .waitdurationinopenstate(duration.ofmillis(30))
         //屬于慢請求的周期
         .slowcalldurationthreshold(duration.ofmillis(200))
        //慢請求打開斷路器的成功率
         .slowcallratethreshold(50.0f)
         .build())
      .timelimiterconfig(timelimiterconfig.custom().timeoutduration(duration.ofmillis(200)).build()).build());
}

測試resilience4j斷路器

使用默認配置進行測試

?
1
2
3
4
5
6
7
8
9
10
@bean
public customizer<reactiveresilience4jcircuitbreakerfactory> defaultcustomizer() {
    return factory -> factory.configuredefault(id -> new resilience4jconfigbuilder(id)
.circuitbreakerconfig(circuitbreakerconfig.ofdefaults())
            .circuitbreakerconfig(circuitbreakerconfig.custom()
                    .slowcalldurationthreshold(duration.ofmillis(200))
                    .build())
            .timelimiterconfig(timelimiterconfig.custom().timeoutduration(duration.ofmillis(200)).build())
            .build());
}

執行下面test用例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@springboottest(webenvironment = springboottest.webenvironment.defined_port)
@runwith(springrunner.class)
public class gatewaycircuitbreakertest {
 
 
    private static final logger logger = loggerfactory.getlogger(gatewayratelimitertest.class);
 
    @rule
    public testrule benchmarkrun = new benchmarkrule();
 
    @classrule
    public static mockservercontainer mockserver = new mockservercontainer();
 
    @autowired
    testresttemplate template;
    final random random = new random();
    int i = 0;
 
    @beforeclass
    public static void init() {
        system.setproperty("logging.level.org.springframework.cloud.gateway.filter.factory", "trace");
        system.setproperty("spring.cloud.gateway.routes[0].id", "account-service");
        system.setproperty("spring.cloud.gateway.routes[0].uri", "http://localhost:" + mockserver.getserverport());
        system.setproperty("spring.cloud.gateway.routes[0].predicates[0]", "path=/account/**");
        system.setproperty("spring.cloud.gateway.routes[0].filters[0]", "rewritepath=/account/(?<path>.*), /$\\{path}");
        system.setproperty("spring.cloud.gateway.routes[0].filters[1].name", "circuitbreaker");
        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.name", "exampleslowcircuitbreaker");
//        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.slowcalldurationthreshold", "100");
//        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.slowcallratethreshold", "9.0f");
//        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.fallbackuri", "forward:/fallback/account");
        mockserverclient client = new mockserverclient(mockserver.getcontaineripaddress(), mockserver.getserverport());
        client.when(httprequest.request()
                .withpath("/1"))
                .respond(response()
                        .withbody("{\"id\":1,\"number\":\"1234567890\"}")
                        .withheader("content-type", "application/json"));
//        client.when(httprequest.request()
//                .withpath("/2"), times.exactly(3))
//    .respond(response()
//                        .withbody("{\"id\":2,\"number\":\"1\"}")
//                        .withdelay(timeunit.seconds, 1000)
//                        .withheader("content-type", "application/json"));
        client.when(httprequest.request()
                .withpath("/2"))
                .respond(response()
                        .withbody("{\"id\":2,\"number\":\"1234567891\"}")
                        .withdelay(timeunit.seconds, 200)
                        .withheader("content-type", "application/json"));
    }
 
    @test
    @benchmarkoptions(warmuprounds = 0, concurrency = 1, benchmarkrounds = 600)
    public void testaccountservice() {
        int gen = 1 + (i++ % 2);
        responseentity<account> r = template.exchange("/account/{id}", httpmethod.get, null, account.class, gen);
        logger.info("{}. received: status->{}, payload->{}, call->{}", i, r.getstatuscodevalue(), r.getbody(), gen);
    }
}

請求日志如下:當請求達到100次時候,此時失敗率為50% 這時候系統開啟斷路器返回503!

20:07:29.281 --- [pool-2-thread-1] : 91. received: status->200, payload->account(id=1, number=1234567890), call->1
20:07:30.297 --- [pool-2-thread-1] : 92. received: status->504, payload->account(id=null, number=null), call->2
20:07:30.316 --- [pool-2-thread-1] : 93. received: status->200, payload->account(id=1, number=1234567890), call->1
20:07:31.328 --- [pool-2-thread-1] : 94. received: status->504, payload->account(id=null, number=null), call->2
20:07:31.345 --- [pool-2-thread-1] : 95. received: status->200, payload->account(id=1, number=1234567890), call->1
20:07:32.359 --- [pool-2-thread-1] : 96. received: status->504, payload->account(id=null, number=null), call->2
20:07:32.385 --- [pool-2-thread-1] : 97. received: status->200, payload->account(id=1, number=1234567890), call->1
20:07:33.400 --- [pool-2-thread-1] : 98. received: status->504, payload->account(id=null, number=null), call->2
20:07:33.414 --- [pool-2-thread-1] : 99. received: status->200, payload->account(id=1, number=1234567890), call->1
20:07:34.509 --- [pool-2-thread-1] : 100. received: status->504, payload->account(id=null, number=null), call->2
20:07:34.525 --- [pool-2-thread-1] : 101. received: status->503, payload->account(id=null, number=null), call->1
20:07:34.533 --- [pool-2-thread-1] : 102. received: status->503, payload->account(id=null, number=null), call->2
20:07:34.539 --- [pool-2-thread-1] : 103. received: status->503, payload->account(id=null, number=null), call->1
20:07:34.545 --- [pool-2-thread-1] : 104. received: status->503, payload->account(id=null, number=null), call->2
20:07:34.552 --- [pool-2-thread-1] : 105. received: status->503, payload->account(id=null, number=null), call->1
20:07:34.566 --- [pool-2-thread-1] : 106. received: status->503, payload->account(id=null, number=null), call->2
20:07:34.572 --- [pool-2-thread-1] : 107. received: status->503, payload->account(id=null, number=null), call->1
20:07:34.576 --- [pool-2-thread-1] : 108. received: status->503, payload->account(id=null, number=null), call->2
20:07:34.580 --- [pool-2-thread-1] : 109. received: status->503, payload->account(id=null, number=null), call->1
20:07:34.586 --- [pool-2-thread-1] : 110. received: status->503, payload->account(id=null, number=null), call->2
20:07:34.591 --- [pool-2-thread-1] : 111. received: status->503, payload->account(id=null, number=null), call->1

這時候我們修改下配置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
     @beforeclass
    public static void init() {
        system.setproperty("logging.level.org.springframework.cloud.gateway.filter.factory", "trace");
        system.setproperty("spring.cloud.gateway.routes[0].id", "account-service");
        system.setproperty("spring.cloud.gateway.routes[0].uri", "http://localhost:" + mockserver.getserverport());
        system.setproperty("spring.cloud.gateway.routes[0].predicates[0]", "path=/account/**");
        system.setproperty("spring.cloud.gateway.routes[0].filters[0]", "rewritepath=/account/(?<path>.*), /$\\{path}");
        system.setproperty("spring.cloud.gateway.routes[0].filters[1].name", "circuitbreaker");
        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.name", "exampleslowcircuitbreaker");
//        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.slowcalldurationthreshold", "100");
//        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.slowcallratethreshold", "9.0f");
        system.setproperty("spring.cloud.gateway.routes[0].filters[1].args.fallbackuri", "forward:/fallback/account");
        mockserverclient client = new mockserverclient(mockserver.getcontaineripaddress(), mockserver.getserverport());
        client.when(httprequest.request()
                .withpath("/1"))
                .respond(response()
                        .withbody("{\"id\":1,\"number\":\"1234567890\"}")
                        .withheader("content-type", "application/json"));
        client.when(httprequest.request()
                .withpath("/2"), times.exactly(3))
    .respond(response()
                        .withbody("{\"id\":2,\"number\":\"1\"}")
                        .withdelay(timeunit.seconds, 1000)
                        .withheader("content-type", "application/json"));
        client.when(httprequest.request()
                .withpath("/2"))
                .respond(response()
                        .withbody("{\"id\":2,\"number\":\"1234567891\"}")
//                        .withdelay(timeunit.seconds, 200)
                        .withheader("content-type", "application/json"));
    }

新建一個回調接口,用于斷路器打開后請求的地址。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@restcontroller
@requestmapping("/fallback")
public class gatewayfallback {
 
    @getmapping("/account")
    public account getaccount() {
        account a = new account();
        a.setid(2);
        a.setnumber("123456");
        return a;
    }
 
}

使用默認設置時,前3次請求觸發斷路器回調,后面正常請求成功

20:20:23.529 --- [pool-2-thread-1] : 1. received: status->200, payload->account(id=1, number=1234567890), call->1
20:20:23.777 --- [pool-2-thread-1] : 2. received: status->200, payload->account(id=2, number=123456), call->2
20:20:23.808 --- [pool-2-thread-1] : 3. received: status->200, payload->account(id=1, number=1234567890), call->1
20:20:24.018 --- [pool-2-thread-1] : 4. received: status->200, payload->account(id=2, number=123456), call->2
20:20:24.052 --- [pool-2-thread-1] : 5. received: status->200, payload->account(id=1, number=1234567890), call->1
20:20:24.268 --- [pool-2-thread-1] : 6. received: status->200, payload->account(id=2, number=123456), call->2
20:20:24.301 --- [pool-2-thread-1] : 7. received: status->200, payload->account(id=1, number=1234567890), call->1
20:20:24.317 --- [pool-2-thread-1] : 8. received: status->200, payload->account(id=2, number=1234567891), call->2
20:20:24.346 --- [pool-2-thread-1] : 9. received: status->200, payload->account(id=1, number=1234567890), call->1
20:20:24.363 --- [pool-2-thread-1] : 10. received: status->200, payload->account(id=2, number=1234567891), call->2
20:20:24.378 --- [pool-2-thread-1] : 11. received: status->200, payload->account(id=1, number=1234567890), call->1
20:20:24.392 --- [pool-2-thread-1] : 12. received: status->200, payload->account(id=2, number=1234567891), call->2
20:20:24.402 --- [pool-2-thread-1] : 13. received: status->200, payload->account(id=1, number=1234567890), call->1

至此給大家介紹了spring cloud gateway中斷路器跟限流器使用。更多相關spring cloud gateway 限流熔斷內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/1ssqq1lxr/p/14680663.html

延伸 · 閱讀

精彩推薦
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7472021-02-04
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
主站蜘蛛池模板: 日本激情网 | 亚洲电影免费 | 国产视频一区二区在线 | 亚洲高清视频在线观看 | 天天澡天天狠天天天做 | 中文字幕在线观看av | 亚洲免费片| 亚洲精品国偷拍自产在线观看 | 黑人精品欧美一区二区蜜桃 | www.麻豆av| 春色导航 | 一区二区不卡 | 欧美成人激情视频 | 一区二区在线看 | 99精品热视频 | 精品久久av| 精品久久久久久亚洲综合网 | 国产a视频 | 韩国精品免费视频 | 久久夜色精品国产 | 久久久久久久97 | 亚洲电影在线 | 91精品在线播放 | 在线不卡一区 | 欧美日韩精品电影 | 超级碰在线视频 | 国产视频一区二区在线 | 久久国产精品偷 | 国产精品久久久久久亚洲调教 | 国产成人高清视频 | 日本精品一区二区三区在线观看视频 | 成年网站视频 | 日韩一区中文字幕 | 69中文字幕 | 日本一区二区三区四区 | 红桃成人少妇网站 | 午夜看片| 亚洲欧美日韩精品久久亚洲区 | 中文字幕观看 | 欧美视频精品 | 精品久|