Network Filter#
Network Filter Chains#
在前面章節的 图:Istio里的 Envoy Inbound 配置举例 中,可以看出,一个 Listener 可以包含多个 Network Filter Chain
。而其中每个 Chain 都有自己的 filter_chain_match
,用于配置新建立的 Inbound Connection
选定 Network Filter Chain
的策略。
每个 Network Filter Chain
都有自己的名字。需要注意的是,Network Filter Chain
的名字是允许重复的。
每个 Network Filter Chain
又由顺序化的 Network Filter
组成。
Network Filter 概述#
Envoy 对为保证扩展性,采用多层插件化的设计模式。其中,Network Filter
就是 L2 / L3 (IP/TCP) 层的组件。如,上面的 图:Istio里的 Envoy Inbound 配置举例 中,顺序地有:
istio.metadata_exchange
Network Filter
envoy.filters.network.http_connection_manager
Network Filter
两个 Network Filter。其中,主要逻辑当然在 http_connection_manager
了。
Network Filter 框架设计概念#
我在学习 Envoy 的 Network Filter 框架设计时,发现它和我想像中的 Filter 设计非常不同。甚至有点违反我的直觉。见下图:
以下仅以 ReadFilter 说说:
我直觉中的模型(My intuition Ideal model)
是:
Filter 框架层有
Upstream
这个概念一个 Filter 的输出数据和事件,会是下一个 Filter 的输入数据和事件。因为这叫 Chain,应该和 Linux 的
cat myfile | grep abc | grep def
类似。Filter 之间逻辑上的 Buffer 应该是隔离的。
而 现实的模型(Realistic model)
中
框架层面,没有
Upstream
这个概念。Filter 实现自行实现/不实现 Upstream,包括连接建立和数据读写,事件通知。所以,框架层面,更没有 Cluster / Connection Pool 等等概念了。见下面一项
Filter 之间共享了 Buffer,前面的 Filter 对 Buffer 的读操作,如果沒进行
drained(排干)
,后面的 Filter 将会重复读取数据。前面的 Filter 也可以在 Buffer 中插入新数据。 而这个有状态的 Buffer,会传递到后面的 Filter 。由于 “框架层面,没有
Upstream
这个概念” 所以WriteFilter
也不是直觉中的向Upstream
写 Request/Data 的模块,而是向Downstream
写 Response/Data 的模块。
Network Filter 对象关系#
写到这里,是时候看看代码了。不过,不是直接看,先看看 C++ 类图吧。
可见,大家日常生活中,WriteFilter
并不常用 :) 。
Network Filter 框架设计细说#
在代码实现层, Network Filter 框架下,抽象对象间的协作关系如下:
下面,以经典的 TCP Proxy Filter 为例,说明一下。
Network Filter - ReadFilter 协作#
ReadFilter 协作比较复杂,也是 Network Filter Framework 的核心逻辑。所以要细说。
如前所言, Framework 本身没的直接提供 Upstream / Upstream Connection Pool / Cluster / Route 这些抽象对象和相关事件。而这里,我们暂且把这些称为:外部对象与事件
。Filter 实现需要自己去创建或获取这些 外部对象
,也需要自己去监听这些 外部事件
。外部事件
可能包括:
Upstream 域名解释完成
Upstream Connection Pool 连接可用
Upstream socket read ready
Upstream write buffer full
…
Network Filter - WriteFilter 协作#
由于 WriteFilter
在 Envoy 中使用场景有限,只有 MySQLFilter / PostgresFilter / KafkaBrokerFilter 和 Istio 的 MetadataExchangeFilter 。所以这里就不展开说明了。
扩展阅读#
如果有兴趣研究 Listener 的实现细节,建议看看我 Blog 的文章: