Envoy 与 Nginx 的八大对比
Envoy 与 Nginx 架构层面的对比 Nginx 是 Envoy 出现之前网络通信中间件领域非常有代表性的开源系统,功能强大,性能出色,扩展性很强,已经形成了强大的生态,成为 HTTP 流量管理领域事实上的标杆。Envoy 作为后起之秀,虽然定位和目标上与 Nginx 有不少差异,但架构设计层面,Envoy 和 Nginx 都有很多的可取之处,下面会从功能定位、整体网络模型、连接处理、请求解析、插件机制、配置管理、部署和运维、管理方式等诸多维度,对 Envoy 和 Nginx 进行详细剖析和比较,通过与 Nginx 功能和架构层面的全方位对比,大家也可以对 Envoy 的架构设计有更立体的认识。
一、功能与定位
Nginx 最核心的功能是 Web 服务器和反向代理服务器,Web 服务器完成对 HTTP 请求协议的解析和以 HTTP 协议格式响应请求、缓存、日志处理这些基本 Web 服务器功能;反向代理服务器完成对请求的转发、负载均衡、鉴权、限流、缓存、日志处理等代理常用功能。Nginx 还支持普通的 TCP、UDP 反向代理功能,同时以 stream 方式支持通用的基于 4 层协议的反向代理,比如 MySQL 代理、Memcached 代理等。
Envoy 定位是透明接管微服务之间的通信流量,将通信和服务治理功能从微服务中解耦,通过 Envoy 可以方便地增加对自定义协议的支持。
Nginx 的关键词是 Web 服务器和反向代理,是显式调用;Envoy 是透明接管流量,是隐式调用,更加体现对流量的控制和掌控力。
二、网络模型
网络模型上,Nginx 采用的是经典的多进程架构,由 master 进程和 worker 进程组成。其中,master 进程负责对 worker 进程进行管理,worker 进程负责处理各种网络事件,各个 worker 进程之间相互独立。
Envoy 采用了多线程的网络架构,Envoy 一般会根据当前 CPU 核数创建相同个数的 worker 线程,所有 worker 线程同时对 Envoy 配置的监听器进行监听,接受新的连接,为每个新连接实例化相应的过滤器处理链,处理该连接上的所有请求。
三、连接处理
Nginx 通过 worker_connections 参数来控制每个 worker 能够建立的最大连接数,从 Nginx 网络模型可以看出,客户端连接到来时,所有空闲的进程都会去竞争这个新连接。对连接进行精细化管理,Nginx 采取的方式是各工作进程根据自身的忙闲程度,动态调整获取新连接的时机。
Envoy 也会遇到和 Nginx 类似的负载不均问题,Envoy 当前发展很快,同时需要解决的问题很多。后续会根据具体情况对这个问题进行讨论和解决。
四、插件机制
Nginx 拥有强大的插件扩展能力,基于 Nginx 的插件扩展机制,业务可以非常方便地完成差异化和个性化定制,Nginx 插件通过模块的方式提供,具体来说,Nginx 主要提供如下几种形式的插件扩展:
1)通过 stream 机制进行协议扩展,比如增加 memcached 协议代理和负载均衡等;
2)以 Handler 方式处理 HTTP 请求;
3)对 HTTP 请求和响应消息进行过滤,比如可以修改和定制消息内容等;
4)访问 Upstream 时的负载均衡,可以提供自定义的负载均衡机制。
Envoy 也提供了强大的插件扩展机制,当前使用最多的地方是监听过滤插件和网络处理过滤插件。和 Nginx 相比,Envoy 网络插件定位在协议层面,以 HTTP 协议为例,Envoy 并没有那么细粒度的插件扩展机制,如果想对 Envoy 的 HTTP 协议处理进行扩展,当前并没有提供特别多的扩展点。
Envoy 的插件当前采用的是静态注册的方式,插件代码和 Envoy 代码一块进行编译,和 Nginx 不同,Envoy 从最开始就支持插件的动态加载,Envoy 通过独特的 XDS API 设计,可以随时对 Envoy 的 XDS 插件进行定制修改,Istio 将修改后的 XDS 配置通过 Grpc 的方式推送给 Envoy 动态加载和生效。
五、配置管理
Nginx 的配置格式使用自定义的方式,配置结构和配置解析过程都非常复杂。配置组织上,Nginx 采用层层嵌套的方式,最外层是核心模块的配置,主要包括 events 事件模块、http 模块和 stream 模块。对于最复杂的 http 模块来说,下面会嵌套着 server 子模块,负责监听和管理 http 请求,server 子模块下还会嵌套着一到多个 location,用于描述具体的路由规则。Nginx 的配置解析代码可以说是 Nginx 整个源码体系中最晦涩难懂的部分,配置解析的核心代码在 ngx_conf_file.c 中,通过层层嵌套解析,形成了一棵树状的配置信息结构。
Envoy 的配置管理部分设计得就比较优雅,配置格式直接使用了 Protobuf 3,复用了 Protobuf 3 的数据描述能力和自动代码生成机制,完全省去了配置解析的过程,并且也非常方便对配置格式的有效性进行验证。Nginx 的配置都是静态配置,不支持任何形式的动态配置能力。动态配置能力是 Envoy 相比 Nginx 最核心的竞争力,通过动态配置,可以在线修改流量路由和链路治理策略,实现策略配置修改的即时生效。
六、内存管理
Nginx 内存管理通过 Nginx 内存池实现,通过内存池的良好设计,使用内存池进行内存管理时,不需要关注内存什么时候释放,连接销毁时会回收连接对应的内存资源;同时通过内存池可以减少内存碎片,通过内存对齐、内存分页等机制,可以有效减少缓存未命中(Cache Miss),提高内存访问的效率。
Envoy 在内存管理方面的支持还很粗糙,直接基于原生的内存管理库,内存释放时机管理通过智能指针管理内存的生命周期。和 Nginx 相比,Envoy 在内存管理方面提供的支持不多,完全依赖智能指针机制,对使用者的要求比较高,同时无法满足对性能的极致要求。
七、部署与运维
从运维上说,Nginx 采用多进程的通信架构,主进程负责维护工作进程的状态,主要有以下两方面。一方面,监控工作进程的状态,状态异常时会对工作进程进行重启;另一方面,主进程也可以接收外界的管理信号,通知工作进程完成相应的操作。
Envoy 是通过控制平面组件 Pilot Agent 和 Sidecar-injection 进行管理,Pilot Agent 负责管理 Envoy 的运行状态,当 Envoy 状态有问题时,Pilot Agent 会将 Envoy 重启,如果重启仍然不能解决问题,会尝试将 Envoy 调度到其他环境下;Sidecar-injection 负责 Envoy 的自动注入。因此,从架构上看 Nginx 是自运维的,Envoy 是借助控制平面来完成 Envoy 运行状态的管理,运维上比 Nginx 方便。
从架构上看 Nginx 是自运维的,Envoy 是借助控制平面来完成 Envoy 运行状态的管理,运维上比 Nginx 方便。
八、观测与诊断
从服务的可观测以及诊断上说,Envoy 投入了大量的精力,已经全面支持 Log、Metric、Trace 等可观测机制,并且每种观测方式均提供相应的扩展机制,Nginx 在这方面相对逊色很多,可观测以及诊断支持上相对弱一些,当前可能是为了和商业版进行区分,Nginx 商业版有完善的运维和问题诊断支持。
版权声明: 本文为 InfoQ 作者【阿泽🧸】的原创文章。
原文链接:【http://xie.infoq.cn/article/fbb3f87fd4df82fea8ec7497f】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论