在大促等场景下,瞬间洪峰流量会使系统超出最大负载,调用大量堆积,导致整个调用链路卡死。ASM提供了本地限流功能,支持对网关和服务进行流量限制,达到保护系统的目的。本文介绍如何使用ASM本地限流功能。
前提条件
- 已创建ASM实例,且ASM实例要符合以下要求:
- 如果您使用的是ASM商业版(专业版),要求ASM商业版(专业版)为v1.11.5.30或以上版本。关于升级ASM实例的具体操作,请参见升级ASM实例。
- 如果您使用的是ASM标准版,ASM标准版仅支持Istio原生方式配置本地限流功能,且要求ASM标准版为v1.9或以上版本。不同Istio版本需参考相应版本文档,关于最新的Istio版本配置本地限流功能的具体操作,请参见Enabling Rate Limits using Envoy。
- 已添加集群到ASM实例。具体操作,请参见添加集群到ASM实例。
- 已部署入口网关服务。具体操作,请参见创建入口网关服务。
- 创建Bookinfo服务和Nginx。具体操作,请参见部署应用到ASM实例。本文将Bookinfo部署在default命名空间,将Nginx部署在foo命名空间。
- 使用以下内容创建ASM网关。具体操作,请参见创建入口网关服务。
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: bookinfo-gateway namespace: default spec: selector: istio: ingressgateway servers: - hosts: - bf2.example.com port: name: http number: 80 protocol: http
- 使用以下内容创建虚拟服务。具体操作,请参见管理虚拟服务。
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: bookinfo namespace: default spec: gateways: - bookinfo-gateway hosts: - bf2.example.com http: - match: - uri: exact: /productpage - uri: prefix: /static - uri: exact: /login - uri: exact: /logout - uri: prefix: /api/v1/products name: productpage-route-name1 route: - destination: host: productpage port: number: 9080 - match: - uri: prefix: /nginx name: nginx-route-name1 rewrite: uri: / route: - destination: host: nginx.foo.svc.cluster.local port: number: 80
- 安装流量加压工具。具体操作,请参见hey。
ASMLocalRateLimiter声明式配置介绍
ASMLocalRateLimiter CRD的apiVersion字段说明如下:
- 若ASM实例版本为1.15.3.105及以上,支持使用
apiVersion: istio.alibabacloud.com/v1
。若您在ACK集群进行了相关配置,请将对应的ASMLocalRateLimiter CRD中的apiVersion: istio.alibabacloud.com/v1beta1
修改为apiVersion: istio.alibabacloud.com/v1
,再重新进行部署。 - 若ASM实例版本为1.15.3.105以下,支持使用
apiVersion: istio.alibabacloud.com/v1beta1
。
ASM通过ASMLocalRateLimiter CRD实现本地限流的声明式配置。配置Spec说明如下:
字段 | 类型 | 说明 | 是否必须 |
---|---|---|---|
workloadSelector | map<string, string> | 通过一个或多个标签,指明限流配置生效的一组特定的Pod或VM。标签搜索的范围限制在资源所在的配置命名空间。更多信息,请参见Workload Selector。 | Yes |
isGateway | bool | 默认为false 。 | No |
configs | LocalRateLimiterConfig[] | 本地限流配置,可配置多条。 | Yes |
LocalRateLimiterConfig属性字段
字段 | 类型 | 说明 | 是否必须 |
---|---|---|---|
name | string | 单条限流配置的名称。 | Yes |
match | RatelimitMatch | 匹配条件。 | Yes |
limit | LimitConfig | 限流阈值配置。 | Yes |
字段 | 类型 | 说明 | 是否必须 |
---|---|---|---|
vhost | VirtualHostMatch | VirtualHost匹配条件。 | No |
LimitConfig属性字段
字段 | 类型 | 说明 | 是否必须 |
---|---|---|---|
fill_interval | Duration | 令牌填充时间单位,例如seconds: 1 或者nanos: 1000 。nanos表示纳秒。 | No |
quota | int | 令牌数量,必须为整数,例如:1000。 | No |
per_downstream_connection | bool | 指定速率限制器的令牌桶的范围。默认为false 。取值说明如下:
说明 仅支持ASM版本≥1.13.4。 | No |
custom_response_body | string | 当请求被限制时,自定义返回Body内容。 说明 仅支持ASM版本≥1.13.4。 | No |
response_header_to_add | map[string]string | 当请求被限制时,自定义添加Header内容。 说明 仅支持ASM版本≥1.13.4。 | No |
VirtualHostMatch属性字段
字段 | 类型 | 说明 | 是否必须 |
---|---|---|---|
name | string | 匹配的VirtualHost 名称。 | Yes |
port | int | 匹配的请求端口。 | No |
route | RouteMatch | 匹配的请求接口对应的路由名称。 | No |
RouteMatch属性字段
字段 | 类型 | 说明 | 是否必须 |
---|---|---|---|
name_match | string | 匹配的路由名称,对应VirtualService 下的单条路由名称。 | No |
header_match | HeaderMatcher[] | 匹配服务请求的header,支持配置多个。 | No |
HeaderMatcher属性字段
字段 | 类型 | 说明 | 是否必须 |
---|---|---|---|
name | string | header名称。 | No |
regex_match | string | 正则表达式匹配。 | No |
exact_match | string | 精确匹配。 | No |
prefix_match | string | 前缀匹配,以什么开头进行匹配。 | No |
suffix_match | string | 后缀匹配,以什么结尾进行匹配。 | No |
present_match | bool | 如果配置为true ,则不关心该header value的具体取值,只需要header存在即可。 | No |
invert_match | bool | 默认为false ,如果设置为true ,则正则匹配结果取反。 | No |
适用对象
场景示例说明

网关限流
对网关进行限流,从流量入口处进行限流,防止下游服务被压垮。
limite.quota
只针对单个网关实例生效,若网关有n个实例,test1该路由对应的后端服务限流阈值则为n * quota,若调整了后端服务实例个数,需要对应调整限流阈值。apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMLocalRateLimiter
metadata:
name: for-api-test
namespace: default
spec:
workloadSelector:
labels:
app: istio-ingressgateway
isGateway: true
configs:
- match:
vhost:
name: "www.example1.com" # 如果gateway中配置了多个host域名,填最后一个即可。
port: 80
route:
name_match: "test1" # VirtualService路由配置中对应route的name,若VirtualService路由配置下没有对应name的路由,则不生效。
limit:
fill_interval:
seconds: 1
quota: 10
- match:
vhost:
name: "www.example2.com"
port: 80
route:
name_match: "test1"
limit:
fill_interval:
seconds: 1
quota: 100
- workloadSelector:用于匹配生效的Pod或虚拟机。本文为了使ASMLocalRateLimiter作用于网关,设置为istio-ingressgateway。
- isGateway:是否作用于网关,本示例设置为true。
- fill_interval下的seconds:令牌填充时间。
- quota:令牌发放个数。
本文设置seconds为1,quota为100,表示1s内发放100个令牌,即网关1s内最多处理100个请求。
网关限流场景示例
场景一:对单个接口配置限流规则
对bf2.example.com:80
这个VirtualHost下的productpage-route-name1
路由设定限流配置,使得访问productpage-route-name1
路由下的/productpage、/static、/login、/logout接口都将受到流量限制。
- 使用kubectl连接ASM,具体操作,请参见通过kubectl连接ASM实例。
- 创建ASMLocalRateLimiter。
- 在hey工具中执行以下命令,持续产生压力流量。
hey -host bf2.example.com -c 10 -n 100000 http://<ASM网关IP>/productpage
hey -host bf2.example.com -c 10 -n 100000 http://<ASM网关IP>/nginx
- 执行以下命令,访问Bookinfo服务的/productpage接口。
curl -H 'host: bf2.example.com' http://<ASM网关IP>/productpage -v
预期输出:
< HTTP/1.1 429 Too Many Requests < Content-Length: 18 < Content-Type: text/plain < Date: Thu, 13 Jan 2022 03:03:09 GMT < Server: istio-envoy < local_rate_limited
可以看到访问Bookinfo服务受到限流。
- 执行以下命令,访问Bookinfo服务的/nginx接口。
curl -H 'host: bf2.example.com' http://${ASM_GATEWAY_IP}/nginx -v
返回结果中没有429,说明访问未限流。
场景二:对网关域名和端口的全局配置限流规则
对bf2.example.com:80
这个virtualHost设定限流配置,使得访问Bookinfo服务下的/productpage、/static、/login、/logout、/nginx接口都将收到流量限制。
- 使用kubectl连接ASM,具体操作,请参见通过kubectl连接ASM实例。
- 创建ASMLocalRateLimiter。
- 在hey工具中执行以下命令,持续产生压力流量。
hey -host bf2.example.com -c 10 -n 100000 http://${ASM_GATEWAY_IP}/nginx
- 执行以下命令,访问Bookinfo服务的/nginx接口。
curl -H 'host: bf2.example.com' http://${ASM_GATEWAY_IP}/nginx -v
可以看到,返回
HTTP/1.1 429 Too Many Requests
,说明访问Bookinfo服务的/nginx接口受到限流。
场景三:删除限流配置后,访问恢复
- 使用kubectl连接ASM,具体操作,请参见通过kubectl连接ASM实例。
- 执行以下命令,删除限流配置文件。
kubectl delete -f asmlocalratelimiter-test-gw.yaml
kubectl delete -f asmlocalratelimiter-test-gw-global.yaml
- 执行以下命令,访问Bookinfo服务的/nginx接口。
curl -H 'host: bf2.example.com' http://${ASM_GATEWAY_IP}/nginx -v
返回结果中没有429,说明访问未限流。
应用服务限流
对服务进行限流,限制服务一定时间内处理请求的数量。
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMLocalRateLimiter
metadata:
name: reviews-v3-local-ratelimiter
namespace: default
spec:
workloadSelector:
labels:
app: reviews
version: v3
....
若服务有多个版本,可以通过WorkLoadSelector label
定义生效的Deployment范围,例如以上表示仅针对reviews的v3版本配置限流。
应用服务限流场景示例
场景一:对reviews服务配置限流规则
- 使用kubectl连接ASM,具体操作,请参见通过kubectl连接ASM实例。
- 创建ASMLocalRateLimiter。
- 在hey工具中执行以下命令,持续产生压力流量。
hey -host bf2.example.com -c 10 -n 100000 http://<ASM网关IP>/productpage
- 执行以下命令,查看productpage sidecar日志。
kubectl logs -f productpage-v1-b84f8bfdd-wgxlc -c istio-proxy
预期输出:
[2022-01-14T07:56:13.086Z] "GET /reviews/0 HTTP/1.1" 429 - via_upstream - "-" 0 18 1 1 "-" "hey/0.0.1" "9295da56-9a6b-9476-b662-1cbd61a82898" "reviews:9080" "10.180.0.190:9080" outbound|9080|v1|reviews.default.svc.cluster.local 10.180.0.196:36702 192.168.195.113:9080 10.180.0.196:33522 - - [2022-01-14T07:56:13.091Z] "GET /reviews/0 HTTP/1.1" 429 - via_upstream - "-" 0 18 0 0 "-" "hey/0.0.1" "9295da56-9a6b-9476-b662-1cbd61a82898" "reviews:9080" "10.180.0.190:9080" outbound|9080|v1|reviews.default.svc.cluster.local 10.180.0.196:36702 192.168.195.113:9080 10.180.0.196:33528 - - [2022-01-14T07:56:13.051Z] "GET /details/0 HTTP/1.1" 200 - via_upstream - "-" 0 178 41 1 "-" "hey/0.0.1" "061d3542-52a7-9511-b217-7fdf9ee9a1dd" "details:9080" "10.180.0.160:9080" outbound|9080||details.default.svc.cluster.local 10.180.0.196:58724 192.168.127.75:9080 10.180.0.196:57754 - default [2022-01-14T07:56:13.095Z] "GET /reviews/0 HTTP/1.1" 429 - via_upstream - "-" 0 18 0 0 "-" "hey/0.0.1" "061d3542-52a7-9511-b217-7fdf9ee9a1dd" "reviews:9080" "10.180.0.190:9080" outbound|9080|v1|reviews.default.svc.cluster.local 10.180.0.196:36702 192.168.195.113:9080 10.180.0.196:33534 - -
可以看到访问
reviews:9080
返回结果中包含429,说明访问受到限流。
场景二:对review v3版本配置限流规则
- 使用kubectl连接ASM,具体操作,请参见通过kubectl连接ASM实例。
- 创建ASMLocalRateLimiter。
- 在hey工具中执行以下命令,持续产生压力流量。
hey -host bf2.example.com -c 10 -n 100000 http://<ASM网关IP>/productpage
- 执行以下命令,查看reviews-v1、reviews-v2、reviews-v3对应Pod下Sidecar的日志。
kubectl logs -f ${your-reviews-pod-name} -c istio-proxy
可以看到只有reviews-v3下access_log日志对应请求的返回包含429,reviews-v2和reviews-v3对应请求的返回是正常的200。说明只有reviews-v3服务受到限流,reviews-v1和reviews-v2服务未受到限流。