Apache APISIX 和 Envoy 性能大比拼

在CNCF组织的一场技术分享会上,第一次听到了 Enovy 这么一个东西,分享的嘉宾巴拉巴拉讲了一大堆,啥都没记住,就记住了一个特别新颖的概念“通讯总线”,后面 google 了下 Envoy 这个东西究竟是什么,发现官网上如是描述:node

“Envoy 是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通讯总线”nginx

也就是说, Envoy 是为了解决 Server Mesh 领域而诞生一款 L7 代理软件,这里我网上找了一张图,我理解种的 Envoy 大概是以下的部署架构。(若是错了请大佬指教)git

image
既然是L7的代理软件嘛,做为常年混迹 openresty 社区的老司机,天然忍不住把它拿来搞一搞,对比对比。github

咱们选择的比试对象是最近刚从 Apache 社区毕业的 APISIX,它是基于 OpenResty 实现的 API 网关。(其实也就是 L7 代理而后加了路由、认证,限流、动态上游等等之类的功能)apache

为何选择它呢,由于有一次社区分享的时候据说这货的路由实现很是棒,正好咱们的如今业务的路由系统乱七八糟,扒拉了下 APISIX 的源码,发现确实是6到飞起,吊打我看到过的同类产品, 因此印象深入,就它了!ubuntu

这里附上一张在 APISIX 官网扒拉的图,真是一图胜千言,一看就知道这玩意儿是怎么工做的;api

image

开搞吧,首先咱们去官网找到两个产品的最版本:服务器

Apache APISIX 1.5Envoy 1.14网络

构建环境准备

  • 压力测试客户端:wrk
  • 测试主要指标包括:网关延迟、QPS 和是否线性扩展;
  • 测试环境:微软云 Linux (ubuntu 18.04), Standard D13 v2 (8 vcpus, 56 GiB memory);
  • 测试方式1:采用单核运行横向对比(由于它们都是基于 epoll 的IO模型,因此用单核压测验证它们的处理能力);
  • 测试方式2:采用多核运行横向对比,主要是为了验证二者在添加多(进程|线程)的场景下其总体处理能力是否可以线性增加;

测试场景

这里咱们用 nginx 搭建了一个上游服务器,配置 2 个 worker,接收到请求直接应答 4k 内容,参考配置以下:架构

server {
  listen 1980;
  
  access_log off;
  location = /hello {
    echo_duplicate 400 "1234567890";
  }
}
  • 网络架构示意图以下:(绿色正常负载,未跑满。红色为高压负载,要把进程资源跑满,主要是 CPU)

image

路由配置

首先咱们找到 APISIX 的入门配置指南,咱们添加一条到 /hello 的路由,配置以下:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '{、
    "uri": "/hello",
    "upstream": {
        "type": "roundrobin",
        "nodes": {
            "127.0.0.1:1980": 1
        }
    }}'

须要注意的是,这里没并无开始 proxy_cache 和 proxy_mirror 插件,由于Enovy并无相似的功能;

而后咱们参考 Envoy 官方压测指导 为 Envoy 添加一条路由:

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: "0.0.0.0", port_value: 10000 }

    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          generate_request_id: false,
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/hello" }
                route: { cluster: service_test }
          http_filters:
          - name: envoy.router
            config:
              dynamic_stats: false
  clusters:
  - name: service_test
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    hosts: [{ socket_address: { address: "127.0.0.1", port_value: 1980 }}]
    circuit_breakers:
      thresholds:
        - priority: DEFAULT
          max_connections: 1000000000
          max_pending_requests: 1000000000
          max_requests: 1000000000
          max_retries: 1000000000
        - priority: HIGH
        max_connections: 1000000000
        max_pending_requests: 1000000000
        max_requests: 1000000000
        max_retries: 1000000000

上面的 generate_request_id、dynamic_stats 和 circuit_breakers 部分,在 envoy 内部是默认开启,但本次压测用不到,须要显示关闭或设置超大阈值从而提高性能。(谁能给我解释下为何这玩意儿配置这么复杂 -_-!)

压测结果

单条路由,不开启任何插件。开启不一样 CPU 数量,进行满载压力测试。说明:对于 Nginx 叫 worker 数量,envoy 是 concurrent ,为了统一后面都叫 worker 数量。

进程数 APISIX QPS APISIX Latency Envoy QPS Envoy Latency
1 worker 18608.4 0.96 15625.56 1.02
2 workers 34975.8 1.01 29058.135 1.09
3 workers 52334.8 1.02 42561.125 1.12

注:原始数据公开在 gist 中。

image

QPS:每秒钟完成的请求数,数量越多越好,数值越大表明单位时间内能够完成的请求数量越多。从 QPS 结果看,APISIX 性能是 envoy 的 120% 左右,核心数越多 QPS 差距越大。

Latency:每请求的延迟时间,数值越小越好。它表明每请求从发出后须要通过多长时间能够接收到应答。对于反向代理场景,该数值越小,对请求的影响也就最小。从结果上看,envoy 的每请求延迟要比 APISIX 多 6-10% ,核心数量越多延迟越大。

能够看到二者在单工做线程|进程的模式下,QPS 和 Latency 两个指标差距不大,可是随着工做线程|进程的增长他们的差距逐渐放大,这里我分析可能有如下两方面的缘由,nginx 在高并发场景下用多 worker 和系统的 IO 模型进行交互是否是会更有优点,另一方面,也多是nginx 自身在实现上面对内存和 CPU 的使用比较“抠门”,这样累积起来的性能优点,之后详细评估评估。

总结

整体来讲 APISIX 在响应延迟和 QPS 层面都略优于 Envoy, 因为 nginx 的多 worker 的协做方式在高并发场景下更有优点,得益于此, APISIX 在开启多个 worker 进程后性能提高较 Enovy 更为明显;可是二者并不冲突, Envoy 的总线设计使它在处理东西向流量上有独特的优点, APISIX 在性能和延迟上的表现使它在处理南北向流量上具备海量的吞吐能力,根据本身的业务场景来选择合理的组件配合插件构建本身的服务才是正解。

相关文章
相关标签/搜索