侧边栏壁纸
  • 累计撰写 28 篇文章
  • 累计创建 23 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Envoy HTTP流量治理基础

zhanjie.me
2025-09-17 / 0 评论 / 0 点赞 / 7 阅读 / 0 字

在Envoy中,虚拟主机(Virtual Host)和路由(Route)是配置HTTP请求路由的重要概念。

一、Envoy HTTP路由配置框架

1.1 虚拟主机(Virtual Host)

虚拟主机是Envoy中用于根据请求的主机头(Host Header)来匹配请求的一种机制。它允许你在同一个Envoy实例中处理多个域名或服务。

image-jlafntus.png

在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)来决定如何处理请求。这些路由规则可以定义多种行为,包括:
    • 路由到后端集群:最常见的行为是将请求路由到一个后端服务或集群。这通常涉及到更细粒度的匹配条件,如请求的路径(prefixpath或使用正则表达式等),请求方法等。
    • 重定向:路由规则还可以配置为对某些请求执行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.comwww.example.com 的请求。

二、Envoy HTTP路由(Route)

路由是指根据请求的路径、方法、头信息等将请求转发到特定的后端服务。它定义了当请求匹配某个虚拟主机后,如何处理这个请求。

2.1 路由配置

在虚拟主机下,你可以配置一个或多个路由,每个路由包括匹配条件(match)和处理方式(route)。

简单配置示例

routes:
- match:
    prefix: "/"
  route:
    cluster: service_cluster
- match:
    prefix: "/api"
  route:
    cluster: api_service_cluster

在上述配置中,有两个路由规则:

  1. 匹配所有路径(/),请求将被转发到 service_cluster
  2. 匹配路径以 /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-headervalue 的请求。匹配后,将请求转发到 service_cluster,并配置了超时时间和重试策略。

2.2 路由配置步骤

  1. 定义虚拟主机:在虚拟主机中定义多个域名。
  2. 添加路由规则:在虚拟主机中添加一个或多个路由规则。
  3. 设置匹配条件:在路由规则中设置路径、请求头等匹配条件。
  4. 配置转发选项:在路由规则中配置转发的后端集群、超时、重试等选项。

通过以上步骤,可以灵活地根据请求的不同属性配置Envoy的路由策略,从而实现流量的精确控制和管理。

2.3 路由匹配(match)

在Envoy中,路由匹配(match)用于定义如何筛选进入的流量并匹配特定的路由规则。路由匹配可以根据请求路径、请求头、查询参数等进行配置。主要包括基础匹配和高级匹配两类。

image-gzurfcmo.png

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-headercustom_value 且查询参数 useradmin 的请求。
  • 第二条路由规则使用正则表达式匹配路径以 /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默认端口。
  • filter_chains:
    • filters:
      • name: 使用的过滤器名称,这里是 envoy.filters.network.http_connection_manager,它管理HTTP连接。
      • typed_config: 过滤器的详细配置。
        • @type: 配置类型,指定为HTTP连接管理器的v3版本。
        • stat_prefix: 用于统计的前缀,这里是"ingress_http"。
        • codec_type: 解码类型,自动选择适当的HTTP编解码器。
  • 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作为一个单一的进程运行,内部通过多个线程来处理不同的任务。

image-ppludbaq.png

3.2.2 主线程(Main Thread)

主线程是Envoy的核心管理线程,负责多个关键管理任务:

  1. 启动和关闭:负责Envoy程序的启动和关闭,包括初始化配置和资源。
  2. xDS API调用处理:处理与xDS API的交互,xDS(Extensible Service Discovery and Configuration)是Envoy用来动态获取配置信息的机制。包括集群管理、服务发现、负载均衡等。
  3. DNS和健康状态检测:管理DNS解析和集群健康检查,确保服务的可用性。
  4. 运行时配置:管理运行时配置更新,允许动态修改配置而无需重启Envoy。
  5. 统计数据刷新:定期刷新和维护统计数据,用于监控和分析。
  6. 线程管理:维护其他工作线程,包括信号处理和热重启等操作。

主线程中的所有事件都是以异步非阻塞模式完成的,这确保了高效的管理操作,不会阻塞其他工作线程的执行。

主线程负责Envoy的管理和控制任务,它的职责包括:

  • xDS:处理与xDS API的交互,管理动态配置,包括服务发现和负载均衡。
  • Runtime:管理运行时配置,允许动态修改配置而无需重启Envoy。
  • Stat flush:负责统计数据的刷新和维护,提供监控和分析信息。
  • Admin:维护管理接口,提供操作和控制功能。
  • Process management:处理信号和热重启等进程管理任务。

主线程以异步非阻塞的方式处理这些任务,确保不会阻塞其他线程的执行。

3.2.3 工作线程(Worker Threads)

工作线程是Envoy处理实际代理功能的核心:

  1. 线程数量:默认情况下,Envoy根据主机的CPU核心数创建等量的工作线程,管理员也可以通过 --concurrency选项指定具体数量。
  2. 非阻塞事件循环:每个工作线程运行一个非阻塞的事件循环,负责处理监听器分配的套接字、接收新请求,并初始化和管理过滤器栈。
  3. 请求处理:处理请求的整个生命周期,包括解析请求、应用过滤器和转发请求等。

工作线程负责实际的请求处理,每个工作线程包含以下部分:

  • Listeners:监听器,负责接受新连接。Envoy可以配置多个监听器,每个监听器可以监听不同的端口和协议。
  • Connections:连接管理,处理每个连接的生命周期,包括请求的接收、解析、处理和响应。

每个工作线程运行一个非阻塞事件循环,确保高效地处理大量并发连接。默认情况下,Envoy会根据主机的CPU核心数创建等量的工作线程,但也可以通过 --concurrency选项指定具体数量。

3.2.4 文件刷写线程(File Flush Thread)

文件刷写线程负责Envoy的日志和其他文件写入操作:

  1. 独立线程:每个文件写入操作都有一个专用的独立阻塞型刷写线程。
  2. 内存缓冲区:工作线程将数据写入内存缓冲区,然后由文件刷写线程同步写入文件。
  3. 同步刷写:确保数据最终一致性和文件的持久化存储。

文件刷写线程负责Envoy的日志和其他文件写入操作。每个文件写入都有一个独立的阻塞型刷写线程:

  • 内存缓冲区:工作线程将数据写入内存缓冲区。
  • 文件同步:文件刷写线程将内存缓冲区中的数据同步写入文件,确保数据的一致性和持久性。

总结

Envoy的单进程/多线程架构模型实现了高效的资源管理和任务处理:

  • 主线程处理管理任务和动态配置,确保代理的可用性和灵活性。
  • 工作线程并发处理实际的请求,提供高性能的代理服务。
  • 文件刷写线程确保日志和数据的持久化,独立于主线程和工作线程,避免阻塞核心代理功能。

这种架构使Envoy能够在高负载和高并发的环境中高效运行,同时提供动态配置和灵活管理的能力。

四、Envoy连接处理流程

image-kwcjsmgi.png

  1. Worker Thread
    • 工作线程负责处理具体的请求。Envoy根据主机的CPU核心数创建等量的工作线程(可通过 --concurrency选项指定数量)。每个工作线程运行一个非阻塞事件循环来处理请求。
  2. Listener Filters
    • 监听过滤器是请求处理的第一个环节。它们在连接刚建立时应用,用于执行一些初步处理,如协议检测和SNI(服务器名称指示)处理。
  3. Connection
    • 连接管理组件接受新连接并管理连接的整个生命周期,包括连接的建立、维护和关闭。
  4. TCP Filter Manager
    • TCP过滤器管理器负责调度TCP层的读写过滤器。它在连接建立后,管理TCP过滤器的执行顺序和逻辑。
  5. TCP Read Filters
    • TCP读过滤器处理TCP层的数据读取。它们可以执行如协议解码、数据验证等操作,将TCP数据转换为更高级别的协议数据。
  6. HTTP Codec
    • HTTP编解码器负责将TCP层的数据解码为HTTP请求。它将字节流解析为HTTP请求头、请求体等结构化数据,供后续处理。
  7. HTTP Connection Manager
    • HTTP连接管理器负责管理HTTP连接的生命周期,包括HTTP请求的接收、处理和响应发送。它是HTTP请求处理的核心管理组件。
  8. HTTP Read Filters
    • HTTP读过滤器处理HTTP请求数据,可以执行如认证、授权、请求修改等操作。它们在HTTP连接管理器中被调用,逐步处理HTTP请求。
  9. Service Router
    • 服务路由器基于配置的路由规则,将HTTP请求路由到适当的后端服务。它根据请求的路径、头信息等,将请求转发到正确的集群或服务实例。
  10. Upstream Connection Pool
    • 上游连接池管理与后端服务的连接,支持连接复用和负载均衡。它维护与后端服务的持久连接,优化连接的建立和管理。
  11. Backend Services
    • 后端服务是实际处理请求的服务器或服务实例。请求在这里得到处理,并生成响应。
  12. HTTP Write Filters
    • HTTP写过滤器处理HTTP响应数据,可以对响应进行修改、添加头信息等操作。这些过滤器在响应发送给客户端之前被调用。
  13. HTTP Connection Manager
    • HTTP连接管理器负责将HTTP响应数据编码为TCP数据。它将结构化的HTTP响应转为字节流,并准备发送回客户端。
  14. 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头部匹配的虚拟主机的域名:

  1. 精确匹配 (Exact domain names):
    • 这是最直接的匹配方式,Envoy会检查配置中是否有与 Host头部完全相同的域名。
    • 例如,如果 Host头为 www.kubex.io,Envoy会查找配置中是否有一个虚拟主机定义了 www.kubex.io为其域名。
  2. 左前缀匹配 (Prefix domain wildcards):
    • 如果没有找到精确匹配,Envoy会查找是否有域名前缀匹配。这种匹配使用星号 *作为前缀通配符。
    • 例如,如果 Host头为 blog.kubex.io,Envoy会匹配诸如 *.kubex.io的域名。
  3. 右后缀匹配 (Suffix domain wildcards):
    • 如果前两种方式都没有找到匹配项,Envoy会尝试后缀通配符匹配,这也使用星号 *,但放在域名的末尾。
    • 例如,如果 Host头为 kubex.com,Envoy会匹配如 kubex.*的配置。
  4. 通配符“*” (Special wildcard *):
    • 如果以上所有匹配方式都未成功,Envoy将使用特殊的通配符 *,这意味着匹配任何域名。
    • 这通常用于默认的虚拟主机配置,以确保所有未明确匹配到特定配置的请求都能被处理。

7.2 终止搜索

在Envoy的虚拟主机匹配逻辑中,一旦找到匹配的域名,搜索过程即终止。这意味着,匹配过程是按优先级进行的,一旦匹配成功,不会继续考虑其他可能的匹配。

域名示例

假设配置了以下虚拟主机的域名:

  • www.kubex.io (精确匹配)
  • *.kubex.io (左前缀匹配)
  • kubex.* (右后缀匹配)
  • * (通配符)

对于请求 Hostapi.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_001vh_002),每个主机都有针对特定类型请求的路由规则。下面是对这些路由规则的详细解释:

虚拟主机 vh_001

  • 域名kubex.io, *.kubex.io, kubex.* 这个虚拟主机处理从 kubex.io及其所有子域和不同顶级域的请求。
  • 路由规则
    1. 精确路径匹配
      • 路径/service/blue
      • 动作:将请求路由到名为 blue的集群。
    2. 正则表达式匹配
      • 正则表达式^/service/.*blue$
      • 动作:将请求重定向到 /service/blue。这可以用于规范化URL格式或处理旧URL的迁移。
    3. 前缀匹配
      • 前缀/service/yellow
      • 动作:返回直接响应,状态码为200,响应体为"This page will be provided soon later.\n"。这种类型的路由常用于站点维护或未完成页面的提示。
    4. 根路径前缀匹配
      • 前缀/
      • 动作:将根路径及其子路径的请求路由到名为 red的集群。

虚拟主机 vh_002

  • 域名* 这个虚拟主机处理所有未由 vh_001捕获的域名的请求。
  • 路由规则
    1. 前缀匹配
      • 前缀/
      • 动作:将所有请求路由到名为 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: 该虚拟主机处理的域名列表。这里的 "*"表示这个虚拟主机将处理所有域名的请求。
  • 路由规则 (Routes):

    • 每个 match条件定义了一组规则,根据请求的属性决定使用哪个路由。所有的路由都从根路径 "/"开始匹配,但基于其他属性(如头部或查询参数)来进一步细化匹配规则。
    1. 第一条路由规则:
      • 头部匹配: 查找头部 X-Canary且值必须精确为 "true"
      • 路由目标: 如果匹配成功,请求将被路由到名为 demoappv12的集群。
    2. 第二条路由规则:
      • 查询参数匹配: 查找查询参数 username,其值必须以 "vip_"为前缀。
      • 路由目标: 如果匹配成功,请求将被路由到名为 demoappv11的集群。
    3. 第三条路由规则:
      • 基本匹配: 仅基于路径 "/",没有额外条件。
      • 路由目标: 如果前两条规则都未匹配,请求默认路由到名为 demoappv10的集群。

这个配置文件示例显示了Envoy如何利用HTTP头部和查询参数进行条件匹配,以决定将请求路由到何种后端服务。这种灵活的路由机制使得Envoy非常适合动态的、基于条件的路由场景,如进行A/B测试、灰度发布或处理多租户应用。

两个YAML示例文件展示了Envoy路由配置中不同的焦点和用途:

  1. 第一个示例
    • 展示了多种match的基本匹配机制:这包括精确路径匹配、正则表达式匹配、前缀匹配以及直接响应的配置。这些匹配机制使得路由配置能够处理各种类型的HTTP请求,根据路径或路径模式来决定如何路由请求或是提供直接响应。
    • 不同的路由方式:示例中展示了将请求路由到指定集群、执行HTTP重定向、以及返回直接响应等操作。这种多样化的路由行为展示了Envoy的强大灵活性在处理不同路由需求上的能力。
  2. 第二个示例
    • 侧重于基于HTTP头部和查询参数的匹配:此示例中的路由规则特别关注于使用请求中的特定HTTP头部(如 X-Canary)和查询参数(如用户名前缀 vip_)来决定路由目标。这表明了配置的目的是根据请求的具体内容来动态地决定路由,这在进行A/B测试、用户分群等场景中非常有用。
    • 动态路由决策:通过检查请求的特定属性来路由到不同的后端服务,强调了根据实际请求动态选择服务的能力,而不是仅仅基于请求路径。

总的来说,第一个示例强调了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!
0

评论区