在Envoy中,虚拟主机(Virtual Host)和路由(Route)是配置HTTP请求路由的重要概念。
一、Envoy HTTP路由配置框架
1.1 虚拟主机(Virtual Host)
虚拟主机是Envoy中用于根据请求的主机头(Host Header)来匹配请求的一种机制。它允许你在同一个Envoy实例中处理多个域名或服务。

在Envoy中,HTTP路由是通过路由配置来实现的,这是Envoy的核心功能之一。Envoy作为一个边缘和服务代理,提供了丰富的路由功能,能够管理微服务架构中的流量。下面是Envoy中HTTP路由及配置框架的一些关键组件和概念:
路由配置 (Route Configuration)
Envoy的路由配置通常在其配置文件中定义,主要包括虚拟主机(virtual hosts)、路由条目(route entries)和路由表(route tables)。这些配置可以静态定义,也可以通过xDS API动态获取。
虚拟主机 (Virtual Hosts)
虚拟主机是一组路由规则的集合,它们基于请求的域名(例如 Host头部)来进行匹配。每个虚拟主机包含一个或多个路由规则,用于根据路径、请求头等信息将流量路由到不同的后端服务。
路由条目 (Route Entries)
每个路由条目定义了单个路由规则。它包含匹配条件和路由行为,如重定向、直接响应或将请求转发到指定的集群。路由条目可以根据请求路径、请求头、HTTP方法等条件进行匹配。
集群 (Clusters)
集群是Envoy用来管理后端服务的节点。每个集群包含一个或多个服务实例,Envoy将根据路由配置将流量分发到这些实例。集群支持多种发现和健康检查机制。
示例配置
这是一个简单的Envoy路由配置示例:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: backend_service
clusters:
- name: backend_service
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
hosts:
- socket_address:
address: backend
port_value: 80
在这个配置中,所有到达端口80的HTTP请求都将由 envoy.http_connection_manager处理,并根据定义的路由规则路由到后端服务。
Envoy的HTTP路由配置非常灵活且功能强大,能够应对各种复杂的路由需求,并支持高度的动态配置和扩展。
1.2 虚拟主机在Envoy路由中的作用和行为
在Envoy的HTTP路由配置中,顶级元素通常是虚拟主机(Virtual Host)。以下描述了虚拟主机在Envoy路由中的作用和行为:
虚拟主机的定义和作用
- 逻辑名称与域名集合:每个虚拟主机在配置中有一个唯一的逻辑名称(
name),这是为了在配置文件中标识不同的虚拟主机。此外,虚拟主机还定义了一组域名(domains),这些域名用于匹配进入Envoy的请求中的Host头部。这意味着,当一个HTTP请求到达Envoy时,Envoy会查看请求的Host头部,并将其与虚拟主机配置的域名进行比较,以决定该请求应该由哪个虚拟主机处理。
路由决策过程
- 域名匹配后的路由处理:一旦基于域名匹配到一个虚拟主机,接下来的处理就是根据该虚拟主机下配置的路由规则(
routes)来决定如何处理请求。这些路由规则可以定义多种行为,包括:- 路由到后端集群:最常见的行为是将请求路由到一个后端服务或集群。这通常涉及到更细粒度的匹配条件,如请求的路径(
prefix、path或使用正则表达式等),请求方法等。 - 重定向:路由规则还可以配置为对某些请求执行HTTP重定向,例如从HTTP自动重定向到HTTPS,或者从一个旧的URL重定向到新的URL。
- 路由到后端集群:最常见的行为是将请求路由到一个后端服务或集群。这通常涉及到更细粒度的匹配条件,如请求的路径(
这种基于虚拟主机的路由机制使得Envoy能够非常灵活地处理来自不同域的请求,并且可以在同一个Envoy实例上配置多个虚拟主机,每个主机都有自己独立的路由策略。这对于运行多个服务或应用在同一物理服务器上的情况非常有用,也支持微服务架构中服务的隔离和独立路由决策。
这是一个结构化的Envoy配置示例,包含监听器、过滤器链、HTTP连接管理器以及路由配置。
listeners:
- name: <listener_name> # 监听器的名称
address: {...} # 监听器的地址配置
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: ingress_http # 统计数据前缀
codec_type: AUTO # 编解码器类型
route_config:
name: <route_config_name> # 路由配置的名称
virtual_hosts:
- name: <virtual_host_name> # 虚拟主机的名称
domains: [] # 与此虚拟主机相关联的域名列表
routes:
- name: <route_name> # 路由条目的名称
match:
{...} # 路由匹配条件,可以基于路径前缀、完整路径、正则表达式或连接匹配器
route:
{...} # 路由目标,可以是集群、基于请求头的集群或加权集群
redirect:
{...} # 重定向配置
direct_response:
{...} # 直接响应配置
virtual_clusters: [] # 虚拟集群列表,用于统计信息
关键元素说明:
- listeners: 这是配置文件的顶级元素,其中包括所有监听器的定义。每个监听器负责在特定的网络地址上监听入站连接。
- filter_chains: 每个监听器可以有多个过滤器链,用于处理通过该监听器的数据流。
- filters: 指定使用的过滤器类型,这里使用的是
envoy.filters.network.http_connection_manager,专门处理HTTP连接。 - typed_config: 具体到HTTP连接管理器的配置,包括路由配置。
- route_config: 定义了如何处理通过HTTP连接管理器的请求,包括一个或多个虚拟主机。
- virtual_hosts: 每个虚拟主机根据请求的
Host头部匹配特定的域名,并定义一系列的路由规则。 - routes: 每个路由定义了匹配条件和处理动作,包括直接路由到后端集群、重定向或直接响应。
这种配置方式为Envoy提供了高度的灵活性和强大的流量管理能力,使其成为处理复杂网络环境中的请求的理想选择。
实际应用配置示例
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
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: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "example.com"
- "www.example.com"
routes:
- match:
prefix: "/"
route:
cluster: service_cluster
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: service_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8081
在上述配置中,虚拟主机 local_service 用于匹配请求主机头为 example.com 或 www.example.com 的请求。
二、Envoy HTTP路由(Route)
路由是指根据请求的路径、方法、头信息等将请求转发到特定的后端服务。它定义了当请求匹配某个虚拟主机后,如何处理这个请求。
2.1 路由配置
在虚拟主机下,你可以配置一个或多个路由,每个路由包括匹配条件(match)和处理方式(route)。
简单配置示例
routes:
- match:
prefix: "/"
route:
cluster: service_cluster
- match:
prefix: "/api"
route:
cluster: api_service_cluster
在上述配置中,有两个路由规则:
- 匹配所有路径(
/),请求将被转发到service_cluster。 - 匹配路径以
/api开头的请求,将被转发到api_service_cluster。
路由配置详细解释
match:定义请求匹配条件。可以是路径前缀(prefix),完全路径(path),正则表达式(regex)等。route:定义匹配到请求后的处理方式。主要指定转发的后端集群(cluster),还可以定义超时时间、重试策略、负载均衡等。
详细路由配置示例
下面是一个更详细的路由配置示例,包含更多的匹配条件和处理选项:
routes:
- match:
prefix: "/"
headers:
- name: "x-custom-header"
exact_match: "value"
route:
cluster: service_cluster
timeout: 0.5s
retry_policy:
retry_on: "5xx"
num_retries: 3
per_try_timeout: 0.2s
在这个示例中,路由规则匹配路径为 / 且请求头 x-custom-header 为 value 的请求。匹配后,将请求转发到 service_cluster,并配置了超时时间和重试策略。
2.2 路由配置步骤
- 定义虚拟主机:在虚拟主机中定义多个域名。
- 添加路由规则:在虚拟主机中添加一个或多个路由规则。
- 设置匹配条件:在路由规则中设置路径、请求头等匹配条件。
- 配置转发选项:在路由规则中配置转发的后端集群、超时、重试等选项。
通过以上步骤,可以灵活地根据请求的不同属性配置Envoy的路由策略,从而实现流量的精确控制和管理。
2.3 路由匹配(match)
在Envoy中,路由匹配(match)用于定义如何筛选进入的流量并匹配特定的路由规则。路由匹配可以根据请求路径、请求头、查询参数等进行配置。主要包括基础匹配和高级匹配两类。

2.3.1 基础匹配
- prefix: 按路径前缀匹配。
- path: 按完全路径匹配。
- safe_regex: 按正则表达式匹配。
2.3.2 高级匹配
- headers: 按请求头匹配。
- query_parameters: 按查询参数匹配。
通过这些匹配条件,可以将进入的流量基于报文的某些特征筛选出来,进行匹配或流量筛选,从而将其交换或路由到某个特定的路径上去。
配置示例
routes:
- match:
prefix: "/api"
headers:
- name: "x-custom-header"
exact_match: "custom_value"
query_parameters:
- name: "user"
string_match:
exact: "admin"
route:
cluster: api_service_cluster
- match:
safe_regex:
google_re2: {}
regex: "^/user/.*"
route:
cluster: user_service_cluster
- 第一条路由规则匹配路径前缀为
/api且请求头x-custom-header为custom_value且查询参数user为admin的请求。 - 第二条路由规则使用正则表达式匹配路径以
/user/开头的请求。
2.4 路由处理方式
2.4.1 重定向 (redirect)
重定向规则用于将请求重定向到另一个URL。可以配置301或302重定向。
配置示例
routes:
- match:
prefix: "/old-path"
redirect:
path_redirect: "/new-path"
response_code: 301
2.4.2 直接响应 (direct_response)
直接响应规则用于由Envoy直接响应请求,而不转发给其他上游服务处理。可以配置静态响应内容和状态码。
配置示例
routes:
- match:
prefix: "/healthcheck"
direct_response:
status: 200
body:
inline_string: "Healthy"
在这个示例中,请求匹配路径前缀为 /healthcheck 的请求将由Envoy直接响应,返回状态码200和响应体"Healthy"。
2.5 Envoy匹配路由工作过程
Envoy作为一个高度灵活的代理,通过详细的配置实现对入站HTTP请求的精确路由。这一过程主要涉及三个关键步骤,如下所述:
匹配虚拟主机
- 检测HTTP请求的
Host头部或:authority:当HTTP请求到达Envoy时,Envoy首先检查请求中的Host头部或HTTP/2的:authority头部。这些头部包含了发起请求的域名信息。 - 与虚拟主机域名进行匹配:Envoy将这个域名与路由配置中定义的所有虚拟主机的域名进行匹配。每个虚拟主机可以配置一个或多个域名。Envoy选择第一个域名匹配的虚拟主机来处理该请求。
匹配路由条目
- 按顺序检查路由条目:在找到合适的虚拟主机后,Envoy将按照定义的顺序遍历这个虚拟主机中的每个路由条目。每个路由条目都有其自己的匹配条件,这些条件可以基于请求的路径、HTTP方法、请求头等信息。
- 第一个匹配的路由条目:Envoy使用“短路”逻辑来处理匹配,即一旦找到第一个符合条件的路由条目,就停止进一步的检查,并按照该路由条目定义的指令处理请求。这可能包括将请求路由到一个后端集群、执行重定向或直接返回一个响应。
虚拟集群的匹配(如果配置)
- 检查虚拟集群:如果在虚拟主机配置中定义了虚拟集群,Envoy还会进行额外的匹配检查。虚拟集群主要用于流量的细粒度统计,不影响路由决策。
- 虚拟集群匹配:Envoy会按顺序检查每个定义的虚拟集群的匹配条件,直到找到第一个匹配的虚拟集群。匹配成功的虚拟集群会被用来收集该请求的统计数据。
这个路由匹配过程确保Envoy可以处理各种复杂的路由场景,并且通过优先匹配的逻辑提供高效的请求处理。
当然,这里有一个更详细的YAML配置示例,说明了一个Envoy监听器配置。该配置包含了路由处理和虚拟主机的详细信息。
listeners:
- name: main_listener
address:
socket_address:
address: 0.0.0.0
port_value: 80
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: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["local.example.com"] # 虚拟主机的域名,用于匹配请求中的Host头部
routes:
- name: home_page
match:
prefix: "/" # 匹配所有以"/"开始的请求路径
route:
cluster: home_service # 将匹配的请求路由到名为home_service的集群
- name: api
match:
prefix: "/api" # 匹配所有以"/api"开始的请求路径
route:
cluster: api_cluster # 将匹配的请求路由到名为api_cluster的集群
virtual_clusters:
- name: api_stats
pattern: "^/api/.*$" # 使用正则表达式匹配所有API请求
method: GET # 只统计GET方法的请求
解释
- listeners: 这是顶层元素,包含所有的监听器配置。
- name: 监听器的名称,这里是"main_listener"。
- address:
- socket_address: 指定监听器的网络地址。
- address: 监听的IP地址,这里是"0.0.0.0"表示监听所有接口。
- port_value: 监听的端口号,这里是80,HTTP默认端口。
- socket_address: 指定监听器的网络地址。
- filter_chains:
- filters:
- name: 使用的过滤器名称,这里是
envoy.filters.network.http_connection_manager,它管理HTTP连接。 - typed_config: 过滤器的详细配置。
- @type: 配置类型,指定为HTTP连接管理器的v3版本。
- stat_prefix: 用于统计的前缀,这里是"ingress_http"。
- codec_type: 解码类型,自动选择适当的HTTP编解码器。
- name: 使用的过滤器名称,这里是
- filters:
- route_config: 路由配置的详细信息。
- name: 路由配置的名称,这里是"local_route"。
- virtual_hosts: 包含一组虚拟主机配置。
- name: 虚拟主机的名称,这里是"local_service"。
- domains: 这个虚拟主机处理的域名列表,这里只有"local.example.com"。
- routes: 定义如何处理匹配到此虚拟主机的请求。
- name: 路由的名称,例如"home_page"和"api"。
- match: 定义匹配条件,如前缀"/"和"/api"。
- route: 定义路由目标,指定集群如"home_service"和"api_cluster"。
- virtual_clusters: 定义用于统计信息的虚拟集群。
- name: 虚拟集群的名称,例如"api_stats"。
- pattern: 匹配模式,这里使用正则表达式匹配所有"/api/.*$"路径。
- method: 指定要统计的HTTP方法,这里是"GET"。
这个配置示例展示了如何在Envoy中设置监听器来处理不同类型的HTTP请求,并将它们路由到不同的后端服务,同时也如何收集特定请求的统计信息。
三、Envoy线程模型回顾
3.1 Envoy线程模型的作用
在讨论Envoy的虚拟主机和路由配置时,提到Envoy的线程模型是非常重要的,因为Envoy的线程模型直接影响到其性能、并发处理能力以及配置策略的有效性。以下是一些关键原因:
性能优化
Envoy采用多线程模型,每个工作线程处理一个事件循环。在这样的模型下:
- 无锁并发:每个线程独立处理自己的事件循环,避免了跨线程的锁竞争,提升了性能。
- 高效的事件驱动:每个线程负责处理一部分连接和请求,通过事件驱动模型高效地管理I/O操作。
并发处理能力
Envoy的线程模型允许它同时处理大量并发连接:
- 线程池:Envoy在启动时创建固定数量的工作线程,默认与机器的CPU核心数相同。每个线程独立处理请求,从而提高了并发处理能力。
- 连接分配:新连接被轮询分配给不同的线程,这样可以均匀地分担负载,防止单个线程成为瓶颈。
配置策略的有效性
了解线程模型对于配置虚拟主机和路由策略至关重要,因为:
- 配置一致性:Envoy的配置在多个线程间是一致的,所有线程共享同一个配置,这保证了配置的统一性和一致性。
- 动态配置更新:Envoy支持动态配置更新,在更新配置时,所有线程会同步更新,保证了配置的即时生效。
资源管理
Envoy的线程模型还影响资源管理和调优策略:
- 资源隔离:通过多个线程处理请求,可以实现资源的隔离,防止单个请求影响整个系统的性能。
- 负载均衡:通过将连接均匀分配给不同线程,可以实现更好的负载均衡,提高系统的稳定性和响应速度。
3.2 Envoy线程模型架构
理解Envoy的单进程/多线程架构模型,可以更好地了解其高效性能和可扩展性。下面详细解释一下每个部分的内容:
3.2.1 架构模型概述
Envoy使用单进程/多线程的架构模型,这意味着Envoy作为一个单一的进程运行,内部通过多个线程来处理不同的任务。

3.2.2 主线程(Main Thread)
主线程是Envoy的核心管理线程,负责多个关键管理任务:
- 启动和关闭:负责Envoy程序的启动和关闭,包括初始化配置和资源。
- xDS API调用处理:处理与xDS API的交互,xDS(Extensible Service Discovery and Configuration)是Envoy用来动态获取配置信息的机制。包括集群管理、服务发现、负载均衡等。
- DNS和健康状态检测:管理DNS解析和集群健康检查,确保服务的可用性。
- 运行时配置:管理运行时配置更新,允许动态修改配置而无需重启Envoy。
- 统计数据刷新:定期刷新和维护统计数据,用于监控和分析。
- 线程管理:维护其他工作线程,包括信号处理和热重启等操作。
主线程中的所有事件都是以异步非阻塞模式完成的,这确保了高效的管理操作,不会阻塞其他工作线程的执行。
主线程负责Envoy的管理和控制任务,它的职责包括:
- xDS:处理与xDS API的交互,管理动态配置,包括服务发现和负载均衡。
- Runtime:管理运行时配置,允许动态修改配置而无需重启Envoy。
- Stat flush:负责统计数据的刷新和维护,提供监控和分析信息。
- Admin:维护管理接口,提供操作和控制功能。
- Process management:处理信号和热重启等进程管理任务。
主线程以异步非阻塞的方式处理这些任务,确保不会阻塞其他线程的执行。
3.2.3 工作线程(Worker Threads)
工作线程是Envoy处理实际代理功能的核心:
- 线程数量:默认情况下,Envoy根据主机的CPU核心数创建等量的工作线程,管理员也可以通过
--concurrency选项指定具体数量。 - 非阻塞事件循环:每个工作线程运行一个非阻塞的事件循环,负责处理监听器分配的套接字、接收新请求,并初始化和管理过滤器栈。
- 请求处理:处理请求的整个生命周期,包括解析请求、应用过滤器和转发请求等。
工作线程负责实际的请求处理,每个工作线程包含以下部分:
- Listeners:监听器,负责接受新连接。Envoy可以配置多个监听器,每个监听器可以监听不同的端口和协议。
- Connections:连接管理,处理每个连接的生命周期,包括请求的接收、解析、处理和响应。
每个工作线程运行一个非阻塞事件循环,确保高效地处理大量并发连接。默认情况下,Envoy会根据主机的CPU核心数创建等量的工作线程,但也可以通过 --concurrency选项指定具体数量。
3.2.4 文件刷写线程(File Flush Thread)
文件刷写线程负责Envoy的日志和其他文件写入操作:
- 独立线程:每个文件写入操作都有一个专用的独立阻塞型刷写线程。
- 内存缓冲区:工作线程将数据写入内存缓冲区,然后由文件刷写线程同步写入文件。
- 同步刷写:确保数据最终一致性和文件的持久化存储。
文件刷写线程负责Envoy的日志和其他文件写入操作。每个文件写入都有一个独立的阻塞型刷写线程:
- 内存缓冲区:工作线程将数据写入内存缓冲区。
- 文件同步:文件刷写线程将内存缓冲区中的数据同步写入文件,确保数据的一致性和持久性。
总结
Envoy的单进程/多线程架构模型实现了高效的资源管理和任务处理:
- 主线程处理管理任务和动态配置,确保代理的可用性和灵活性。
- 工作线程并发处理实际的请求,提供高性能的代理服务。
- 文件刷写线程确保日志和数据的持久化,独立于主线程和工作线程,避免阻塞核心代理功能。
这种架构使Envoy能够在高负载和高并发的环境中高效运行,同时提供动态配置和灵活管理的能力。
四、Envoy连接处理流程

- Worker Thread
- 工作线程负责处理具体的请求。Envoy根据主机的CPU核心数创建等量的工作线程(可通过
--concurrency选项指定数量)。每个工作线程运行一个非阻塞事件循环来处理请求。
- 工作线程负责处理具体的请求。Envoy根据主机的CPU核心数创建等量的工作线程(可通过
- Listener Filters
- 监听过滤器是请求处理的第一个环节。它们在连接刚建立时应用,用于执行一些初步处理,如协议检测和SNI(服务器名称指示)处理。
- Connection
- 连接管理组件接受新连接并管理连接的整个生命周期,包括连接的建立、维护和关闭。
- TCP Filter Manager
- TCP过滤器管理器负责调度TCP层的读写过滤器。它在连接建立后,管理TCP过滤器的执行顺序和逻辑。
- TCP Read Filters
- TCP读过滤器处理TCP层的数据读取。它们可以执行如协议解码、数据验证等操作,将TCP数据转换为更高级别的协议数据。
- HTTP Codec
- HTTP编解码器负责将TCP层的数据解码为HTTP请求。它将字节流解析为HTTP请求头、请求体等结构化数据,供后续处理。
- HTTP Connection Manager
- HTTP连接管理器负责管理HTTP连接的生命周期,包括HTTP请求的接收、处理和响应发送。它是HTTP请求处理的核心管理组件。
- HTTP Read Filters
- HTTP读过滤器处理HTTP请求数据,可以执行如认证、授权、请求修改等操作。它们在HTTP连接管理器中被调用,逐步处理HTTP请求。
- Service Router
- 服务路由器基于配置的路由规则,将HTTP请求路由到适当的后端服务。它根据请求的路径、头信息等,将请求转发到正确的集群或服务实例。
- Upstream Connection Pool
- 上游连接池管理与后端服务的连接,支持连接复用和负载均衡。它维护与后端服务的持久连接,优化连接的建立和管理。
- Backend Services
- 后端服务是实际处理请求的服务器或服务实例。请求在这里得到处理,并生成响应。
- HTTP Write Filters
- HTTP写过滤器处理HTTP响应数据,可以对响应进行修改、添加头信息等操作。这些过滤器在响应发送给客户端之前被调用。
- HTTP Connection Manager
- HTTP连接管理器负责将HTTP响应数据编码为TCP数据。它将结构化的HTTP响应转为字节流,并准备发送回客户端。
- TCP Write Filters
- TCP写过滤器处理TCP层的数据写入。它们将编码好的TCP数据发送回客户端,完成整个请求处理流程。
辅助模块
- Stats
- 统计模块实时收集和报告Envoy的运行时统计数据,提供详细的性能和使用情况报告。
- Admin
- 管理接口提供Envoy的配置、控制和监控功能。管理员可以通过这个接口查看和修改Envoy的配置,监控运行状态。
- Cluster/Listener/Route Manager
- 集群、监听器和路由管理器负责管理集群的健康检查、服务发现和路由配置。它通过与xDS API交互动态更新配置。
- xDS API
- xDS API用于动态配置和服务发现,包括CDS(Cluster Discovery Service)、EDS(Endpoint Discovery Service)、LDS(Listener Discovery Service)和RDS(Route Discovery Service)等。这些API允许Envoy在运行时动态获取和更新配置。
五、Envoy HTTP连接管理器
http_connection_manager 专门用于激活7层代理功能的4层过滤器。
配置示例文件:
# cat front-envoy.yaml admin: profile_path: /tmp/envoy.prof access_log_path: /tmp/admin_access.log address: socket_address: { address: 0.0.0.0, port_value: 9901 } static_resources: listeners: - name: listener_0 address: socket_address: { address: 0.0.0.0, port_value: 80 } 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: ingress_http codec_type: AUTO route_config: name: local_route virtual_hosts: - name: webservice domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: web_cluster_01 } http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: web_cluster_01 connect_timeout: 0.25s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: web_cluster_01 endpoints: - lb_endpoints: - endpoint: address: socket_address: { address: myservice, port_value: 80 } health_checks: - timeout: 5s interval: 10s unhealthy_threshold: 2 healthy_threshold: 2 http_health_check: path: /livez expected_statuses: start: 200 end: 399
Envoy的HTTP连接管理(HTTP Connection Management)是Envoy代理的重要组成部分,负责管理HTTP连接的生命周期,包括HTTP请求的接收、处理和响应发送。以下是HTTP连接管理的主要内容:
5.1 HTTP连接管理器(HTTP Connection Manager)作用
HTTP连接管理器是Envoy中处理HTTP流量的核心组件。它提供了全面的功能来管理HTTP连接和流量。
5.2 配置结构
HTTP连接管理器的配置通常包括以下几个部分:
- stat_prefix: 统计前缀,用于生成统计数据的前缀。
- codec_type: 编解码类型,支持HTTP1、HTTP2和自动检测(AUTO)。
- route_config: 路由配置,定义如何将请求路由到上游服务。
- http_filters: HTTP过滤器,定义在请求和响应过程中应用的过滤器链。
- access_log: 访问日志配置,定义如何记录访问日志。
5.3 路由配置(Route Configuration)
路由配置定义了如何将HTTP请求路由到适当的上游服务。它包括虚拟主机和路由规则:
- virtual_hosts: 虚拟主机,包含域名和对应的路由规则。
- routes: 路由规则,定义如何匹配请求并将其转发到后端集群。
5.4 HTTP过滤器(HTTP Filters)
HTTP过滤器是在请求和响应过程中应用的插件。它们可以执行多种功能,如:
- 认证和授权: 验证请求的合法性并检查访问权限。
- 修改请求和响应: 修改HTTP头、请求体或响应体。
- 统计和监控: 收集和报告请求处理的统计数据。
常见的HTTP过滤器包括:
- envoy.filters.http.router: 路由过滤器,负责将请求转发到上游服务。
- envoy.filters.http.jwt_authn: JWT认证过滤器,用于验证JWT令牌。
- envoy.filters.http.rbac: 角色访问控制过滤器,用于实施访问控制策略。
5.5 访问日志(Access Logging)
访问日志记录每个请求的详细信息,用于监控和审计。配置项包括:
- path: 日志文件路径。
- format: 日志格式,可以是预定义的格式或自定义格式。
- filters: 日志过滤器,控制哪些请求被记录。
5.6 连接管理和超时设置
Envoy提供多种选项来管理HTTP连接和超时:
- idle_timeout: 空闲连接超时时间,超过该时间未活动的连接将被关闭。
- request_timeout: 请求超时时间,单个请求的处理时间超过该值将被终止。
- drain_timeout: 连接排空超时时间,用于优雅关闭连接。
5.7 示例配置
以下是一个示例配置,展示了HTTP连接管理器的基本配置:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
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: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "*"
routes:
- match:
prefix: "/"
route:
cluster: service_cluster
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: "/var/log/envoy/access.log"
format: "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% \"%REQ(USER-AGENT)%\" \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(REQUEST_ID)%\" \"%REQ(AUTHORITY)%\" \"%UPSTREAM_HOST%\"\n"
clusters:
- name: service_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8081
Envoy的HTTP连接管理器提供了强大的功能来管理HTTP连接和请求处理。它支持灵活的路由配置、丰富的HTTP过滤器、多种超时设置和详细的访问日志记录。这些功能使Envoy能够高效地处理复杂的HTTP流量管理需求,并提供高性能和可扩展的解决方案。
5.8 HTTP连接管理的扩展功能
5.8.1 HTTP连接管理器的基本功能
- 字节到消息转换:通过内置的L4过滤器,HTTP连接管理器将原始字节流转换为HTTP应用层协议级别的消息和事件,例如接收到的标头和主体。
- HTTP连接和请求处理:处理所有HTTP连接和请求的通用功能,包括访问日志、生成跟踪连接ID、请求/响应头处理、路由表管理和统计信息收集等。
5.8.2 支持的协议
- HTTP/1.1、WebSockets和HTTP/2:Envoy支持这些协议的处理,但不支持SPDY。
5.8.3 路由表管理
- 静态和动态路由表:路由表可以通过静态配置或者通过xDS API中的RDS(Route Discovery Service)动态生成。
5.8.4 重试插件
- 内建重试插件:可以配置重试行为,包括Host Predicates和Priority Predicates,用于定义重试的条件和优先级。
5.8.5 302重定向支持
- 内建302重定向支持:Envoy可以捕获302重定向响应,合成新请求后将其发送到路由匹配指定的上游端,并将收到的响应返回给原始客户端。
5.8.6 超时机制
- 连接级别超时:
- 空闲超时:处理连接空闲时间超过设定值时关闭连接。
- 排空超时(GOAWAY):在连接关闭前,发送GOAWAY帧通知客户端不再接受新请求。
- 流级别超时:
- 空闲超时:处理HTTP流空闲时间超过设定值时关闭流。
- 每路由相关的上游端点超时:针对特定路由配置的超时时间。
- gRPC最大超时:处理gRPC请求的最大超时时间。
5.8.7 动态转发代理
- 基于自定义集群的动态转发代理:Envoy支持基于自定义集群的动态转发,这允许Envoy根据实时情况动态调整请求的转发目标。
5.8.8 HTTP协议相关功能通过HTTP过滤器实现
HTTP协议相关的功能通过各类HTTP过滤器实现,这些过滤器大体可分为编码器和解码器两类:
常用过滤器
- Router过滤器(envoy.router):
- 请求转发和重定向:基于路由表完成请求的转发或重定向。
- 重试操作:处理重试逻辑,确保请求在失败后按照配置进行重试。
- 统计信息生成:收集和生成有关请求处理的统计信息。
Envoy的HTTP连接管理器不仅负责基础的HTTP连接和请求处理,还包含丰富的功能来增强HTTP协议的支持和管理能力。这些功能包括多协议支持、静态和动态路由配置、内建重试和重定向支持、详细的超时管理以及动态转发代理能力。通过这些功能,Envoy能够灵活、高效地管理和处理复杂的HTTP流量,使其成为一个强大的边缘代理和服务网格组件。
六、Envoy HTTP高级路由
Envoy的HTTP高级路由功能提供了强大的工具和配置选项,以便灵活地管理和处理HTTP请求。以下是Envoy的HTTP高级路由的主要内容和功能:
6.1 路由匹配(Route Matching)
路由匹配是Envoy路由的核心部分,通过配置不同的匹配条件,将请求路由到合适的上游服务。匹配条件包括:
- 前缀匹配(prefix match):匹配请求路径的前缀。
- 完全路径匹配(path match):匹配完整的请求路径。
- 正则表达式匹配(regex match):使用正则表达式匹配请求路径。
- 请求头匹配(header match):基于请求头的值进行匹配。
- 查询参数匹配(query parameter match):基于查询参数的值进行匹配。
6.2 路由目标(Route Destination)
定义匹配请求后的目标服务和行为,包括:
- 集群(cluster):将请求转发到特定的上游集群。
- 集群权重(weighted clusters):将请求按权重分配到多个集群,实现流量分配和负载均衡。
- 直连响应(direct response):直接由Envoy响应请求,而不是转发到上游服务。
- 重定向(redirect):将请求重定向到另一个URL。
6.3 路由策略(Route Policies)
通过路由策略对请求进行进一步的处理和控制:
- 请求/响应修改:修改请求和响应的头信息、路径等。
- 重试策略(retry policy):定义请求失败后的重试行为,包括重试次数、条件等。
- 超时策略(timeout policy):定义请求的超时时间,包括总超时、空闲超时等。
- 流量镜像(traffic mirroring):将请求复制并发送到其他服务进行调试和测试。
6.4 路由级别的特性和操作
- 健康检查(health checks):确保请求仅被路由到健康的上游服务实例。
- 负载均衡策略(load balancing policy):定义请求在上游集群中的负载均衡行为,例如轮询、最少连接、随机等。
- 请求限速(rate limiting):对请求进行限速控制,防止过载。
- 服务质量(QoS):配置不同的优先级和延迟管理策略。
6.5 高级匹配条件
- 复合匹配(composite matching):组合多种匹配条件进行复杂匹配,例如同时基于路径、请求头和查询参数进行匹配。
- 谓词匹配(predicate matching):使用自定义条件进行匹配,例如基于请求的某些特征进行高级匹配。
6.6 动态路由
- xDS API:通过xDS API动态更新路由配置,包括CDS(Cluster Discovery Service)、EDS(Endpoint Discovery Service)、LDS(Listener Discovery Service)和RDS(Route Discovery Service)。
- 实时配置更新:支持路由配置的实时更新,确保系统的高灵活性和可用性。
6.7 示例配置
以下是一个示例配置,展示了Envoy的高级路由功能:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
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: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "*"
routes:
- match:
prefix: "/service1"
route:
cluster: service1_cluster
timeout: 5s
retry_policy:
retry_on: "5xx"
num_retries: 3
per_try_timeout: 1s
- match:
prefix: "/service2"
route:
weighted_clusters:
clusters:
- name: service2_cluster
weight: 80
- name: service2_canary_cluster
weight: 20
- match:
prefix: "/health"
direct_response:
status: 200
body:
inline_string: "OK"
- match:
prefix: "/old-path"
redirect:
path_redirect: "/new-path"
response_code: 301
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: service1_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service1_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8081
- name: service2_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service2_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.2
port_value: 8082
- name: service2_canary_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service2_canary_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.3
port_value: 8083
Envoy的HTTP高级路由功能提供了多种匹配条件、策略和控制选项,能够灵活高效地处理HTTP请求。这些功能包括详细的路由匹配、丰富的目标和策略配置、高级匹配条件、动态路由和实时配置更新等,使Envoy成为一个功能强大且灵活的代理和服务网格组件。
6.8 扩展内容
域名映射到虚拟主机
- 域名映射到虚拟主机:Envoy使用虚拟主机(Virtual Host)来根据域名匹配请求。每个虚拟主机可以管理一个或多个域名,并包含相应的路由规则。
路由匹配
- 路径前缀匹配(prefix match):根据路径前缀匹配请求。
- 精确匹配(exact match):根据完整路径精确匹配请求。
- 正则表达式匹配(regex match):使用正则表达式匹配路径。
重定向
- 虚拟主机级别的TLS重定向:在虚拟主机级别进行TLS重定向,将HTTP请求重定向到HTTPS。
- 路径级别的重定向(path/host redirect):根据路径或主机头进行重定向,将请求重定向到另一个路径或主机。
直接生成响应
- 直接响应:Envoy可以直接生成HTTP响应,而无需将请求转发到上游服务。
主机重写和前缀重写
- 主机重写(host rewrite):将请求的主机头重写为另一个主机名,例如将hostA重写为hostB。
- 前缀重写(prefix rewrite):将请求路径的前缀重写为另一个前缀。
请求重试和超时
- 请求重试(retry):基于HTTP头或路由配置进行请求重试,可以配置重试条件、重试次数和重试策略。
- 请求超时(timeout):配置请求的超时时间,包括总超时和每次尝试的超时。
流量迁移和权重路由
- 流量迁移:基于运行时参数进行流量迁移,动态调整流量的路由目标。
- 权重或百分比流量分割:基于权重或百分比将流量分割到多个上游集群,实现流量分配和负载均衡。
基于标头和优先级的路由
- 基于标头的路由:根据HTTP请求头的值进行路由匹配。
- 基于优先级的路由:配置请求的优先级,基于优先级进行路由选择。
基于哈希的路由
- 哈希策略(hash-based routing):基于请求的某些特征(例如请求头、URL参数)进行哈希计算,确保同一特征的请求路由到相同的上游服务。
配置示例及解析
下面我们来看一个Envoy高级路由配置的示例,展示上述功能的实现:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
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: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains:
- "example.com"
routes:
- match:
prefix: "/service1"
route:
cluster: service1_cluster
host_rewrite_literal: new-service1.example.com
timeout: 5s
retry_policy:
retry_on: "5xx"
num_retries: 3
per_try_timeout: 1s
- match:
prefix: "/service2"
route:
weighted_clusters:
clusters:
- name: service2_cluster
weight: 80
- name: service2_canary_cluster
weight: 20
- match:
prefix: "/health"
direct_response:
status: 200
body:
inline_string: "OK"
- match:
prefix: "/old-path"
redirect:
path_redirect: "/new-path"
response_code: 301
- match:
prefix: "/test"
route:
cluster: test_cluster
prefix_rewrite: "/new-test"
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: service1_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service1_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.1
port_value: 8081
- name: service2_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service2_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.2
port_value: 8082
- name: service2_canary_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service2_canary_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.3
port_value: 8083
- name: test_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: test_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 127.0.0.4
port_value: 8084
示例配置解释
监听器(Listener)
- 定义了一个监听器
listener_0,监听0.0.0.0:8080端口,使用HTTP连接管理器过滤器。
虚拟主机(Virtual Hosts)
- 定义了一个虚拟主机
local_service,域名为example.com。
路由规则(Route Rules)
- /service1路径:
- 将请求路由到
service1_cluster集群。 - 将主机头重写为
new-service1.example.com。 - 配置请求超时时间为5秒。
- 配置重试策略,针对5xx错误重试3次,每次重试的超时时间为1秒。
- 将请求路由到
- /service2路径:
- 将请求按权重分配到
service2_cluster(80%)和service2_canary_cluster(20%)。
- 将请求按权重分配到
- /health路径:
- 直接响应请求,返回状态码200和响应体“OK”。
- /old-path路径:
- 将请求重定向到
/new-path,返回301重定向状态码。
- 将请求重定向到
- /test路径:
- 将请求路由到
test_cluster集群。 - 将路径前缀重写为
/new-test。
- 将请求路由到
这些配置展示了Envoy的HTTP高级路由功能,包括多种匹配条件、重试和超时策略、主机和前缀重写、直接响应、重定向等。通过这些功能,Envoy能够灵活高效地处理HTTP流量,满足复杂的路由需求。
七、Envoy HTTP路由域名映射过程
在Envoy配置中,虚拟主机的域名匹配是处理入站HTTP请求的关键环节。这一机制允许Envoy根据请求的 Host头部将不同的请求路由到不同的后端服务。下面是对域名搜索顺序的详细解释:
7.1 域名搜索顺序
当HTTP请求到达Envoy代理时,Envoy会根据请求中的 Host头部或HTTP/2的 :authority头部中的值来确定该请求应该由哪个虚拟主机处理。Envoy按以下顺序搜索与 Host头部匹配的虚拟主机的域名:
- 精确匹配 (
Exact domain names):- 这是最直接的匹配方式,Envoy会检查配置中是否有与
Host头部完全相同的域名。 - 例如,如果
Host头为www.kubex.io,Envoy会查找配置中是否有一个虚拟主机定义了www.kubex.io为其域名。
- 这是最直接的匹配方式,Envoy会检查配置中是否有与
- 左前缀匹配 (
Prefix domain wildcards):- 如果没有找到精确匹配,Envoy会查找是否有域名前缀匹配。这种匹配使用星号
*作为前缀通配符。 - 例如,如果
Host头为blog.kubex.io,Envoy会匹配诸如*.kubex.io的域名。
- 如果没有找到精确匹配,Envoy会查找是否有域名前缀匹配。这种匹配使用星号
- 右后缀匹配 (
Suffix domain wildcards):- 如果前两种方式都没有找到匹配项,Envoy会尝试后缀通配符匹配,这也使用星号
*,但放在域名的末尾。 - 例如,如果
Host头为kubex.com,Envoy会匹配如kubex.*的配置。
- 如果前两种方式都没有找到匹配项,Envoy会尝试后缀通配符匹配,这也使用星号
- 通配符“*” (
Special wildcard *):- 如果以上所有匹配方式都未成功,Envoy将使用特殊的通配符
*,这意味着匹配任何域名。 - 这通常用于默认的虚拟主机配置,以确保所有未明确匹配到特定配置的请求都能被处理。
- 如果以上所有匹配方式都未成功,Envoy将使用特殊的通配符
7.2 终止搜索
在Envoy的虚拟主机匹配逻辑中,一旦找到匹配的域名,搜索过程即终止。这意味着,匹配过程是按优先级进行的,一旦匹配成功,不会继续考虑其他可能的匹配。
域名示例
假设配置了以下虚拟主机的域名:
www.kubex.io(精确匹配)*.kubex.io(左前缀匹配)kubex.*(右后缀匹配)*(通配符)
对于请求 Host为 api.kubex.io,Envoy会按照上述顺序首先尝试精确匹配,然后是左前缀匹配,这将成功匹配到 *.kubex.io。
这种灵活而详尽的匹配机制使得Envoy能够有效地管理大规模和复杂的微服务架构中的网络流量。
路由配置示例一
virtual_hosts:
- name: vh_001
domains: ["kubex.io", "*.kubex.io", "kubex.*"]
routes:
- match:
path: "/service/blue"
route:
cluster: blue
- match:
safe_regex:
google_re2: {}
regex: "^/service/.*blue$"
redirect:
path_redirect: "/service/blue"
- match:
prefix: "/service/yellow"
direct_response:
status: 200
body:
inline_string: "This page will be provided soon later.\n"
- match:
prefix: "/"
route:
cluster: red
- name: vh_002
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: gray
以上路由配置示例在Envoy的上下文中演示了虚拟主机的配置及多种路由匹配机制。这里的配置包括两个虚拟主机(vh_001和 vh_002),每个主机都有针对特定类型请求的路由规则。下面是对这些路由规则的详细解释:
虚拟主机 vh_001
- 域名:
kubex.io,*.kubex.io,kubex.*这个虚拟主机处理从kubex.io及其所有子域和不同顶级域的请求。 - 路由规则:
- 精确路径匹配:
- 路径:
/service/blue - 动作:将请求路由到名为
blue的集群。
- 路径:
- 正则表达式匹配:
- 正则表达式:
^/service/.*blue$ - 动作:将请求重定向到
/service/blue。这可以用于规范化URL格式或处理旧URL的迁移。
- 正则表达式:
- 前缀匹配:
- 前缀:
/service/yellow - 动作:返回直接响应,状态码为200,响应体为"This page will be provided soon later.\n"。这种类型的路由常用于站点维护或未完成页面的提示。
- 前缀:
- 根路径前缀匹配:
- 前缀:
/ - 动作:将根路径及其子路径的请求路由到名为
red的集群。
- 前缀:
- 精确路径匹配:
虚拟主机 vh_002
- 域名:
*这个虚拟主机处理所有未由vh_001捕获的域名的请求。 - 路由规则:
- 前缀匹配:
- 前缀:
/ - 动作:将所有请求路由到名为
gray的集群。
- 前缀:
- 前缀匹配:
这个配置演示了Envoy在处理HTTP请求时的灵活性:
- 匹配类型多样:支持基于精确路径、正则表达式、前缀的匹配,允许细致地控制请求路由。
- 多种路由动作:可以执行请求的路由、重定向、直接响应等不同动作。
- 域名通配符:通过使用通配符,虚拟主机可以灵活处理来自多个域名的请求。
这种配置使得Envoy非常适合作为微服务架构中的边缘或内部代理,能够根据复杂的规则集处理入站和出站流量。
路由配置示例二
这个YAML配置定义了一个Envoy代理中的虚拟主机配置。虚拟主机包含了几个路由规则,这些规则基于请求的特定属性(如头部信息和查询参数)将流量路由到不同的后端服务。
virtual_hosts:
- name: vh_001
domains: ["*"]
routes:
- match:
prefix: "/"
headers:
- name: X-Canary
exact_match: "true"
route:
cluster: demoappv12
- match:
prefix: "/"
query_parameters:
- name: "username"
string_match:
prefix: "vip_"
route:
cluster: demoappv11
- match:
prefix: "/"
route:
cluster: demoappv10
-
虚拟主机 (Virtual Host):
- name: 虚拟主机的名称,这里是
vh_001。 - domains: 该虚拟主机处理的域名列表。这里的
"*"表示这个虚拟主机将处理所有域名的请求。
- name: 虚拟主机的名称,这里是
-
路由规则 (Routes):
- 每个
match条件定义了一组规则,根据请求的属性决定使用哪个路由。所有的路由都从根路径"/"开始匹配,但基于其他属性(如头部或查询参数)来进一步细化匹配规则。
- 第一条路由规则:
- 头部匹配: 查找头部
X-Canary且值必须精确为"true"。 - 路由目标: 如果匹配成功,请求将被路由到名为
demoappv12的集群。
- 头部匹配: 查找头部
- 第二条路由规则:
- 查询参数匹配: 查找查询参数
username,其值必须以"vip_"为前缀。 - 路由目标: 如果匹配成功,请求将被路由到名为
demoappv11的集群。
- 查询参数匹配: 查找查询参数
- 第三条路由规则:
- 基本匹配: 仅基于路径
"/",没有额外条件。 - 路由目标: 如果前两条规则都未匹配,请求默认路由到名为
demoappv10的集群。
- 基本匹配: 仅基于路径
- 每个
这个配置文件示例显示了Envoy如何利用HTTP头部和查询参数进行条件匹配,以决定将请求路由到何种后端服务。这种灵活的路由机制使得Envoy非常适合动态的、基于条件的路由场景,如进行A/B测试、灰度发布或处理多租户应用。
两个YAML示例文件展示了Envoy路由配置中不同的焦点和用途:
- 第一个示例:
- 展示了多种match的基本匹配机制:这包括精确路径匹配、正则表达式匹配、前缀匹配以及直接响应的配置。这些匹配机制使得路由配置能够处理各种类型的HTTP请求,根据路径或路径模式来决定如何路由请求或是提供直接响应。
- 不同的路由方式:示例中展示了将请求路由到指定集群、执行HTTP重定向、以及返回直接响应等操作。这种多样化的路由行为展示了Envoy的强大灵活性在处理不同路由需求上的能力。
- 第二个示例:
- 侧重于基于HTTP头部和查询参数的匹配:此示例中的路由规则特别关注于使用请求中的特定HTTP头部(如
X-Canary)和查询参数(如用户名前缀vip_)来决定路由目标。这表明了配置的目的是根据请求的具体内容来动态地决定路由,这在进行A/B测试、用户分群等场景中非常有用。 - 动态路由决策:通过检查请求的特定属性来路由到不同的后端服务,强调了根据实际请求动态选择服务的能力,而不是仅仅基于请求路径。
- 侧重于基于HTTP头部和查询参数的匹配:此示例中的路由规则特别关注于使用请求中的特定HTTP头部(如
总的来说,第一个示例强调了Envoy如何处理多种路由情况,而第二个示例则显示了基于更细致条件(如HTTP头部和查询参数)的路由决策,两者都体现了Envoy在现代云基础设施中的应用灵活性。
八、Envoy HTTP路由应用案例
8.1 简单匹配
环境说明
八个Service:
- envoy:Front Proxy,地址为172.31.10.10
- 7个后端服务
- light_blue和dark_blue:对应于Envoy中的blue集群
- light_red和dark_red:对应于Envoy中的red集群
- light_green和dark_green:对应Envoy中的green集群
- gray:对应于Envoy中的gray集群
代理配置:
# cat front-envoy.yaml
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 80 }
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: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: vh_001
domains: ["kubex.io", "*.kubex.io", "kubex.*"]
routes:
- match:
path: "/service/blue"
route:
cluster: blue
- match:
safe_regex:
google_re2: {}
regex: "^/service/.*blue$"
redirect:
path_redirect: "/service/blue"
- match:
prefix: "/service/yellow"
direct_response:
status: 200
body:
inline_string: "This page will be provided soon later.\n"
- match:
prefix: "/"
route:
cluster: red
- name: vh_002
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: gray
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: blue
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: blue
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: blue
port_value: 80
- name: red
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: red
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: red
port_value: 80
- name: green
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: green
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: green
port_value: 80
- name: gray
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
http2_protocol_options: {}
load_assignment:
cluster_name: gray
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: gray
port_value: 80
运行并测试:
默认访问时,由gray集群进行响应,www.kubeabc.com域名不被匹配
# curl -H "Host: www.kubeabc.com" http://172.31.10.10/service/a
Hello from App behind Envoy (service gray)! hostname: 939baac592ca resolved hostname: 172.31.10.3
添加kubex.io标头进行访问,默认匹配为/,匹配path为/,由red集群进行响应
# curl -H "Host: www.kubex.io" http://172.31.10.10/service/a
Hello from App behind Envoy (service dark_red)! hostname: 93e233552153 resolved hostname: 172.31.10.2
添加ilinux.io标头进行访问,URI为/service/blue,由 blue进行响应
# curl -H "Host: www.kubex.io" http://172.31.10.10/service/blue
Hello from App behind Envoy (service light_blue)! hostname: 4f0b5d0cb883 resolved hostname: 172.31.10.4
添加kubex.io标头进行访问,URI为/service/dark_blue,被重定向到/service/blue
# curl -I -H "Host: www.kubex.io" http://172.31.10.10/service/dark_blue
HTTP/1.1 301 Moved Permanently
location: http://www.kubex.io/service/blue
date: Tue, 04 Jun 2024 15:28:59 GMT
server: envoy
transfer-encoding: chunked
添加kubex.io标头进行访问,URI为/service/yellow,使用inline_string 内联字符串
不会有任何的响应,直接由envoy进行响应
# curl -H "Host: www.kubex.io" http://172.31.10.10/service/yellow
This page will be provided soon later.
8.2 基于请求头匹配(header match)
代理配置
# cat front-envoy.yaml
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 80 }
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: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: vh_001
domains: ["*"]
routes:
- match:
prefix: "/"
headers:
- name: X-Canary
exact_match: "true"
route:
cluster: demoappv12
- match:
prefix: "/"
query_parameters:
- name: "username"
string_match:
prefix: "vip_"
route:
cluster: demoappv11
- match:
prefix: "/"
route:
cluster: demoappv10
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: demoappv10
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: demoappv10
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: demoappv10
port_value: 80
- name: demoappv11
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: demoappv11
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: demoappv11
port_value: 80
- name: demoappv12
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: demoappv12
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: demoappv12
port_value: 80
运行并测试:
不使用任何独特的访问条件
# curl http://172.31.11.10
demoapp v1.0 !! ClientIP: 172.31.11.10, ServerName: demoapp-v1.0-2, ServerIP: 172.31.11.6!
# curl http://172.31.11.10
demoapp v1.0 !! ClientIP: 172.31.11.10, ServerName: demoapp-v1.0-1, ServerIP: 172.31.11.5!
匹配使用特定的标头发起请求
# curl -H "X-Canary: true" http://172.31.11.10
demoapp v1.2 !! ClientIP: 172.31.11.10, ServerName: demoapp-v1.2-1, ServerIP: 172.31.11.2!
匹配使用特定的查询条件
# curl http://172.31.11.10?username=kubex
demoapp v1.0 !! ClientIP: 172.31.11.10, ServerName: demoapp-v1.0-2, ServerIP: 172.31.11.6!
# curl http://172.31.11.10?username=vip_kubex
demoapp v1.1 !! ClientIP: 172.31.11.10, ServerName: demoapp-v1.1-2, ServerIP: 172.31.11.3!
# curl http://172.31.11.10?username=vip_kubex
demoapp v1.1 !! ClientIP: 172.31.11.10, ServerName: demoapp-v1.1-1, ServerIP: 172.31.11.4!
评论区