如何设置全局限流

    安装完成后,可以看到集群中增加了下面两个 NS,这两个 NS 中分别安装了基于 MetaProtocol 实现的 Dubbo 和 Thrift 协议的示例程序。 你可以选用任何一个程序进行测试。

    什么是全局限流

    和不同的是,在使用全局限流时,所有的服务实例共用一个限流配额。全局限流通过一个限流服务器来实现在多个服务实例之间共享限流配额。在收到请求时,服务服务端的 Sidecar Proxy 会先向限流服务器发送一个限流查询请求,限流服务器在其自身的配置文件中读取限流的规则,根据规则判断一个限流请求是否触发了限流条件,然后将限流结果返回给 Sidecar Proxy。 Sidecar Proxy 根据该限流结果决定是禁止本次请求还是继续处理本次请求。

    全局限流的特点是限流判断在限流服务器处统一进行的,因此不会受到服务实例数量的影响。但全局限流也会引入限流服务器这额外一跳,会带来附加的网络延迟。在大量客户请求的情况下,限流服务器自身是一个潜在的瓶颈点,部署和管理比本地限流更为复杂。

    如果用限流的目的是为了将服务实例的压力控制在合理的范围内,建议使用本地限流。因为本地限流是在每个服务实例的 Sidecar Proxy 处分别处理的,因此在这种场景下本地限流对服务实例的入向请求控制更为精确和合理。如果配合适当的 HPA 策略,在现有服务实例负载都打满的情况下还可以对服务实例进行水平扩容,保障服务的稳定运行。

    部署限流服务器

    在示例程序中已经部署了限流服务器,并通过配置文件配置了限流规则,无需再单独部署。

    全局限流的限流规则需要在限流服务器的配置文件中进行设置。下面的限流规则表示对 sayHello 接口设置 5条/每分钟 的限流。

    1. descriptors:
    2. - key: method
    3. value: "sayHello"
    4. rate_limit:
    5. unit: minute
    6. requests_per_unit: 5

    部署的相关脚本参见:

    通过 MetaRouter 为服务器启用限流,启用后,服务的 Sidecar Proxy 在收到请求后会向限流服务器发起限流请求,并根据请求的返回结果决定是继续处理该请求还是终止请求。

    MetaRouter 中的限流设置中可以设置 match 条件,如果 match 条件存在,则表示只将符合条件的请求发送到限流服务器进行限流判断。如果 match 条件未设置,则表示该服务的所有请求都会发送到限流服务器进行判断。合理使用 match 条件可以在本地过滤掉不需要限流的请求,提高请求处理效率。

    使用 aerakictl 命令来查看客户端的应用日志,可以看到客户端每分钟只能成功执行 5 次请求:

    1. ~ aerakictl_app_log client meta-thrift -f --tail 10
    2. Hello Aeraki, response from thrift-sample-server-v1-5c8476684-842l6/172.17.0.40
    3. Hello Aeraki, response from thrift-sample-server-v2-6d5bcc885-hpx7n/172.17.0.41
    4. Hello Aeraki, response from thrift-sample-server-v1-5c8476684-842l6/172.17.0.40
    5. Hello Aeraki, response from thrift-sample-server-v2-6d5bcc885-hpx7n/172.17.0.41
    6. Hello Aeraki, response from thrift-sample-server-v1-5c8476684-842l6/172.17.0.40
    7. org.apache.thrift.TApplicationException: meta protocol local rate limit: request '6' has been rate limited
    8. at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:79)
    9. at org.aeraki.HelloService$Client.recv_sayHello(HelloService.java:61)
    10. at org.aeraki.HelloService$Client.sayHello(HelloService.java:48)
    11. at org.aeraki.HelloClient.main(HelloClient.java:44)
    12. Connected to thrift-sample-server
    13. org.apache.thrift.TApplicationException: meta protocol local rate limit: request '7' has been rate limited
    14. ...

    理解原理

    在向 Sidecar Proxy 下发的配置中, Aeraki 在 VirtualInbound Listener 中服务对应的 FilterChain 中设置了 MetaProtocol Proxy。

    Aeraki 会将 MetaRouter 中配置的限流规则翻译为 global rate limit filter 的限流配置,通过 Aeraki 下发给 MetaProtocol Proxy。

    可以通过下面的命令查看服务的 sidecar proxy 的配置:

    1. {
    2. "typed_config": {
    3. "@type": "type.googleapis.com/udpa.type.v1.TypedStruct",
    4. "type_url": "type.googleapis.com/aeraki.meta_protocol_proxy.v1alpha.MetaProtocolProxy",
    5. "stat_prefix": "inbound|9090||",
    6. "application_protocol": "thrift",
    7. "route_config": {
    8. "name": "inbound|9090||",
    9. "routes": [
    10. {
    11. "route": {
    12. "cluster": "inbound|9090||"
    13. }
    14. }
    15. ]
    16. },
    17. "codec": {
    18. "name": "aeraki.meta_protocol.codec.thrift"
    19. },
    20. "meta_protocol_filters": [
    21. {
    22. "name": "aeraki.meta_protocol.filters.ratelimit",
    23. "config": {
    24. "@type": "type.googleapis.com/aeraki.meta_protocol_proxy.filters.ratelimit.v1alpha.RateLimit",
    25. "match": {
    26. "metadata": [
    27. {
    28. "name": "method",
    29. ]
    30. },
    31. "domain": "production",
    32. "timeout": "0.100s",
    33. "failure_mode_deny": true,
    34. "rate_limit_service": {
    35. "grpc_service": {
    36. "envoy_grpc": {
    37. "cluster_name": "outbound|8081||rate-limit-server.meta-thrift.svc.cluster.local"
    38. }
    39. }
    40. },
    41. "descriptors": [
    42. {
    43. "property": "method",
    44. "descriptor_key": "method"
    45. }
    46. ]
    47. }
    48. },
    49. {
    50. "name": "aeraki.meta_protocol.filters.router"
    51. }
    52. ]
    53. }
    54. }

    最后修改 May 9, 2022: