Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cluster key rate limit enhancement #1036

Merged
merged 18 commits into from
Jun 17, 2024

Conversation

hanxiantao
Copy link
Collaborator

@hanxiantao hanxiantao commented Jun 13, 2024

Ⅰ. Describe what this PR did

cluster key rate limit enhancement
1)add limit_type: limit_by_consumer、limit_by_cookie、limit_by_per_header、limit_by_per_param、limit_by_per_consumer、limit_by_per_cookie
2)support batch configuration of rate limiting rules

Ⅱ. Does this pull request fix one issue?

Ⅲ. Why don't you add test cases (unit test/integration test)?

Ⅳ. Describe how to verify it

1)、limit_by_param和limit_by_per_param

wasmplugin.yam:

apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
  name: test
  namespace: higress-system
spec:
  defaultConfig:
    rule_name: default_rule
    rule_items:
      - limit_by_param: apikey
        limit_keys:
          - key: 9a342114-ba8a-11ec-b1bf-00163e1250b5
            query_per_minute: 10
          - key: a6a6d7f2-ba8a-11ec-bec2-00163e1250b5
            query_per_hour: 100
      - limit_by_per_param: apikey
        limit_keys:
          # 正则表达式,匹配以a开头的所有字符串,每个apikey对应的请求10qds
          - key: "regexp:^a.*"
            query_per_second: 10
          # 正则表达式,匹配以b开头的所有字符串,每个apikey对应的请求100qd
          - key: "regexp:^b.*"
            query_per_minute: 100
          # 兜底用,匹配所有请求,每个apikey对应的请求1000qdh
          - key: "*"
            query_per_hour: 1000
    redis:
      service_name: redis.static
    show_limit_quota_header: true
  url: oci://registry.cn-hangzhou.aliyuncs.com/wasm-plugin/wasm-plugin:0.0.68
  imagePullSecret: aliyun

1)根据第一个apikey进行限流

一分钟内请求三次:

curl -kvv -X GET 'http://localhost:8082/test?apikey=9a342114-ba8a-11ec-b1bf-00163e1250b5' \
-H 'Host: www.test.com'

根据第一个apikey进行限流

响应头中x-ratelimit-limit为10(限制的总请求数),x-ratelimit-remaining为7(剩余还可以发送的请求数)

2)根据第二个apikey限流

请求三次:

curl -kvv -X GET 'http://localhost:8082/test?apikey=a6a6d7f2-ba8a-11ec-bec2-00163e1250b5' \
-H 'Host: www.test.com'

根据第二个apikey限流

Redis中的数据:
根据第二个apikey限流Redis中的数据

3)正则表达式以b开头的字符串

一分钟内请求三次:

curl -kvv -X GET 'http://localhost:8082/test?apikey=b123456' \
-H 'Host: www.test.com'

正则表达式以b开头的字符串

响应头中x-ratelimit-limit为100(限制的总请求数),x-ratelimit-remaining为97(剩余还可以发送的请求数)s

4)*

请求四次:

curl -kvv -X GET 'http://localhost:8082/test?apikey=123456' \
-H 'Host: www.test.com'

All请求三次

Redis中的数据:
All请求三次Redis中的数据

2)、limit_by_header和limit_by_per_header

wasmplugin.yam:

apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
  name: test
  namespace: higress-system
spec:
  defaultConfig:
    rule_name: default_rule
    rule_items:
      - limit_by_header: x-ca-key
        limit_keys:
          - key: 102234
            query_per_minute: 10
          - key: 308239
            query_per_hour: 10
      - limit_by_per_header: x-ca-key
        limit_keys:
          # 正则表达式,匹配以a开头的所有字符串,每个apikey对应的请求10qds
          - key: "regexp:^a.*"
            query_per_second: 10
          # 正则表达式,匹配以b开头的所有字符串,每个apikey对应的请求100qd
          - key: "regexp:^b.*"
            query_per_minute: 100
          # 兜底用,匹配所有请求,每个apikey对应的请求1000qdh
          - key: "*"
            query_per_hour: 1000            
    redis:
      service_name: redis.static
    show_limit_quota_header: true  
  url: oci://registry.cn-hangzhou.aliyuncs.com/wasm-plugin/wasm-plugin:0.0.68
  imagePullSecret: aliyun

1)根据第一个请求头进行限流

一分钟内请求三次:

curl -kvv -X GET 'http://localhost:8082/test' -H 'x-ca-key: 102234' -H 'Host: www.test.com'

根据第一个请求头进行限流

响应头中x-ratelimit-limit为10(限制的总请求数),x-ratelimit-remaining为7(剩余还可以发送的请求数)

2)根据第二个请求头进行限流

请求三次:

curl -kvv -X GET 'http://localhost:8082/test' -H 'x-ca-key: 308239' -H 'Host: www.test.com'

根据第二个请求头进行限流

Redis中的数据:

根据第二个请求头进行限流Redis中的数据

3)正则表达式以b开头的字符串

一分钟内请求三次:

curl -kvv -X GET 'http://localhost:8082/test' -H 'x-ca-key: b123456' -H 'Host: www.test.com'

正则表达式以b开头的字符串

响应头中x-ratelimit-limit为100(限制的总请求数),x-ratelimit-remaining为97(剩余还可以发送的请求数)s

4)*

请求三次:

curl -kvv -X GET 'http://localhost:8082/test' -H 'x-ca-key: 123456' -H 'Host: www.test.com'

All请求三次

Redis中的数据:

All请求三次Redis中的数据

3)、limit_by_cookie和limit_by_per_cookie

wasmplugin.yam:

apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
  name: test
  namespace: higress-system
spec:
  defaultConfig:
    rule_name: default_rule
    rule_items:
      - limit_by_cookie: key1
        limit_keys:
          - key: value1
            query_per_minute: 10
          - key: value2
            query_per_hour: 100
      - limit_by_per_cookie: key1
        limit_keys:
          # 正则表达式,匹配以a开头的所有字符串,每个cookie中的value对应的请求10qds
          - key: "regexp:^a.*"
            query_per_second: 10
          # 正则表达式,匹配以b开头的所有字符串,每个cookie中的value对应的请求100qd
          - key: "regexp:^b.*"
            query_per_minute: 100
          # 兜底用,匹配所有请求,每个cookie中的value对应的请求1000qdh
          - key: "*"
            query_per_hour: 1000 
    rejected_code: 200
    rejected_msg: '{"code":-1,"msg":"Too many requests"}'
    redis:
      service_name: redis.static
    show_limit_quota_header: true  
  url: oci://registry.cn-hangzhou.aliyuncs.com/wasm-plugin/wasm-plugin:0.0.68
  imagePullSecret: aliyun

1)根据第一个cookie进行限流

一分钟内请求三次:

curl -kvv -X GET 'http://localhost:8082/test' -H 'Host: www.test.com' -H 'Cookie: test=www.test.com;key1=value1'

根据第一个cookie进行限流

响应头中x-ratelimit-limit为10(限制的总请求数),x-ratelimit-remaining为7(剩余还可以发送的请求数)

触发限流后:

根据第一个cookie进行限流触发限流后

2)根据第二个cookie限流

请求三次:

curl -kvv -X GET 'http://localhost:8082/test' -H 'Host: www.test.com' -H 'Cookie: test=www.test.com;key2=value1;key1=value2'

根据第二个cookie限流

Redis中的数据:

根据第二个cookie限流Redis中的数据

3)正则表达式以b开头的字符串

一分钟内请求三次:

curl -kvv -X GET 'http://localhost:8082/test' -H 'Host: www.test.com' -H 'Cookie: test=www.test.com;key2=value1;key1=bbbb'

正则表达式以b开头的字符串

响应头中x-ratelimit-limit为100(限制的总请求数),x-ratelimit-remaining为97(剩余还可以发送的请求数)

4)*

请求三次:

curl -kvv -X GET 'http://localhost:8082/test' -H 'Host: www.test.com' -H 'Cookie: test=www.test.com;key2=value1;key1=helloworld'

All请求三次

Redis中的数据:

All请求三次Redis中的数据

4)、limit_by_per_ip

wasmplugin.yam:

apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
  name: test
  namespace: higress-system
spec:
  defaultConfig:
    rule_name: default_rule
    rule_items:
      - limit_by_per_ip: from-header-x-forwarded-for
        limit_keys:
          # 精确ip
          - key: 1.1.1.1
            query_per_day: 10
          # ip段,符合这个ip段的ip,每个ip 100qpd
          - key: 1.1.1.0/24
            query_per_day: 100
          # 兜底用,即默认每个ip 1000qpd
          - key: 0.0.0.0/0
            query_per_day: 1000
    redis:
      service_name: redis.static
    show_limit_quota_header: true    
  url: oci://registry.cn-hangzhou.aliyuncs.com/wasm-plugin/wasm-plugin:0.0.68
  imagePullSecret: aliyun

1)1.1.1.1

连续请求三次:

curl -kvv -X GET 'http://localhost:8082/test' \
-H 'Host: www.test.com' \
-H 'x-forwarded-for: 1.1.1.1,2.1.1.1'

根据第一个ip进行限流

响应头中x-ratelimit-limit为10(限制的总请求数),x-ratelimit-remaining为7(剩余还可以发送的请求数)

2)1.1.1.0/24

请求三次:

curl -kvv -X GET 'http://localhost:8082/test' \
-H 'Host: www.test.com' \
-H 'x-forwarded-for: 1.1.1.2,2.1.1.1'

ip段请求三次

Redis中的数据:
ip段请求三次Redis中数据

3)0.0.0.0/0

请求三次:

curl -kvv -X GET 'http://localhost:8082/test' \
-H 'Host: www.test.com' \
-H 'x-forwarded-for: 2.1.1.2,2.1.1.1'

all请求三次

Redis中的数据:
all请求三次Redis中数据

4)、limit_by_consumer和limit_by_per_consumer
Redis中key示例:
image

Ⅴ. Special notes for reviews

@@ -51,6 +52,12 @@ limit_keys:
query_per_second: 10
- key: a6a6d7f2-ba8a-11ec-bec2-00163e1250b5
query_per_minute: 100
# 正则表达式,以b开头的所有字符串
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里会有歧义,是匹配到的所有统一限制1000,还是匹配到的每一个分别限制1000。

所以我建议增加新的配置项: limit_by_per_header, limit_by_per_param

用来表示匹配到的每一个分别限制这一含义。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里会有歧义,是匹配到的所有统一限制1000,还是匹配到的每一个分别限制1000。

所以我建议增加新的配置项: limit_by_per_header, limit_by_per_param

用来表示匹配到的每一个分别限制这一含义。

好的,那应该就是limit_by_header和limit_by_param只支持精确匹配的,limit_by_per_header和limit_by_per_param只支持正则匹配和*的方式

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以的

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以的

已调整,目前支持以下几种方式:
limit_by_header、limit_by_param、limit_by_consumer、limit_by_cookie(匹配cookie中的key=value) 支持精准匹配
limit_by_per_ip 支持按照ip和ip段配置
limit_by_peer_header、limit_by_peer_param、limit_by_peer_consumer、limit_by_per_cookie 支持正则匹配和*

| redis | object | 是 | - | redis相关配置 |
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
| ----------------------- | ------ | ---- | ------ |-----------------------------------------------------------------------------------------------------------------------------|
| rule_name | string | 是 | - | 限流规则名称,根据限流类型+限流规则名称+限流key对应的实际值来拼装redis key |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

支持下配置多个rule可以同时生效吧,现有的配置作为rules数组里的配置项

Copy link
Collaborator Author

@hanxiantao hanxiantao Jun 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

支持下配置多个rule可以同时生效吧,现有的配置作为rules数组里的配置项

将limit_by_*(共9种)和limit_keys调整到了rule_items中,拼接redis的key的方式调整为限流规则名称+限流类型+限流key名称+限流key对应的实际值,这样只需要外部配置一个rule_name即可

Copy link
Collaborator

@johnlanni johnlanni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@johnlanni johnlanni merged commit 634de3f into alibaba:main Jun 17, 2024
6 checks passed
@hanxiantao hanxiantao deleted the key-cluster-rate-limit branch June 17, 2024 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants