详解Spring Cloud Netflix Zuul中的速率限制

2025-05-29 0 59

spring cloud netflix zuul是一个包含netflix zuul的 开源网关。它为spring boot应用程序添加了一些特定功能。不幸的是,开箱即用不提供速率限制

除了spring cloud netflix zuul依赖项之外,我们还需要将spring cloud zuul ratelimit 添加到我们的应用程序的pom.xml中:

?

1

2

3

4

5

6

7

8

9
<dependency>

<groupid>org.springframework.cloud</groupid>

<artifactid>spring-cloud-starter-netflix-zuul</artifactid>

</dependency>

<dependency>

<groupid>com.marcosbarbero.cloud</groupid>

<artifactid>spring-cloud-zuul-ratelimit</artifactid>

<version>2.2.0.release</version>

</dependency>

首先,让我们创建几个rest端点,我们将在其上应用速率限制

下面是一个简单的spring controller类,有两个端点:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14
@controller

@requestmapping("/greeting")

public class greetingcontroller {

@getmapping("/simple")

public responseentity<string> getsimple() {

return responseentity.ok("hi!");

}

@getmapping("/advanced")

public responseentity<string> getadvanced() {

return responseentity.ok("hello, how you doing?");

}

}

让我们在application.yml文件中添加以下zuul属性 :

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23
zuul:

routes:

servicesimple:

path: /greeting/simple

url: forward:/

serviceadvanced:

path: /greeting/advanced

url: forward:/

ratelimit:

enabled: true

repository: jpa

policy-list:

servicesimple:

- limit: 5

refresh-interval: 60

type:

- origin

serviceadvanced:

- limit: 1

refresh-interval: 2

type:

- origin

strip-prefix: true

在zuul.routes下,我们提供端点详细信息。在zuul.ratelimit.policy-list下,我们为端点提供速率限制配置。该限属性指定的时间端点可以在内部被称为数字刷新间隔。

我们可以看到,我们为servicesimple 端点添加了每60秒5个请求的速率限制。相比之下, serviceadvanced的速率限制为每2秒1个请求。

该类型配置指定其速率限制的方法,以下是可能的值:

  • origin – 基于用户原始请求的速率限制
  • url – 基于下游服务的请求路径的速率限制
  • user – 基于经过身份验证的用户名或“匿名”的速率限制
  • no value – 充当每项服务的全局配置。要使用这种方法,请不要设置参数'type'

接下来,让我们测试一下速率限制

?

1

2

3

4

5

6

7

8

9

10

11

12
@test

public void whenrequestnotexceedingcapacity_thenreturnokresponse() {

responseentity<string> response = resttemplate.getforentity(simple_greeting, string.class);

assertequals(ok, response.getstatuscode());

httpheaders headers = response.getheaders();

string key = "rate-limit-application_servicesimple_127.0.0.1";

assertequals("5", headers.getfirst(header_limit + key));

assertequals("4", headers.getfirst(header_remaining + key));

assertequals("60000", headers.getfirst(header_reset + key));

}

在这里,我们只对一个端点/ greeting / simple进行一次调用。请求成功,因为它在速率限制内。

另一个关键点是,对于每个响应,我们返回标头header,为我们提供有关速率限制的更多信息。对于上述请求,我们将获得以下标头:

?

1

2

3

4

5
x-ratelimit-limit-rate-limit-application_servicesimple_127.0.0.1: 5

x-ratelimit-remaining-rate-limit-application_servicesimple_127.0.0.1: 4

x-ratelimit-reset-rate-limit-application_servicesimple_127.0.0.1: 60000

解释:

  • x-ratelimit-limit- [key]:为端点配置 的限制
  • x-ratelimit-remaining- [key]: 调用端点的剩余尝试次数
  • x-ratelimit-reset- [key]:为端点配置 的刷新间隔的剩余毫秒数

另外,如果我们再次立即触发相同的端点,我们可以得到:

?

1

2

3

4

5
x-ratelimit-limit-rate-limit-application_servicesimple_127.0.0.1: 5

x-ratelimit-remaining-rate-limit-application_servicesimple_127.0.0.1: 3

x-ratelimit-reset-rate-limit-application_servicesimple_127.0.0.1: 57031

请注意减少的剩余尝试次数和剩余的毫秒数。

让我们看看当我们超过速率限制时会发生什么:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23
@test

public void whenrequestexceedingcapacity_thenreturntoomanyrequestsresponse() throws interruptedexception {

responseentity<string> response = this.resttemplate.getforentity(advanced_greeting, string.class);

assertequals(ok, response.getstatuscode());

for (int i = 0; i < 2; i++) {

response = this.resttemplate.getforentity(advanced_greeting, string.class);

}

assertequals(too_many_requests, response.getstatuscode());

httpheaders headers = response.getheaders();

string key = "rate-limit-application_serviceadvanced_127.0.0.1";

assertequals("1", headers.getfirst(header_limit + key));

assertequals("0", headers.getfirst(header_remaining + key));

assertnotequals("2000", headers.getfirst(header_reset + key));

timeunit.seconds.sleep(2);

response = this.resttemplate.getforentity(advanced_greeting, string.class);

assertequals(ok, response.getstatuscode());

}

在这里,我们快速连续两次调用,由于我们已将速率限制配置为每2秒一个请求,因此第二个调用将失败。结果,错误代码429(too many requests)返回给客户端。以下是达到速率限制时返回的标头:

?

1

2

3

4

5
x-ratelimit-limit-rate-limit-application_serviceadvanced_127.0.0.1: 1

x-ratelimit-remaining-rate-limit-application_serviceadvanced_127.0.0.1: 0

x-ratelimit-reset-rate-limit-application_serviceadvanced_127.0.0.1: 268

之后,我们休息了2秒钟。这是为端点配置的刷新间隔。最后,我们再次触发端点并获得成功的响应。

自定义密钥生成器

我们可以使用自定义密钥生成器自定义响应头中发送的密钥。这很有用,因为应用程序可能需要控制除type属性提供的选项之外的密钥策略。

例如,这可以通过创建自定义的ratelimitkeygenerator实现类来完成。我们可以添加更多的限定符或完全不同的东西:

?

1

2

3

4

5

6

7

8

9

10

11
@bean

public ratelimitkeygenerator ratelimitkeygenerator(ratelimitproperties properties,

ratelimitutils ratelimitutils) {

return new defaultratelimitkeygenerator(properties, ratelimitutils) {

@override

public string key(httpservletrequest request, route route,

ratelimitproperties.policy policy) {

return super.key(request, route, policy) + "_" + request.getmethod();

}

};

}

上面的代码将rest方法名称附加到键。例如:

?

1
x-ratelimit-limit-rate-limit-application_servicesimple_127.0.0.1_get: 5

另一个关键点是 ratelimitkeygenerator bean将由spring-cloud-zuul-ratelimit自动配置。

自定义错误处理

该框架支持速率限制数据存储的各种实现。例如,提供了spring data jpa和redis。默认情况下,使用defaultratelimitererrorhandler 类将故障记录为错误。

当我们需要以不同方式处理错误时,我们可以定义一个自定义的ratelimitererrorhandler bean:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19
@bean

public ratelimitererrorhandler ratelimiterrorhandler() {

return new defaultratelimitererrorhandler() {

@override

public void handlesaveerror(string key, exception e) {

<i>// implementation</i>

}

@override

public void handlefetcherror(string key, exception e) {

<i>// implementation</i>

}

@override

public void handleerror(string msg, exception e) {

<i>// implementation</i>

}

};

}

与ratelimitkeygenerator bean 类似 ,也将自动配置ratelimitererrorhandler bean。

在github上 找到本文的完整代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

原文链接:https://www.jdon.com/50654

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 详解Spring Cloud Netflix Zuul中的速率限制 https://www.kuaiidc.com/110563.html

相关文章

发表评论
暂无评论