使用ASM本地限流功能
在大促等场景下,瞬间洪峰流量会使系统超出最大负载,调用大量堆积,导致整个调用链路卡死。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网关。具体操作,请参见创建入口网关。
已创建虚拟服务。具体操作,请参见管理虚拟服务。
已安装流量加压工具。具体操作,请参见hey。
适用对象
ASM本地限流功能适用于ASM网关和应用服务(注入了Sidecar)。
您可以单击文件,直接下载本场景示例涉及的配置文件。
场景示例说明
本文以Bookinfo和Nginx为例介绍网关和服务限流的具体使用场景。Nginx将单独部署在foo命名空间,用于验证限流的开启范围。
网关限流
对网关进行限流,从流量入口处进行限流,防止下游服务被压垮。
使用kubectl连接ASM,具体操作,请参见通过控制面kubectl访问Istio资源。然后使用以下内容,创建ASMLocalRateLimiter。
以下配置中的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
部分字段说明如下。关于字段的更多信息,请参见ASMLocalRateLimiter CRD说明。
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访问Istio资源。
创建ASMLocalRateLimiter。
使用以下内容,创建asmlocalratelimiter-test-gw.yaml。
ASM版本为1.13.4以下
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMLocalRateLimiter metadata: name: ingressgateway namespace: istio-system spec: workloadSelector: labels: app: istio-ingressgateway isGateway: true configs: - limit: fill_interval: seconds: 1 quota: 10 match: vhost: name: bf2.example.com port: 80 route: name_match: productpage-route-name1 # 该名称需要和VirtualService下的route name一致。
ASM版本为1.13.4及以上
您可以自定义限流返回的Header和Body内容,在
limit
下配置custom_response_body
即可。apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMLocalRateLimiter metadata: name: ingressgateway namespace: istio-system spec: workloadSelector: labels: app: istio-ingressgateway isGateway: true configs: - limit: fill_interval: seconds: 1 quota: 10 custom_response_body: '{"ret_code": xxx, "message": "Your request be limited" }' match: vhost: name: bf2.example.com port: 80 route: name_match: productpage-route-name1 # 该名称需要和virtualservice下的route name一致。
执行以下命令,创建ASMLocalRateLimiter。
kubectl apply -f asmlocalratelimiter-test-gw.yaml
在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访问Istio资源。
创建ASMLocalRateLimiter。
使用以下内容,创建asmlocalratelimiter-test-gw-global.yaml。
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMLocalRateLimiter metadata: name: ingressgateway namespace: istio-system spec: workloadSelector: labels: app: istio-ingressgateway isGateway: true configs: - match: vhost: name: "bf2.example.com" port: 80 limit: fill_interval: seconds: 1 quota: 10
执行以下命令,创建ASMLocalRateLimiter。
kubectl apply -f asmlocalratelimiter-test-gw-global.yaml
在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访问Istio资源。
执行以下命令,删除限流配置文件。
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,说明访问未限流。
应用服务限流
对服务进行限流,限制服务一定时间内处理请求的数量。
使用kubectl连接ASM,具体操作,请参见通过控制面kubectl访问Istio资源。然后使用以下内容,创建ASMLocalRateLimiter。
针对应用服务进行配置,若服务工作负载有n个实例,对应整体服务限流阈值为n * quota_per_instance。
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版本配置限流。
应用服务限流场景示例
应用服务限流生效前提是应用服务已注入Sidecar。在操作应用服务限流配置之前,请务必移除网关相关限流配置,避免对应用服务限流配置产生影响。
场景一:对reviews服务配置限流规则
使用kubectl连接ASM,具体操作,请参见通过控制面kubectl访问Istio资源。
创建ASMLocalRateLimiter。
使用以下内容,创建asmlocalratelimiter-test-reviews.yaml。
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMLocalRateLimiter metadata: name: reviews namespace: default spec: workloadSelector: labels: app: reviews configs: - match: vhost: name: "*" port: 9080 route: header_match: - name: ":path" prefix_match: "/" limit: fill_interval: seconds: 1 quota: 10
以上配置是针对reviews服务的9080端口,然后通过
header_match
配置匹配条件,匹配以/开头的请求。执行以下命令,创建ASMLocalRateLimiter。
kubectl apply -f asmlocalratelimiter-test-reviews.yaml
在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访问Istio资源。
创建ASMLocalRateLimiter。
使用以下内容,创建asmlocalratelimiter-test-reviews-only-v3.yaml。
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMLocalRateLimiter metadata: name: reviews namespace: default spec: workloadSelector: labels: app: reviews version: v3 configs: - match: vhost: name: "*" port: 9080 route: header_match: - name: ":path" prefix_match: "/" limit: fill_interval: seconds: 1 quota: 10
以上配置是针对reviews v3服务的9080端口,然后通过
header_match
配置匹配条件,匹配/开头的请求。执行以下命令,创建ASMLocalRateLimiter。
kubectl apply -f asmlocalratelimiter-test-reviews-only-v3.yaml
在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服务未受到限流。