资讯动态

Envoy Listener 本地限流过滤器(Local Rate Limit Filter)完全指南:基于令牌桶的 socket 级限流实现与配置

发布时间:2026/9/13 9:24:08 来源:尧图企业网站定制
Envoy Listener 本地限流过滤器Local Rate Limit Filter完全指南基于令牌桶的 socket 级限流实现与配置【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本篇指南深入讲解 Envoy 的本地限流监听器过滤器local rate limit listener filter它以令牌桶token bucket为核心在 socket 被接受、TLS 握手与 filter chain 匹配之前对每个入站连接进行限流令牌不足时立即关闭 socket。读完本文你将掌握该过滤器的完整配置语法、token_bucket各参数语义与约束、运行期特性开关runtime flag的用法、统计指标命名规则以及其底层源码实现与测试验证方式可直接用于防 DDoS、限制连接速率、保护后端服务等场景。功能概述面向 socket 的令牌桶限流本地限流监听器过滤器类型 URL 为type.googleapis.com/envoy.extensions.filters.listener.local_ratelimit.v3.LocalRateLimit为经过该过滤器 filter chain 的入站 socket应用令牌桶限流。其核心行为非常简单直接每个由该过滤器处理的 socket 消耗1 个令牌如果令牌可用socket 被放行继续后续过滤器处理如果令牌不可用socket 被立即关闭不再进行后续的过滤器迭代。从源码实现看这一行为体现在 local_ratelimit.cc 的Filter::onAccept中当canCreateConnection()返回 false 时过滤器递增rate_limited计数器、调用cb.socket().ioHandle().close()关闭 socket并返回Network::FilterStatus::StopIteration终止过滤器链的处理返回Continue则放行连接。过滤器定位为什么要在监听器层限流在 Envoy 中本地限流共有三种落地层次本过滤器属于最前置的一种。官方架构说明见 local_rate_limiting.rst层次过滤器处理时机监听器层Listener本地限流监听器过滤器本文主题在TLS 握手与 filter chain 匹配之前处理 socket也就是连接建立的最早期网络层Network / L4本地限流网络过滤器在网络层对 L4 连接限流发生在连接已进入对应 filter chain 之后HTTP 层L7HTTP 本地限流过滤器对 HTTP 请求限流可在 listener、virtual host 或 route 级别激活由于监听器过滤器在 TLS 握手之前就介入它特别适合在连接建立的最早阶段快速丢弃超出限速的连接从而以最小代价对抗 SYN 洪泛、连接耗尽类攻击或者为某些业务设定每进程的连接接入速率上限。此外本地限流还可以与**全局限流global rate limiting**配合使用先通过本地限流在边缘快速削减大部分流量降低对全局限流服务的压力。配置详解proto 字段与约束该过滤器的完整 proto 定义位于 local_ratelimit.proto共有三个字段字段类型必填说明stat_prefixstring是min_len: 1统计指标的前缀见下文统计指标一节token_buckettype.v3.TokenBucket是message 级别 required用于限制所有入站 socket 的令牌桶配置runtime_enabledconfig.core.v3.RuntimeFeatureFlag否控制过滤器是否生效的运行期特性开关不配置时默认启用其中token_bucket引用通用的令牌桶类型 token_bucket.proto其字段语义如下字段类型默认值校验规则语义max_tokensuint32无gte: 0桶的最大容量也是桶的初始令牌数取 0 时桶永远为空所有连接都会被限流即始终拒绝tokens_per_fillUInt32Value1gt: 0每个填充周期fill interval向桶中补充的令牌数fill_intervalDuration无required: true且gt: 0令牌补充周期每个周期向桶中加入tokens_per_fill个令牌桶中令牌数永远不会超过max_tokens重要的实现约束在该监听器过滤器中fill_interval必须≥ 50ms以避免过于激进的令牌补充见 local_ratelimit.proto 中的注释说明。tokens_per_fill未指定时默认按 1 处理这一点在 local_ratelimit.cc 构造限流器时通过PROTOBUF_GET_WRAPPED_OR_DEFAULT(..., tokens_per_fill, 1)得以印证。完整配置示例将过滤器挂载到监听器的listener_filters列表中即可启用。以下示例配置限流速率为每秒最多接受 100 个新连接桶容量 100每 1s 补充 100 个令牌listeners: - address: socket_address: address: 0.0.0.0 port_value: 443 listener_filters: - name: envoy.filters.listener.local_ratelimit typed_config: type: type.googleapis.com/envoy.extensions.filters.listener.local_ratelimit.v3.LocalRateLimit stat_prefix: ingress_conn_limit token_bucket: max_tokens: 100 tokens_per_fill: 100 fill_interval: 1s典型限速场景配置每秒 1000 连接、允许瞬时突发burst增大max_tokens即可获得突发能力。例如桶容量 2000、每秒补充 1000则允许瞬时最多放行 2000 个连接稳态速率仍为 1000/stoken_bucket: max_tokens: 2000 tokens_per_fill: 1000 fill_interval: 1s全部拒绝限流开关max_tokens: 0时桶恒为空过滤器将拒绝所有连接token_bucket: max_tokens: 0 fill_interval: 1s注意由于本过滤器按每 socket 消耗 1 令牌工作上述速率均指新连接建立速率connections per second而非请求速率。若需对已建立连接上的 HTTP 请求限流请使用 HTTP 本地限流过滤器。工作原理源码级解读配置工厂与注册过滤器的配置工厂定义在 config.cc其要点如下过滤器名称name()为envoy.filters.listener.local_ratelimit这是 YAML 配置中name字段的取值依据工厂继承NamedListenerFilterConfigFactory属于监听器过滤器accept filter通过filter_manager.addAcceptFilter(...)注册到监听器工厂在创建配置时使用mainThreadDispatcher()构造限流器保证令牌桶在事件循环event loop中定时补充。连接决策链路整个决策链路贯穿三个文件可以概括为local_ratelimit.cc 的FilterConfig::canCreateConnection()调用rate_limiter_.requestAllowed({})即对默认令牌桶做一次令牌消费请求限流器的具体实现是LocalRateLimiterImpl其内部持有一个基于AtomicTokenBucketImpl的RateLimitTokenBucket见 local_ratelimit_impl.h采用原子操作实现线程安全的令牌消费并支持按fill_interval定时补充令牌Filter::onAccept依据结果决定Continue放行或关闭 socket 并StopIteration拒绝。值得关注的是Filter::maxReadBytes()返回 0见 local_ratelimit.h说明该过滤器不消费任何连接数据只在 accept 阶段做一次决策因此对数据通路几乎零开销。关键行为令牌桶跨 worker 共享官方文档明确标注了一个重要事实令牌桶在所有 worker 线程之间共享因此限流是按 Envoy 进程生效的。也就是说无论 Envoy 配置了多少个 worker 线程整个进程共享同一个限速额度不会出现每个 worker 各自独立限速导致总速率放大 N 倍的情况。从实现看FilterConfig是跨所有连接共享、必须线程安全的见 local_ratelimit.h 的注释其内部的AtomicTokenBucketImpl正是为此设计的原子令牌桶。独立性每个过滤器与每条 filter chain 独立限流当前实现中每一个过滤器实例、每一条 filter chain 都有独立的限流额度。因此如果同一监听器的不同 filter chain 上都挂载了该过滤器它们各自消费各自的令牌桶互不影响。在设计限速额度时需要把这一点考虑进去例如相同token_bucket配置挂在 N 条 filter chain 上总放行速率理论上会是 N 倍。统计指标Statistics每个配置了本地限流过滤器的监听器都会产生一组以listener_local_ratelimit.stat_prefix.为根的统计指标。当前版本仅有一个指标名称类型描述rate_limitedCounter因超出限速而被关闭的 socket 总数例如当stat_prefix配置为ingress_conn_limit时完整指标名为listener_local_ratelimit.ingress_conn_limit.rate_limited。这一命名规则在源码中有两处直接体现宏定义ALL_LOCAL_RATE_LIMIT_STATS(COUNTER) COUNTER(rate_limited)见 local_ratelimit.h以及generateStats中固定前缀listener_local_ratelimit.见 local_ratelimit.cc。实际使用时你可以通过 Envoy 的 admin 接口/stats直接查看该计数器用于监控被限流的连接数量、验证限流是否生效。运行期特性开关Runtime过滤器支持通过runtime_enabled字段做运行期特性开关feature flag控制无需重启即可在启用/禁用间切换runtime_enabled: default_value: true runtime_key: ratelimit.enabled不配置runtime_enabled时过滤器默认启用配置后Envoy 会在运行期根据runtime_key对应的运行时值动态决定是否限流可实现秒级的灰度开关。对应源码行为见 local_ratelimit.cc当config_-enabled()为 false 时过滤器直接返回Continue不做任何限流决策。测试与验证仓库为该过滤器提供了单元测试与集成测试local_ratelimit_test.cc单元测试覆盖未限流与限流两个核心场景。例如RateLimit用例配置max_tokens: 1、fill_interval: 3s第一个 socket 被放行Continue第二个 socket 触发ioHandle().close()并返回StopIteration此时计数器listener_local_ratelimit.local_rate_limit_stats.rate_limited为 1模拟时间前进 3 秒令牌补充完成后第三个 socket 再次被放行local_ratelimit_integration_test.cc集成测试验证过滤器在完整 Envoy 运行环境中的行为。你可以通过 Envoy 的 stats 计数器与日志限流时日志级别为 debug输出local_rate_limit: rate limiting socket见 local_ratelimit.cc自行验证限流是否按预期工作。使用注意事项总结限速单位是连接每 socket 消耗 1 令牌适合限制连接建立速率不适合限制请求数按进程生效令牌桶跨所有 worker 共享因此限速是进程级的按过滤器/ filter chain 独立多个挂载点各自独立限速设计总额度时需注意叠加效应fill_interval必须 ≥ 50ms否则配置校验将不通过max_tokens: 0表示永久拒绝所有连接可当作紧急限流开关使用位置最早在 TLS 握手与 filter chain 匹配之前执行最适合在连接建立的最早期做防护配合网络层限流过滤器与 HTTP 限流过滤器可组成多层限流体系与全局限流互补本地限流本过滤器先做进程内快速限流全局限流网络过滤器见 network 层 rate limit 过滤器文档再做分布式精确控制两者结合可显著降低全局限流服务的压力。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价