Envoy HTTP过滤器基础

HTTP 过滤器

  • 与网络级过滤器堆栈非常相似,Envoy 在连接管理器中支持 HTTP 级过滤器堆栈。可以编写对 HTTP 级别消息进行操作的过滤器,而无需了解底层物理协议(HTTP/1.1、HTTP/2 等)或多路复用功能。HTTP 级别过滤器分为三种类型:
    • 解码器:当连接管理器解码请求流的部分(标题、正文和尾部)时,调用解码器过滤器。

    • 编码器:当连接管理器将要对部分响应流(标头、正文和尾标)进行编码时,将调用编码器过滤器。

    • 解码器/编码器:解码器/编码器过滤器在连接管理器对请求流的部分进行解码和连接管理器将要对响应流的部分进行编码时调用。

  • HTTP 级别过滤器的 API 允许过滤器在不了解底层协议的情况下运行。与网络级过滤器一样,HTTP 过滤器可以停止并继续迭代到后续过滤器。这允许更复杂的场景,例如运行状况检查处理、调用速率限制服务、缓冲、路由、为 DynamoDB 等应用程序流量生成统计信息等。HTTP 级别的过滤器还可以在上下文中共享状态(静态和动态)单个请求流。Envoy 已经包含了几个 HTTP 级别的过滤器,这些过滤器记录在这个架构概述以及配置参考中

过滤器排序

  • http_filters 字段中的过滤器排序很 重要。如果过滤器按以下顺序配置(并假设所有三个过滤器都是解码器/编码器过滤器):
http_filters:
  - A
  - B
  # The last configured filter has to be a terminal filter, as determined by the
  # NamedHttpFilterConfigFactory::isTerminalFilterByProto(config, context) function. This is most likely the router
  # filter.
  - C

连接管理器将按以下顺序调用解码器过滤器:ABC。另一方面,连接管理器将以相反的 顺序调用编码器过滤器:CBA

条件过滤器配置

这是一个示例 Envoy 配置,它使用复合过滤器通过故障过滤器注入不同的延迟。它使用 header x-fault-category来确定要使用哪个故障配置:如果 header 等于 string ,则注入 10s 延迟,而如果 header 包含1s 延迟则注入。如果标头不存在或包含不同的值,则不实例化过滤器。

admin:
  address:
    socket_address: {address: 0.0.0.0, port_value: 9901}

static_resources:
  listeners:
  - name: listener1
    address:
      socket_address: {address: 0.0.0.0, port_value: 51051}
    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: grpc_json
          codec_type: AUTO
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              # NOTE: by default, matching happens based on the gRPC route, and not on the incoming request path.
              # Reference: https://envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/grpc_json_transcoder_filter#route-configs-for-transcoded-requests
              - match: {prefix: "/helloworld.Greeter"}
                route: {cluster: grpc, timeout: 60s}
          http_filters:
          - name: composite
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.common.matching.v3.ExtensionWithMatcher
              extension_config:
                name: composite
                typed_config:
                  "@type": type.googleapis.com/envoy.extensions.filters.http.composite.v3.Composite
              xds_matcher:
                matcher_tree:
                  input:
                    name: request-headers
                    typed_config:
                      "@type": type.googleapis.com/envoy.type.matcher.v3.HttpRequestHeaderMatchInput
                      header_name: x-fault-category
                  exact_match_map:
                    map:
                      "huge fault":  # inject 10s latency into all requests
                        action:
                          name: composite-action
                          typed_config:
                            "@type": type.googleapis.com/envoy.extensions.filters.http.composite.v3.ExecuteFilterAction
                            typed_config:
                              name: http-fault
                              typed_config:
                                "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
                                delay:
                                  fixed_delay: 10s
                                  percentage:
                                    numerator: 100
                                    denominator: HUNDRED
                      "tiny fault":  # inject 1s latency into all requests
                        action:
                          name: composite-action
                          typed_config:
                            "@type": type.googleapis.com/envoy.extensions.filters.http.composite.v3.ExecuteFilterAction
                            typed_config:
                              name: http-fault
                              typed_config:
                                "@type": type.googleapis.com/envoy.extensions.filters.http.fault.v3.HTTPFault
                                delay:
                                  fixed_delay: 1s
                                  percentage:
                                    numerator: 100
                                    denominator: HUNDRED
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
  - name: grpc
    type: LOGICAL_DNS
    lb_policy: ROUND_ROBIN
    dns_lookup_family: V4_ONLY
    typed_extension_protocol_options:
      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
        "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
        explicit_http_config:
          http2_protocol_options: {}
    load_assignment:
      cluster_name: grpc
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 50051

过滤路由突变

  • 在 HTTP 过滤器链处理期间,当decodeHeaders()被过滤器调用时,连接管理器执行路由解析并设置指向上游集群的缓存路由。
  • 过滤器有能力在路由解析后,通过setRoute回调和DelegatingRoute机制,直接变异此缓存路由。过滤器可以创建DelegatingRoute的派生/子类,以覆盖特定方法(例如,路由的超时值或路由条目的群集名称),同时保留Delegating route环绕的基础路由的其他属性/行为。然后,可以调用setRoute来手动将缓存的路由设置为此DelegatingRoute实例。
  • 如果链中没有其他过滤器修改缓存的路由选择(例如,过滤器执行的一个常见操作是clearRouteCache(),setRoute将无法生存),则该路由选择将被路由到路由器过滤器,路由器过滤器最终确定请求将转发到的上游集群。

参考文档

https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http/http_filters

https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/composite_filter#config-http-filters-composite

https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/http_filters#config-http-filters

posted @ 2022-08-30 14:54  小吉猫  阅读(305)  评论(0编辑  收藏  举报