ASM流量调度套件提供了精细化的限流策略,可以实现对进入指定服务的流量进行全局限流、分用户限流、设置突发流量窗口、自定义请求token消耗速率等高级限流功能。本文介绍如何使用流量调度套件提供的RateLimitingPolicy来支持分用户限流场景。
背景信息
ASM流量调度套件的限流策略采用令牌桶算法。系统以固定速率生成令牌(tokens),并加入到令牌桶中,直到容量上限。服务间的请求需要消耗tokens才能发送成功,如果桶中有足够的tokens,请求发送时将消耗token;如果没有足够的tokens,请求可能会被排队或丢弃。此算法可以保证数据传输的平均速率不会超过token的生成速率,同时又能应对一定程度的突发流量。
前提条件
已添加Kubernetes托管版集群到ASM实例,且ASM实例为1.21.6.83版本及以上。具体操作,请参见添加集群到ASM实例。
已通过kubectl连接至ACK集群。 具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。
已开启ASM流量调度套件。具体操作,请参见开启ASM流量调度套件。
已为Kubernetes集群中的default命名空间开启自动注入。具体操作,请参见管理全局命名空间。
已创建名为ingressgateway的入口网关,并开启80端口。具体操作,请参见创建入口网关。
准备工作
部署httpbin和sleep示例服务,并验证sleep服务能否正常访问httpbin服务。
使用以下内容创建httpbin.yaml。
执行以下命令,创建httpbin应用。
kubectl apply -f httpbin.yaml -n default
使用以下内容创建sleep.yaml。
执行以下命令,创建sleep应用。
kubectl apply -f sleep.yaml -n default
执行以下命令,进入sleep应用Pod。
kubectl exec -it deploy/sleep -- sh
执行以下命令,向httpbin服务发送请求。
curl -I http://httpbin:8000/headers
预期输出:
HTTP/1.1 200 OK server: envoy date: Tue, 26 Dec 2023 07:23:49 GMT content-type: application/json content-length: 353 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 1
返回200 OK,表明访问成功。
步骤一:创建RateLimitingPolicy限流规则
使用kubectl连接到ASM实例,具体操作,请参见通过控制面kubectl访问Istio资源。
使用以下内容,创建ratelimitingpolicy.yaml文件。
apiVersion: istio.alibabacloud.com/v1 kind: RateLimitingPolicy metadata: name: ratelimit namespace: istio-system spec: rate_limiter: bucket_capacity: 2 fill_amount: 2 parameters: interval: 30s limit_by_label_key: http.request.header.user_id selectors: - agent_group: default control_point: ingress service: httpbin.default.svc.cluster.local
部分字段说明如下。关于字段的更多信息,请参见RateLimitingPolicy CRD说明。
字段
说明
fill_amount
在interval指定的时间间隔内填充令牌的数量。示例中指定为2,即每过interval指定的时间间隔后便向令牌桶填充2个令牌。
interval
向令牌桶中填充令牌的时间间隔。示例中指定为30s,即每过30秒后便向令牌桶填充2个令牌。
bucket_capacity
令牌桶内的令牌数量上限。当请求速率小于令牌桶填充速率时,令牌桶内的令牌数量会持续增加,最大将达到
bucket_capacity
。使用bucket_capacity
可以容许一定程度的突发流量。示例中设置为2,和fill_amount相同,即不允许任何突发流量。limit_by_label_key
指定限流策略使用什么请求标签进行分组,指定后,不同标签的请求将分别进行限流,拥有相互独立的令牌桶。示例中使用
http.request.header.user_id
,其意义是使用请求的user_id
请求头进行分组,模拟了分用户限流的场景。示例中假设不同的用户发起的请求拥有不同的used_id
请求头。selectors
指定应用限流策略的多个服务。示例中使用
service: httpbin.default.svc.cluster.local
表示对httpbin.default.svc.cluster.local
服务进行限流。
执行以下命令,创建RateLimitingPolicy限流规则
kubectl apply -f ratelimitingpolicy.yaml
步骤二:验证分用户限流效果
使用ACK集群的kubectl执行以下命令,进入sleep应用开启bash。
kubectl exec -it deploy/sleep -- sh
执行以下命令,使用user1身份连续访问httpbin服务的/headers路径两次。
curl -H "user_id: user1" httpbin:8000/headers -v curl -H "user_id: user1" httpbin:8000/headers -v
预期输出:
< HTTP/1.1 429 Too Many Requests < retry-after: 14 < date: Mon, 17 Jun 2024 11:48:53 GMT < server: envoy < content-length: 0 < x-envoy-upstream-service-time: 1 < * Connection #0 to host httpbin left intact
在第2步执行后的30秒内,执行以下命令,使用user2身份访问httpbin服务的/headers路径一次。
curl -H "user_id: user2" httpbin:8000/headers -v
预期输出:
< HTTP/1.1 200 OK < server: envoy < date: Mon, 17 Jun 2024 12:42:17 GMT < content-type: application/json < content-length: 378 < access-control-allow-origin: * < access-control-allow-credentials: true < x-envoy-upstream-service-time: 5 < { "headers": { "Accept": "*/*", "Host": "httpbin:8000", "User-Agent": "curl/8.1.2", "User-Id": "user2", "X-Envoy-Attempt-Count": "1", "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=ddab183a1502e5ededa933f83e90d3d5266e2ddf87555fb3da1ad40dde3c722e;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/sleep" } } * Connection #0 to host httpbin left intact
可以看到user2访问相同的路径并未触发限流,证明分用户限流成功。
相关操作
您可以通过Grafana大盘来观测RateLimitingPolicy策略的执行效果。请确保Grafana使用的数据源Prometheus实例已经完成配置采集ASM流量调度套件相关指标。
将以下内容导入到Grafana,创建RateLimitingPolicy策略的大盘。
大盘效果如下。