使用教程
安装和使用¶
安装Limiter模块¶
前提:安装Slimeboot以及对应CRD
之后用户可手动应用以下清单,安装支持单机和均分限流功能的 limiter 模块,
如需支持全局共享限流功能,请先安装 安装 Rls & Redis, 以及重新下发支持全局限流、单机限流和均分限流功能的 limiter-global 的模块,
如需要支持自适应限流,请先安装 prometheus
最佳实践¶
smarlimiter 定义见 proto
注意: 网格场景下,每个服务只能创建一个SmartLimiter资源,其name和namespace对应着服务的service的name和namespace
网格场景单机限流¶
入方向限流¶
服务入方向进行限流,即A->B, 在B段入口方向对请求进行限流判断
以下smartlimiter表示,对reviews服务的入方向9080端口进行限流,限流规则是100次/60秒
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: reviews
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: '100'
strategy: 'single'
condition: 'true'
target:
port: 9080
出方向限流¶
服务出方向进行限流,即A->B, 在A段出口方向对B的请求进行限流判断
以下smartlimiter表示,在productpage服务的出方向限流,即访问路由reviews.default.svc.cluster.local:80/default时进行限流判断,限流规则是2次/10秒
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 10
quota: "2"
strategy: single
condition: "true"
target:
direction: outbound
route:
- reviews.default.svc.cluster.local:80/default
网格场景带match的限流¶
在很多场景下,我们希望对带有某个header的请求进行限流
以下smartlimiter表示,对于default下的productpage服务的9080端口,如果请求的header中包含foo=bar, 那么就进行限流,限流规则是 5次/60s
网格场景下,带match的限流,除了支持Header的精确匹配,还支持正则匹配、前缀匹配、后缀匹配、存在性等功能,具体可参考SmartLimitDescriptor
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "5"
strategy: "single"
condition: "true"
target:
port: 9080
match:
- name: foo
exact_match: bar
如果需要对请求方法进行限流, 如下设置
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "5"
strategy: "single"
condition: "true"
target:
port: 9080
match:
- name: :method
regex_match: GET
如果需要对path进行限流, 如下设置
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "5"
strategy: "single"
condition: "true"
target:
port: 9080
match:
- name: :path
prefix_match: /foo
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "5"
strategy: "single"
condition: "true"
target:
port: 9080
match:
- name: foo
exact_match: bar
- action:
fill_interval:
seconds: 60
quota: "5"
strategy: "single"
condition: "true"
target:
port: 9080
match:
- name: foo1
exact_match: bar1
网格场景全局均分限流¶
以下smartlimiter表示,对于default下的reviews服务的9080端口,进行限流,限流总数为100次/60s, 按两个pod来说,每个pod限流规则是50次/60s
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: reviews
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: '100/{{._base.pod}}'
strategy: 'average'
condition: 'true'
target:
port: 9080
网格场景全局共享限流¶
服务的所有pod, 共享一个全局的限流计数器
举个简单的列子,服务A有3个pod, 每次对A的任意pod进行访问都会使A服务全局限流计数器加一,直至触发限流。限流的表现就是有服务访问服务A,服务A将返回429响应码。
以下smartlimiter表示,对于default下的reviews服务的9080端口,进行限流,限流总数为100次/60s, reviews服务的所有pods共享100次/60s
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: reviews
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: '100'
strategy: 'global'
condition: 'true'
target:
port: 9080
网关场景单机限流¶
网关模式下的限流只作用在出方向
以下smartlimiter表示,对于匹配 gw_cluster: prod-gateway
的pods,下发单机限流规则,对路由a.test.com:80/r1的访问的限流规则是 1次/60s
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: prod-gateway-1
namespace: gateway-system
spec:
gateway: true # 针对网关的限流配置
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60 # 时间,单位秒
quota: "1" # 个数
strategy: single
condition: "true"
target:
direction: outbound
route:
- a.test.com:80/r1 # host/路由
workloadSelector:
gw_cluster: prod-gateway # 物理网关label,一般不动
除了支持route级别,网关单机限流还支持host级别的限流
以下smartlimiter表示,对于匹配 gw_cluster: prod-gateway
的pods, 下发单机限流规则,对于host b.test.com的访问进行限流,限流规则是1次/60s
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: prod-gateway-2
namespace: gateway-system
spec:
gateway: true
workloadSelector:
gw_cluster: prod-gateway
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: '2'
strategy: 'single'
condition: 'true'
target:
direction: outbound
port: 80
host:
- b.test.com
网关场景全局共享限流¶
以下smartlimiter表示,对于匹配 gw_cluster: prod-gateway
的pods, 下发全局共享限流规则,对于路由a.test.com:80/default的访问进行限流,限流规则是10次/60s
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: prod-gateway-3
namespace: gateway-system
spec:
gateway: true
workloadSelector:
gw_cluster: prod-gateway
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "10"
strategy: global
condition: "true"
match:
target:
direction: outbound
route:
- a.test.com:80/default
实践¶
实践1:网格场景全局均分¶
首先以下SmartLimiter资源到集群, 对productpage服务进行每分钟均分10次限流。
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: '10/{{._base.pod}}'
strategy: 'average'
condition: 'true'
target:
port: 9080
然后SmartLimiter资源(如下,部分内容被移除),在SmartLimiter中,多出metricStatus和ratelimitStatus字段,可以看到由于productpage的副本数只有1,所有quota的值为10/1 = 10。
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: 10/{{._base.pod}}
strategy: average
condition: "true"
target:
port: 9080
status:
metricStatus:
_base.pod: "1"
ratelimitStatus:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "10"
strategy: average
target:
port: 9080
最后,我们通过curl的方式去访问 productpage 服务,在访问第11次的时候出现了429 Too Many Requests,也就是服务被限流了,这也就证实了服务的有效性。
...
...
... 省略
node@ratings-v1-85b8d86597-smv5m:/opt/microservices$ curl -I http://productpage:9080/productpage
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 3769
server: envoy
date: Fri, 26 Nov 2021 07:16:21 GMT
x-envoy-upstream-service-time: 9
node@ratings-v1-85b8d86597-smv5m:/opt/microservices$ curl -I http://productpage:9080/productpage
HTTP/1.1 429 Too Many Requests
content-length: 18
content-type: text/plain
date: Fri, 26 Nov 2021 07:16:21 GMT
server: envoy
x-envoy-upstream-service-time: 10
以下对照生成的EnvoyFilter清单,解释更底层的细节。
EnvoyFilter清单包含3个patch部分,分别是给流量生成了genericKey、开启envoy.filters.http.local_ratelimit 插件功能,以及bucket的设置。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
creationTimestamp: "2021-11-26T07:09:58Z"
generation: 1
name: productpage.default.ratelimit
namespace: default
ownerReferences:
- apiVersion: microservice.slime.io/v1alpha2
blockOwnerDeletion: true
controller: true
kind: SmartLimiter
name: productpage
spec:
configPatches:
- applyTo: HTTP_ROUTE
match:
routeConfiguration:
vhost:
name: inbound|http|9080
route:
name: default
patch:
operation: MERGE
value:
route:
rate_limits:
- actions:
- generic_key:
descriptor_value: Service[productpage.default]-User[none]-Id[3651085651]
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: envoy.http_connection_manager
subFilter:
name: envoy.router
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.local_ratelimit
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
stat_prefix: http_local_rate_limiter
- applyTo: HTTP_ROUTE
match:
routeConfiguration:
vhost:
name: inbound|http|9080
route:
name: default
patch:
operation: MERGE
value:
typed_per_filter_config:
envoy.filters.http.local_ratelimit:
'@type': type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
value:
descriptors:
- entries:
- key: generic_key
value: Service[productpage.default]-User[none]-Id[3651085651]
token_bucket:
fill_interval:
seconds: "60"
max_tokens: 10
tokens_per_fill:
value: 10
filter_enabled:
default_value:
numerator: 100
runtime_key: local_rate_limit_enabled
filter_enforced:
default_value:
numerator: 100
runtime_key: local_rate_limit_enforced
stat_prefix: http_local_rate_limiter
token_bucket:
fill_interval:
seconds: "1"
max_tokens: 100000
tokens_per_fill:
value: 100000
workloadSelector:
labels:
app: productpage
实践2:网格场景全局共享¶
提交以下资源到集群, 对productpage服务进行每分钟共计10次限流。
apiVersion: microservice.slime.io/v1alpha2
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "10"
strategy: "global"
condition: "true"
target:
port: 9080
然后查看提交的SmartLimiter资源(如下,部分内容被移除)
kind: SmartLimiter
metadata:
name: productpage
namespace: default
spec:
sets:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "10"
strategy: global
condition: "true"
target:
port: 9080
status:
metricStatus:
_base.cpu.max: "563.3837582"
_base.pod: "1"
ratelimitStatus:
_base:
descriptor:
- action:
fill_interval:
seconds: 60
quota: "10"
strategy: global
target:
port: 9080
最后,我们通过curl的方式去访问 productpage 服务,在访问第11次的时候出现了429 Too Many Requests,也就是服务被限流了,这也就证实了服务的有效性。
...
...
... 省略
node@ratings-v1-85b8d86597-smv5m:/opt/microservices$ curl -I http://productpage:9080/productpage
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 3769
server: envoy
date: Fri, 26 Nov 2021 07:33:11 GMT
x-envoy-upstream-service-time: 10
node@ratings-v1-85b8d86597-smv5m:/opt/microservices$ curl -I http://productpage:9080/productpage
HTTP/1.1 429 Too Many Requests
x-envoy-ratelimited: true
date: Fri, 26 Nov 2021 07:33:11 GMT
server: envoy
x-envoy-upstream-service-time: 1
transfer-encoding: chunked
以下对照生成的EnvoyFilter和ConfigMap清单,解释更底层的细节。
在EnvoyFilter中包含两个patch,一个是给流量生成了genericKey,另一个是设置RLS的服务地址outbound|18081||rate-limit.istio-system.svc.cluster.local
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
creationTimestamp: "2021-11-26T07:31:31Z"
name: productpage.default.ratelimit
namespace: default
ownerReferences:
- apiVersion: microservice.slime.io/v1alpha2
blockOwnerDeletion: true
controller: true
kind: SmartLimiter
name: productpage
spec:
configPatches:
- applyTo: HTTP_ROUTE
match:
routeConfiguration:
vhost:
name: inbound|http|9080
route:
name: default
patch:
operation: MERGE
value:
route:
rate_limits:
- actions:
- generic_key:
descriptor_value: Service[productpage.default]-User[none]-Id[2970232041]
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
filterChain:
filter:
name: envoy.http_connection_manager
subFilter:
name: envoy.router
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.ratelimit
typed_config:
'@type': type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
value:
domain: slime
rate_limit_service:
grpc_service:
envoy_grpc:
cluster_name: outbound|18081||rate-limit.istio-system.svc.cluster.local
transport_api_version: V3
workloadSelector:
labels:
app: productpage
ConfigMap内容中包含了一个config.yaml,其内容是将要挂载到RLS的/data/ratelimit/config目录,对带有Service[productpage.default]-User[none]-Id[2970232041]的流量进行限流10/min.
apiVersion: v1
data:
config.yaml: |
domain: slime
descriptors:
- key: generic_key
value: Service[productpage.default]-User[none]-Id[2970232041]
rate_limit:
requests_per_unit: 10
unit: MINUTE
kind: ConfigMap
metadata:
name: rate-limit-config
namespace: istio-system
依赖¶
安装 configmap¶
全局共享限流的实现,依赖rls服务,同时也需要将限流规则挂载至rsl服务,所以需要提前安装rate-limit-config
资源内容如下 mesh
如果是网关场景,需要下发以下资源 gateway
安装 Prometheus¶
Prometheus 是一款广泛应用的监控系统,本服务依赖prometheus采集服务指标。
为此我们提供了一个简单的Prometheus安装清单,使用以下命令进行安装。
kubectl apply -f "https://raw.githubusercontent.com/slime-io/limiter/master/install/prometheus.yaml"
安装 RLS & Redis¶
RLS服务即 Rate Limit Service RLS , 我们利用它支持全局共享限流, 如果确认服务不需要支持全局限流可以选择不安装Rls, 跳过该小节。
简单介绍下RLS服务,它是一个GO开发的gRPC服务,利用Redis支持了全局限流的功能。当你配置了全局限流SmartLimiter后,该资源清单首先会被转化成EnvoyFilter,Istio会根据EnvoyFilter内容下发限流规则到相应的Envoy,之后Envoy在执行全局限流规则时,会去访问RLS服务,让其决定是否进行限流。
为此我们提供了一个简单的 RLS&Redis 安装清单,使用以下命令进行安装。
kubectl apply -f "https://raw.githubusercontent.com/slime-io/limiter/master/install/rls.yaml"
如果是网关场景,需要修改以上资源,并部署到网关所处的ns
问题排查¶
如果出现限流未生效的情况,可以顺着以下思路进行排查。
- Limiter 日志是否出现异常
- EnvoyFilter或者ConfigMap是否正常生成(全局限流)
- 通过config dump 命令查看envoy限流配置是否真实生效
- RLS服务的 /data/ratelimit/config 目录下是否有相关的ConfigMap内容(全局限流)
欢迎交流~