4. Envoy 通用过滤器扩展机制:Network Filter、Access Loggers、Stats 扩展点、扩展注册与配置加载
Envoy 的扩展性是其作为云原生代理核心竞争力的关键。本章深入剖析 Envoy 的通用过滤器扩展机制,涵盖 Network Filter、Access Loggers、Stats 扩展点 以及 扩展注册与配置加载 四大核心模块。理解这些机制是开发自定义扩展(如策略即代码资源配额过滤器)的基础。
4.1 扩展点架构总览
Envoy 的扩展体系采用分层设计,允许开发者在不修改核心代码的情况下,通过插件方式注入自定义逻辑。下图展示了本章涉及的四个主要扩展点及其在数据平面与控制平面中的位置关系。
4.2 Network Filter 扩展机制
Network Filter 是 Envoy 最核心的扩展点之一,工作在 L3/L4 层,直接处理原始 TCP 连接上的数据流。它分为两类:Listener Filter(在连接建立前执行)和 Network Filter(在连接建立后执行)。
4.2.1 核心接口与回调
实现一个自定义 Network Filter 需要实现以下关键接口:
| 接口/回调 | 触发时机 | 典型用途 |
|---|---|---|
onNewConnection() |
新 TCP 连接建立时 | 初始化连接上下文、执行准入控制 |
onData() |
接收到数据时 | 数据解析、修改、转发决策 |
onWrite() |
数据即将发送时 | 响应数据修改、注入头部 |
onEvent() |
连接事件(关闭/重置/超时) | 清理资源、记录连接终止统计 |
关键设计原则:Network Filter 采用链式调用(Filter Chain),每个 Filter 可以决定是否将数据传递给下一个 Filter。通过 FilterStatus 枚举(Continue、StopIteration、ResumeIteration)控制数据流。
4.2.2 配置示例
以下是一个自定义 Network Filter 的静态配置片段,展示了如何将其插入到监听器的 Filter Chain 中:
static_resources:
listeners:
- name: my_listener
address:
socket_address: { address: 0.0.0.0, port_value: 10000 }
filter_chains:
- filters:
- name: envoy.filters.network.my_custom_filter
typed_config:
"@type": type.googleapis.com/myorg.filters.network.MyCustomFilterConfig
max_connections: 100
quota_check_enabled: true
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: tcp
cluster: my_cluster
4.3 Access Loggers 扩展机制
Access Loggers 负责记录经过 Envoy 的每个请求/响应的详细信息。Envoy 提供了多种内置 Logger(如 File、gRPC、Stdout),同时也支持通过扩展机制实现自定义 Logger。
4.3.1 自定义 Access Logger 接口
实现自定义 Access Logger 需要实现 AccessLog::Instance 接口,核心方法包括:
log():接收RequestInfo和AccessLog::AccessLogData,执行日志记录逻辑。logWithFilter():支持基于过滤条件的日志记录,避免全量日志带来的性能开销。
性能建议:在实现自定义 Logger 时,建议使用异步写入或批处理机制,避免在数据路径上阻塞。对于高吞吐场景,优先考虑 gRPC Access Log Service (ALS) 而非文件写入。
4.3.2 配置示例
以下配置展示了如何启用自定义 Access Logger 并指定日志格式:
static_resources:
listeners:
- name: my_listener
address:
socket_address: { address: 0.0.0.0, port_value: 10000 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: http
access_log:
- name: envoy.access_loggers.my_custom_logger
typed_config:
"@type": type.googleapis.com/myorg.accesslog.MyCustomLoggerConfig
log_path: "/var/log/envoy/custom_access.log"
log_format: "%START_TIME% %REQ(X-REQUEST-ID)% %RESPONSE_CODE% %DURATION%"
4.4 Stats 扩展点
Envoy 的统计系统(Stats)是其可观测性的基石。Stats 扩展点允许开发者注册自定义度量指标,包括 Counter(计数器)、Gauge(仪表盘)和 Histogram(直方图)。
4.4.1 自定义 Stats 注册流程
- 获取 Stats 作用域:通过
Stats::ScopeSharedPtr获取当前 Filter 的统计作用域。 - 定义指标结构体:使用
DECLARE_COUNTER、DECLARE_GAUGE等宏声明指标。 - 注册指标:在 Filter 初始化时调用
scope->counterFromString()等方法创建实例。 - 更新指标:在 Filter 回调中调用
counter_.inc()、gauge_.set()等方法。
4.4.2 典型指标设计
| 指标名称 | 类型 | 描述 |
|---|---|---|
custom_filter.requests_total |
Counter | 经过自定义 Filter 的总请求数 |
custom_filter.quota_rejected |
Counter | 因配额不足被拒绝的请求数 |
custom_filter.active_connections |
Gauge | 当前活跃连接数 |
custom_filter.request_duration_ms |
Histogram | 请求处理耗时分布 |
注意:自定义指标的名称应遵循 Envoy 的命名规范,使用点号分隔层级,避免与内置指标冲突。建议在指标名称前添加自定义前缀(如 custom_filter.)。
4.5 扩展注册与配置加载
Envoy 使用 Factory 注册模式 管理所有扩展。每个扩展类型(Filter、Logger、StatsSink 等)都有一个对应的 Factory 基类,开发者需要实现该基类并注册到全局注册表中。
4.5.1 注册流程
下图展示了自定义扩展从代码实现到配置加载的完整生命周期:
4.5.2 代码示例:自定义 Filter Factory
以下是一个简化的自定义 Network Filter Factory 实现,展示了注册和配置解析的核心逻辑:
#include "source/extensions/filters/network/common/factory_base.h"
namespace MyOrg {
namespace Filters {
namespace Network {
class MyCustomFilterFactory : public Envoy::Extensions::NetworkFilters::Common::FactoryBase<MyCustomFilterConfig> {
public:
MyCustomFilterFactory() : FactoryBase("myorg.filters.network.my_custom_filter") {}
private:
Envoy::Network::FilterFactoryCb
createFilterFactoryFromProtoTyped(const MyCustomFilterConfig& proto_config,
Envoy::Server::Configuration::FactoryContext& context) override {
auto filter = std::make_shared<MyCustomFilter>(proto_config, context);
return [filter](Envoy::Network::FilterManager& filter_manager) -> void {
filter_manager.addReadFilter(filter);
};
}
};
// 注册到全局 Registry
REGISTER_FACTORY(MyCustomFilterFactory,
Envoy::Server::Configuration::NamedNetworkFilterConfigFactory);
} // namespace Network
} // namespace Filters
} // namespace MyOrg
4.6 扩展点对比与选型建议
下表总结了四个扩展点的核心差异,帮助开发者在实际项目中做出正确选择:
| 扩展点 | 工作层级 | 数据访问粒度 | 典型延迟影响 | 适用场景 |
|---|---|---|---|---|
| Network Filter | L3/L4 | 连接/数据包 | 低(微秒级) | 协议解析、访问控制、配额检查 |
| Access Logger | L7 | 请求/响应 | 极低(异步) | 审计日志、流量分析、合规记录 |
| Stats 扩展点 | 跨层 | 指标聚合 | 极低(原子操作) | 可观测性、监控告警、容量规划 |
| 扩展注册与配置 | 控制面 | 配置元数据 | 仅启动/热加载时 | 扩展生命周期管理、动态配置 |
实践建议:在开发策略即代码资源配额模型时,推荐组合使用 Network Filter(执行配额检查逻辑)和 Stats 扩展点(记录配额使用指标),并通过 Access Logger 记录被拒绝的请求详情,形成完整的可观测性闭环。