Envoy 基础教程 - Tetrate Academy
1、HTTP/1.1、HTTP/2、HTTP/3 演变
- HTTP/1.1使用 TCP 长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。
- HTTP/1.1请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩
Body
的部分 - HTTP/2 协议是基于 HTTPS 的,会压缩头(Header:
HPACK
算法)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧和数据帧,增加了数据传输的效率。 - HTTP/2 多个请求复用一个TCP连接,一旦发生丢包,就会阻塞住所有的 HTTP 请求。所以 HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP(基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输)
2、Envoy 是一个 L3/L4 网络代理,根据 IP 地址和 TCP 或 UDP 端口进行决策。它具有一个可插拔的过滤器链,可以编写你的过滤器来执行不同的 TCP/UDP 任务。过滤器链(Filter Chain) 的想法借鉴了 Linux shell,即一个操作的输出被输送到另一个操作中。例如:
ls -l | grep "Envoy*.cc" | wc -l
Envoy 可以通过堆叠所需的过滤器来构建逻辑和行为,形成一个过滤器链。
Envoy 支持一个额外的 HTTP L7 过滤器层。我们可以在 HTTP 连接管理子系统中插入 HTTP 过滤器,执行不同的任务,如缓冲、速率限制、路由 / 转发等。
3、Envoy 支持作为 gRPC 请求和响应的路由和负载均衡底层所需的所有 HTTP/2 功能。
gRPC 是一个开源的远程过程调用(RPC)系统,它使用 HTTP/2 进行传输,并将协议缓冲区作为接口描述语言(IDL),它提供的功能包括认证、双向流和流量控制、阻塞 / 非阻塞绑定,以及取消和超时。
4、Envoy 的特点使其非常适合作为边缘代理运行。这些功能包括 TLS 终端、HTTP/1.1、HTTP/2 和 HTTP/3 支持,以及 HTTP L7 路由。
5、请求流:listeners---routes----clusters----endpoints
5.1、Envoy 暴露的监听器listeners是命名的网络位置,可以是一个 IP 地址和一个端口( 监听0.0.0.0:10000
),也可以是一个 Unix 域套接字路径。Envoy 通过监听器接收连接和请求。
构件(路由routes),需要创建一个或多个网络过滤器链(filter_chains
),Envoy 定义了三类过滤器:监听器过滤器、网络过滤器和 HTTP 过滤器。监听器过滤器在收到数据包后立即启动,通常对数据包的头信息进行操作。监听器过滤器包括代理监听器过滤器(提取 PROXY 协议头),或 TLS 检查器监听器过滤器(检查流量是否为 TLS,如果是,则从 TLS 握手中提取数据)。根据传入的请求或连接属性选择不同的过滤器链。
一个特殊的、内置的网络过滤器被称为 HTTP 连接管理器过滤器(HTTP Connection Manager Filter)或 HCM。HCM 过滤器能够将原始字节转换为 HTTP 级别的消息。它可以处理访问日志,生成请求 ID,操作头信息,管理路由表,并收集统计数据。Envoy 也支持在 HCM 过滤器中定义多个 HTTP 级过滤器。
HTTP 过滤器链中的最后一个过滤器必须是路由器过滤器(envoy.filters.HTTP.router
,在 HCM 过滤器的 route_config
字段下定义路由配置)。路由器过滤器负责执行路由任务。这最终把我们带到了第二个构件 —— 路由。
5.2、routes:路由配置route_config中的顶级元素是虚拟主机virtual_hosts。每个虚拟主机都有一个名字,在发布统计数据时使用(不用于路由),还有一组被路由到它的域domains。在大多数情况下,从配置中直接发送响应direct_response是一个很好的功能,但我们会有一组端点或主机,我们将流量路由到这些端点或主机。在 Envoy 中做到这一点的方法是通过定义集群clusters。使用 routes
字段并指定集群cluster
名称。
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
http_filters:
- name: envoy.filters.http.router
route_config:
name: my_first_route
virtual_hosts:
- name: direct_response_service
domains: ["*"]
routes:
- match:
prefix: "/"
---> route:
cluster: hello_world_service
5.3、clusters集群的定义与监听器的定义在同一级别,使用 clusters
字段。我们在路由配置中引用集群时,以及在导出统计数据时,都会使用集群。该名称在所有集群中必须是唯一的。在 load_assignment
字段下,我们可以定义要进行负载均衡的端点列表,以及负载均衡策略设置。
*:基于地域性的(locality),通常用于定义故障转移架构。这种层次结构允许我们定义地理上比较接近的 "首选" 端点,以及在 "首选" 端点变得不健康的情况下应该使用的 "备份" 端点。
5.4、endpoints
字段定义了一组属于特定地域的端点。和监听器的地址一样,端点地址可以是一个套接字地址(socket_address:127.0.0.1:8000),也可以是一个 Unix 域套接字。