WEBKT

Envoy Filter Chain 深度实践:从配置案例到性能优化,助你成为 Envoy 大师

34 0 0 0

1. Envoy Filter Chain 基础回顾

1.1 什么是 Filter?

1.2 什么是 Filter Chain?

1.3 Filter 的执行顺序

2. 常见的 Envoy Filter 及其应用场景

2.1 HTTP Filter

2.1.1 Router Filter

2.1.2 Header-To-Metadata Filter

2.1.3 Lua Filter

2.1.4 Rate Limit Filter

2.2 Network Filter

2.2.1 TCP Proxy Filter

3. Filter Chain 配置最佳实践

3.1 明确需求,精心设计

3.2 遵循 KISS 原则(Keep It Simple, Stupid)

3.3 关注 Filter 的执行顺序

3.4 使用 Metadata 进行数据传递

3.5 充分利用内置 Filter

3.6 编写清晰的注释

3.7 监控和日志记录

3.8 测试,测试,再测试

3.9 版本控制和持续集成

4. 进阶技巧:深入 Filter 开发

4.1 选择合适的编程语言

4.2 了解 Envoy 的 API

4.3 编写 Filter 代码

4.4 编译 Filter 代码

4.5 部署 Filter

4.6 配置 Filter Chain

5. 性能优化与故障排查

5.1 性能优化

5.2 故障排查

6. 总结与展望

大家好,我是老码农小李。今天,咱们来聊聊 Envoy 这个强大的服务网格代理。Envoy 的核心优势之一就是其灵活的 Filter Chain(过滤器链)机制,它允许我们像搭积木一样定制 Envoy 的行为,从而实现各种复杂的功能,例如:流量控制、安全防护、日志记录、请求修改等等。如果你已经对 Envoy 有一定的了解,并且想在实际项目中更深入地应用 Filter Chain,那么这篇文章绝对适合你!

1. Envoy Filter Chain 基础回顾

在深入实践之前,我们先来简单回顾一下 Envoy Filter Chain 的基础知识,确保大家对基本概念有一个清晰的认识。

1.1 什么是 Filter?

Envoy 中的 Filter 就像一个个插件,它们可以拦截并处理 Envoy 代理的流量。每个 Filter 都有自己的特定功能,例如:

  • HTTP Filter: 用于处理 HTTP 流量,包括修改请求头、响应头、body,进行路由、负载均衡等。
  • TCP Filter: 用于处理 TCP 流量,主要用于底层 TCP 连接的处理,例如:连接限速、流量镜像等。
  • Network Filter: 类似于 TCP Filter,但功能更强大,可以实现更复杂的 TCP 协议处理。

1.2 什么是 Filter Chain?

Filter Chain 就是将多个 Filter 按照一定的顺序串联起来,形成一个处理链。当请求或响应经过 Envoy 时,会依次经过 Filter Chain 中的每个 Filter,每个 Filter 都可以对流量进行处理,从而实现复杂的功能。

Filter Chain 可以在不同的层面进行配置,例如:

  • Listener Filter Chain: 作用于 Listener 层面,处理所有进入 Envoy 的流量。
  • HTTP Filter Chain: 作用于 HTTP Connection Manager (HCM) 内部,处理 HTTP 请求和响应。
  • Route Filter Chain: 作用于 Route 层面,处理特定路由的流量。

1.3 Filter 的执行顺序

Filter 的执行顺序至关重要。Envoy 会按照 Filter 在配置中出现的顺序依次执行它们。这意味着,如果两个 Filter 相互依赖,那么它们的顺序会直接影响最终的结果。例如,一个修改请求头的 Filter 应该在路由 Filter 之前执行,这样路由 Filter 才能根据修改后的请求头进行路由。

2. 常见的 Envoy Filter 及其应用场景

Envoy 提供了丰富的内置 Filter,可以满足各种常见的需求。下面,我将介绍几个常用的 Filter,并结合实际场景,演示如何配置和使用它们。

2.1 HTTP Filter

2.1.1 Router Filter

功能: 路由 Filter 是 HTTP Filter Chain 中最核心的 Filter 之一,它负责将请求路由到不同的 Upstream 集群。配置路由规则是 Envoy 最重要的任务之一。

应用场景: 实现流量的负载均衡、灰度发布、蓝绿部署等。

配置示例: (以 YAML 格式为例)

http_filters:
- name: envoy.filters.http.router
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

详细说明: 这段配置将 Router Filter 添加到 HTTP Filter Chain 中。Router Filter 会根据 Listener、VirtualHost、Route 等配置,将请求路由到相应的 Upstream 集群。你需要在 route_config 部分配置具体的路由规则,例如根据 Host、Path、Header 等信息进行路由。

2.1.2 Header-To-Metadata Filter

功能: 将 HTTP 请求头中的信息提取出来,作为 Metadata 添加到 Envoy 的上下文中。Metadata 可以在后续的 Filter 中使用,例如:用于日志记录、流量控制等。

应用场景: 将客户端的请求信息(例如:用户 ID、设备类型)传递给下游服务,或者用于流量统计和监控。

配置示例: (以 YAML 格式为例)

http_filters:
- name: envoy.filters.http.header_to_metadata
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config
request_rules:
- header: x-user-id
metadata_namespace: envoy.lb
key: user_id

详细说明: 这段配置将 x-user-id 请求头的值提取出来,作为 Metadata 存储在 envoy.lb 命名空间下的 user_id 键中。后续的 Filter,例如:envoy.filters.http.lua,就可以访问这个 Metadata,并进行相应的处理。

2.1.3 Lua Filter

功能: 允许使用 Lua 脚本自定义 Envoy 的行为。Lua Filter 提供了强大的扩展能力,可以实现各种复杂的功能,例如:自定义认证、授权、限流、请求修改等。

应用场景: 实现自定义的逻辑处理,弥补内置 Filter 的不足。

配置示例: (以 YAML 格式为例)

http_filters:
- name: envoy.filters.http.lua
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Config
inline_code: |
function envoy_on_request(request_handle)
local user_id = request_handle:headers():get("x-user-id")
if user_id == nil then
request_handle:respond(envoy.headers({{":status", "401"}}), "Unauthorized")
return
end
request_handle:logInfo("User ID: " .. user_id)
end

详细说明: 这段配置定义了一个 Lua Filter,它在请求到达时执行。Lua 脚本首先从请求头中获取 x-user-id。如果 x-user-id 不存在,则返回 401 状态码,拒绝请求。否则,记录用户 ID 到 Envoy 的日志中。这个例子展示了 Lua Filter 的基本用法,你可以根据自己的需求编写更复杂的 Lua 脚本。

2.1.4 Rate Limit Filter

功能: 实现请求限流,保护上游服务,防止过载。

应用场景: 限制特定用户的请求频率、限制特定 API 的调用频率、防止恶意攻击。

配置示例: (以 YAML 格式为例)

http_filters:
- name: envoy.filters.http.ratelimit
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
domain: my_domain
stat_prefix: ratelimit
rate_limit_service:
grpc_service:
envoy_grpc:
cluster_name: ratelimit_cluster
timeout: 0.5s

详细说明: 这段配置使用 gRPC 服务来实现限流。Envoy 会向 ratelimit_cluster 集群发送请求,询问是否允许当前请求通过。你需要在 rate_limit_service 中配置 gRPC 服务的地址。此外,你还需要在 Envoy 的配置中定义 ratelimit_cluster 集群。

2.2 Network Filter

2.2.1 TCP Proxy Filter

功能: 用于代理 TCP 连接,可以实现 TCP 流量的转发和负载均衡。

应用场景: 代理数据库连接、消息队列连接、以及其他基于 TCP 的服务。

配置示例: (以 YAML 格式为例)

network_filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: tcp_proxy
cluster: my_tcp_cluster

详细说明: 这段配置将 TCP Proxy Filter 添加到 Network Filter Chain 中。它将所有 TCP 连接转发到 my_tcp_cluster 集群。你需要配置 my_tcp_cluster 集群,指定后端服务的地址和端口。

3. Filter Chain 配置最佳实践

了解了 Filter 的基本概念和常用 Filter 之后,接下来,我们来探讨一下 Filter Chain 配置的最佳实践,帮助你更好地在实际项目中应用 Envoy。

3.1 明确需求,精心设计

在配置 Filter Chain 之前,首先要明确需求,例如:你需要实现什么功能?需要保护哪些服务?需要监控哪些指标?然后,根据需求设计 Filter Chain 的结构,选择合适的 Filter,并确定它们的执行顺序。

示例: 假设你需要实现以下功能:

  1. 身份认证: 验证用户是否合法。
  2. 限流: 限制每个用户的请求频率。
  3. 路由: 将请求路由到不同的服务。
  4. 日志记录: 记录请求的详细信息。

在这种情况下,你可以这样设计 Filter Chain:

  1. HTTP Filter Chain: 按照如下顺序配置 Filter:
    • JWT Filter: 进行 JWT 认证。
    • Rate Limit Filter: 进行限流。
    • Router Filter: 进行路由。
    • Access Log Filter: 进行日志记录。

3.2 遵循 KISS 原则(Keep It Simple, Stupid)

Filter Chain 越简单,越容易理解和维护。尽量避免过度复杂的配置。如果一个功能可以用多个 Filter 实现,优先选择最简单、最易于理解的方式。

示例: 如果需要修改请求头,可以使用 envoy.filters.http.lua Filter 或者 envoy.filters.http.header_to_metadata Filter。如果只是简单的修改,envoy.filters.http.header_to_metadata Filter 更简单,也更容易理解。

3.3 关注 Filter 的执行顺序

Filter 的执行顺序对最终结果有很大的影响。要仔细考虑每个 Filter 的功能和依赖关系,确保它们的执行顺序符合预期。

示例: 如果需要根据请求头中的信息进行路由,那么修改请求头的 Filter 应该在 Router Filter 之前执行。

3.4 使用 Metadata 进行数据传递

Metadata 是一种非常有效的在 Filter 之间传递数据的方式。通过使用 Metadata,你可以将请求头中的信息、认证信息、限流信息等传递给后续的 Filter,从而实现更复杂的功能。

示例: 可以使用 Header-To-Metadata Filter 将请求头中的用户 ID 提取出来,作为 Metadata 存储。然后,Rate Limit Filter 可以根据 Metadata 中的用户 ID 进行限流,Access Log Filter 可以记录 Metadata 中的用户 ID。

3.5 充分利用内置 Filter

Envoy 提供了丰富的内置 Filter,可以满足各种常见的需求。优先使用内置 Filter,可以减少自定义代码的编写,提高效率和稳定性。

示例: 如果需要进行负载均衡,可以使用 Router Filter。如果需要进行限流,可以使用 Rate Limit Filter。不要重复造轮子。

3.6 编写清晰的注释

Filter Chain 的配置通常比较复杂,需要仔细阅读和理解。为了方便后续的维护和排查问题,应该在配置文件中添加清晰的注释,说明每个 Filter 的功能、配置选项的含义、以及 Filter 的执行顺序。

示例: 在 YAML 配置文件中,可以使用 # 符号添加注释。

http_filters:
- name: envoy.filters.http.jwt_auth
# JWT 认证 Filter
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
providers:
...

3.7 监控和日志记录

为了确保 Envoy 的正常运行,需要监控 Envoy 的各项指标,并记录详细的日志。Envoy 提供了丰富的监控指标,例如:请求数量、响应时间、错误率等。可以使用 Prometheus、Grafana 等工具进行监控。

示例: 可以使用 Access Log Filter 记录请求的详细信息,包括:请求头、响应头、状态码、响应时间等。然后,将日志输出到文件或者其他日志系统,例如:ELK Stack、Splunk 等。

3.8 测试,测试,再测试

配置 Filter Chain 之后,一定要进行充分的测试。可以使用各种测试工具,例如:curl、Postman 等,模拟不同的请求,测试 Filter Chain 的功能是否正常,性能是否满足要求。

示例: 测试身份认证、限流、路由等功能是否正常。测试在不同负载下的性能表现。测试在出现错误时的处理方式。

3.9 版本控制和持续集成

将 Envoy 的配置文件纳入版本控制系统,例如:Git。使用持续集成工具,例如:Jenkins、GitLab CI 等,自动化地构建、测试和部署 Envoy 的配置,可以提高效率和减少错误。

4. 进阶技巧:深入 Filter 开发

除了使用内置 Filter,Envoy 还支持自定义 Filter 的开发,这可以让你实现更强大的功能,满足更个性化的需求。下面,我们简单介绍一下自定义 Filter 的开发流程。

4.1 选择合适的编程语言

Envoy 支持多种编程语言开发自定义 Filter,包括:C++、Lua、Go 等。C++ 是 Envoy 的主要开发语言,性能最好,但开发难度也最高。Lua 适合快速开发原型,Go 是一种相对容易上手的语言。

4.2 了解 Envoy 的 API

开发自定义 Filter 必须了解 Envoy 的 API,例如:

  • Filter 的生命周期: Filter 的创建、初始化、处理请求、处理响应等。
  • 请求和响应的访问: 访问请求头、响应头、body 等。
  • 上下文信息的访问: 访问 Metadata、日志信息等。
  • 错误处理: 处理各种错误情况。

4.3 编写 Filter 代码

根据需求编写 Filter 的代码。需要实现 Filter 的核心逻辑,例如:处理请求、修改请求、转发请求、处理响应、修改响应等。

示例 (Go 语言): 一个简单的自定义 HTTP Filter,用于修改请求头。

package main
import (
"fmt"
"log"
"os"
"github.com/envoyproxy/go-control-plane/envoy/service/extensions/v3"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
)
// 定义 Filter 的配置结构体
type MyHeaderModifierConfig struct {
HeaderName string `json:"header_name"`
HeaderValue string `json:"header_value"`
}
// 定义 Filter 的实现结构体
type MyHeaderModifier struct {
config *MyHeaderModifierConfig
}
// 实现 Filter 的 NewHttpFilter 方法
func NewMyHeaderModifier(config *MyHeaderModifierConfig) (*MyHeaderModifier, error) {
if config == nil {
return nil, fmt.Errorf("config is nil")
}
if config.HeaderName == "" || config.HeaderValue == "" {
return nil, fmt.Errorf("header_name and header_value cannot be empty")
}
return &MyHeaderModifier{config: config},
}
// 实现 Filter 的 OnHttpRequestHeaders 方法
func (f *MyHeaderModifier) OnHttpRequestHeaders(headers map[string]string, endStream bool) {
headers[f.config.HeaderName] = f.config.HeaderValue
}
// ... (其他 Filter 方法的实现,例如:OnHttpRequestBody, OnHttpResponseHeaders, etc.)
func main() {
// ... (Envoy 配置加载和 Filter 注册)
// 示例配置
config := &MyHeaderModifierConfig{HeaderName: "x-custom-header", HeaderValue: "hello"}
filter, err := NewMyHeaderModifier(config)
if err != nil {
log.Fatalf("failed to create filter: %v", err)
}
// ... (Envoy 请求处理逻辑)
}

说明: 这个示例用 Go 语言实现了一个自定义的 HTTP Filter,它会在 HTTP 请求头中添加一个自定义的 Header。你需要根据自己的需求,修改代码,实现更复杂的功能。

4.4 编译 Filter 代码

使用相应的工具,例如:CMake、Go Build 等,编译 Filter 代码,生成 Filter 的二进制文件或者共享库。

4.5 部署 Filter

将编译好的 Filter 部署到 Envoy 所在的服务器上。Envoy 会通过插件机制加载和运行自定义 Filter。

4.6 配置 Filter Chain

在 Envoy 的配置文件中,配置 Filter Chain,将自定义 Filter 添加到 Filter Chain 中,并指定 Filter 的配置参数。

示例 (YAML):

http_filters:
- name: my_header_modifier
typed_config:
'@type': type.googleapis.com/google.protobuf.Struct
value:
header_name: x-custom-header
header_value: modified_value

说明: 这段配置将自定义的 my_header_modifier Filter 添加到 HTTP Filter Chain 中。typed_config 部分是 Filter 的配置参数。你需要将 Filter 的名称和配置参数设置为正确的值。

5. 性能优化与故障排查

除了功能实现,性能优化和故障排查也是使用 Envoy 的重要环节。下面,我将分享一些相关的经验。

5.1 性能优化

  • 选择合适的 Filter: 避免使用过于复杂的 Filter,尽量选择性能更好的 Filter。
  • 优化 Filter 的执行顺序: 将耗时的 Filter 放在靠后的位置,避免阻塞请求处理。
  • 使用连接池: Envoy 默认使用连接池,可以提高连接复用率,减少连接建立的开销。
  • 调整并发度: 根据服务器的 CPU 和内存资源,调整 Envoy 的并发度。
  • 启用缓存: 对于静态资源,可以启用缓存,减少请求的响应时间。
  • 监控性能指标: 监控 Envoy 的各项性能指标,例如:请求数量、响应时间、CPU 使用率、内存使用率等,及时发现性能瓶颈。

5.2 故障排查

  • 查看 Envoy 的日志: Envoy 的日志记录了详细的请求处理信息,包括:错误信息、警告信息等。可以通过查看日志,快速定位问题。
  • 使用 Envoy 的管理 API: Envoy 提供了管理 API,可以用于获取 Envoy 的状态信息、配置信息、统计信息等,帮助你诊断问题。
  • 使用调试工具: 可以使用调试工具,例如:gdb、lldb 等,调试 Envoy 的代码,定位问题。 (如果需要调试自定义 Filter,可以尝试)。
  • 简化配置: 如果遇到问题,可以尝试简化 Envoy 的配置,例如:禁用一些 Filter,缩小问题的范围。
  • 升级 Envoy: 升级到最新版本的 Envoy,可以修复一些已知的 Bug,提高稳定性和性能。

6. 总结与展望

Envoy Filter Chain 是一个强大的工具,可以帮助你实现各种复杂的功能,提高项目的性能和可维护性。通过本文的介绍,我相信你已经对 Envoy Filter Chain 有了更深入的了解,并掌握了配置和使用的最佳实践。

总的来说,掌握 Envoy Filter Chain 的关键在于:

  1. 理解 Filter 的基本概念: Filter 的类型、执行顺序、作用等。
  2. 熟悉常用的内置 Filter: Router Filter、Header-To-Metadata Filter、Lua Filter 等。
  3. 遵循最佳实践: 明确需求、精心设计、关注执行顺序、使用 Metadata、充分利用内置 Filter、编写清晰的注释、监控和日志记录、测试、版本控制和持续集成。
  4. 掌握自定义 Filter 的开发流程: 选择合适的编程语言、了解 Envoy 的 API、编写 Filter 代码、编译 Filter 代码、部署 Filter、配置 Filter Chain。
  5. 关注性能优化和故障排查: 选择合适的 Filter、优化执行顺序、使用连接池、调整并发度、启用缓存、监控性能指标、查看日志、使用管理 API、使用调试工具、简化配置、升级 Envoy。

随着云原生技术的不断发展,服务网格正在成为微服务架构的核心组成部分。Envoy 作为服务网格代理的事实标准,将会发挥越来越重要的作用。我希望这篇文章能帮助你更好地使用 Envoy,成为 Envoy 大师!

未来,Envoy 还会不断发展,推出更多的新特性和功能。例如,Envoy 的 WebAssembly (Wasm) 支持,可以让你使用多种语言开发自定义 Filter,扩展 Envoy 的能力。请持续关注 Envoy 的发展,不断学习和探索!

希望这篇文章对你有所帮助!如果你有任何问题或者建议,欢迎在评论区留言。 咱们下次再见!

老码农小李 EnvoyFilter Chain服务网格性能优化自定义Filter

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/8193