监听是处理网络请求的第一步,Envoy使用监听器来具体管理监听请求工作,可以同时支持多个监听器,每个监听器负责一类网络请求的监听行为。
1、监听器类型
为了减少对业务的影响,Istio对业务流量采取了透明拦截的方式,Iptables等将拦截后的流量转发到Envoy,因此,为了实现正确的流量路由和转发,Envoy的监听器分为两类:
1)虚拟监听器:需要绑定相应的端口号,同时配置相应的Iptables规则,将Iptables拦截的流量转发到虚拟监听器对应的端口上;
2)真实监听器:用于处理Iptables拦截前的“真实目的地址”,虚拟监听器接收到监听请求时,按照一定的匹配规则查找对应的真实监听器,将新监听请求转交给真实监听器进行处理,真实监听器由于不需要和网络进行交互,因此不需要配置和绑定具体的端口号。
2、监听器建立
LDS配置首次获取或者更新时,均需要建立新的监听器。新建监听器主要有两个工作:一个是对监听过滤插件和网络过滤插件进行初始化,供后续建立新连接时使用;还有一个是创建监听器对应的套接字。
Envoy当前支持UNIX域套接字、UDP和TCP 3种监听方式,对于需要绑定具体端口号的监听器来说,创建相应的套接字后,绑定到相应的端口。
对于热重启的场景来说,为了保证旧的Envoy进程优雅退出,新启动的Envoy进程直接使用旧进程的监听套接字,保证新旧进程之间完美衔接,从而不会带来流量的损失。
3、监听器和工作线程绑定
上面创建的监听器只是“逻辑”上的监听器,并没有和真实的网络建立起联系,因此还不能提供实际的监听工作。Envoy下各个工作线程拥有独自的事件调度器,创建“逻辑”监听器后,会遍历当前所有的工作线程,将监听器加入到每个工作线程中,各个工作线程独立建立自己网络层面的监听器。
4、监听器匹配
Envoy对通信进行接管的基础是透明拦截,拦截后请求的目的地址被统一替换为Envoy虚拟监听器地址,为了完成后续的请求流量识别和路由转发,需要能够有相应的机制还原出原来的目的地址,并根据该目的地址查找到匹配的监听器。新连接到来时会触发逻辑监听器的接收新连接逻辑onAccept函数,onAccept函数的主要逻辑是创建并执行监听过滤插件。
5、协议过滤器匹配
在Envoy中,每个监听器下会对应多个网络过滤插件,每个过滤插件对应一种网络协议类型,处理相应协议的请求解析和路由。在进行监听器配置时会配置每个过滤插件的匹配条件(通过FilterChainMatch字段表示),具体包含目的地址、目的端口号、源地址等,创建新连接时依次根据目的地址、目的端口号等进行匹配判断,查找最合适的网络过滤插件。
6、创建新连接
确定好新连接的网络过滤插件后,新连接对应的传输层也相应确定了,接下来就可以进行传输层新连接的创建流程。newConnection负责新连接的创建。首先创建传输层的连接,然后提交读写就绪事件到事件调度器,等待新数据的到来。