2019 年 10 月 27 日,又拍云联合 Apache APISIX 社区举办 API 网关与高性能服务最佳实践丨Open Talk 杭州站活动,Apache APISIX PPMC 成员王院生做了题为《 Apache APISIX 微服务网关极致性能架构解析》的分享。本次活动,邀请了来自阿里巴巴、蚂蚁金服、Apache APISIX、PolarisTech、又拍云等企业的技术专家,分享网关和高性能服务的实战经验。
王院生,深圳支流科技创始人,Apache APISIX PPMC 成员,OpenResty 社区发起人,《 OpenResty 最佳实践》作者。
以下是分享全文:
前言
大家好,我是来自深圳支流科技的王院生。今年 3 月份,我和志同道合的伙伴一起创业,发起了 APISIX 项目,目前这个项目已进入 Apache 孵化器。Apache APISIX 是一个高性能、可扩展的微服务 API 网关。它是基于 Nginx 和 etcd 来实现,和传统 API 网关相比,APISIX 具备动态路由、插件热加载、gRPC 协议转换等功能,特别适合微服务体系下的 API 管理。
Apache APISIX 是一个蓬勃发展的开源项目,在 2019 年 6 月 6 号开源后,很快就获得了开发者的关注和兴趣,并在开源一个月后被收录到 CNCF(云原生软件基金会) 的全景图中。现在 Apache APISIX 在 GitHub 有 1500 多个 star,近40 多名贡献者,是一个聚集了 800 多人的开发者社区。从开源之初,APISIX 保持每个月发布一个版本,并坚持测试驱动开发、自动化 CI/CD 等理念,以保证代码的质量和稳定性。
Apache APISIX 微服务网关
微服务 API 网关
API 网关并非一个新兴的概念,在十几年前就已经存在了,它的作用主要是作为流量的入口,统一处理和业务相关的请求,让 API 更加安全、快速和准确的得到处理,它有以下传统功能:
- 反向代理和负载均衡,这和 Nginx 的定位和功能是一致的;
- 动态上游、动态 SSL 证书和动态限流限速等运行时的动态功能,这是开源版本 Nginx 并不具备的功能;
- 上游的主动和被动健康检查,以及服务熔断;
- 在 API 网关的基础之上进行扩展,成为全生命周期的 API 管理平台。
最近几年,业务相关的流量不再仅仅是由 PC 客户端和浏览器发起,更多的来自手机、IoT 设备等,未来随着 5G 的普及,这些流量会越来越多。同时,随着微服务架构的结构变迁,服务之间的流量也开始爆发性的增长。在这种新的业务场景下,对 API 网关有了更多新需求:
- 云原生友好,架构要轻巧,便于容器化;
- 对接 Prometheus、Zipkin、Skywalking 等监控组件;
- 支持 gRPC、Dubbo、websocket、MQTT 等协议的代理,以及 http 到 gRPC 之间的协议转换,以便适应更广泛的场景;
- 做身份验证,与 Auth0、okta 等身份认证提供商的服务对接,把流量的安全作为头等大事;
- 通过运行时动态执行用户函数的方式来实现 serverless,让网关的边缘节点更加灵活;
- 支持插件的热加载,新增、删除和修改插件,都不用重启服务;
- 开源不锁定用户,支持混合云的部署架构;
- 最后是网关节点自身要无状态,可以随意的扩容和缩容。
有了这些功能,微服务只需关心业务本身,而与业务相关的周边管理功能,比如服务发现、服务熔断、身份认证、限流限速、统计、性能分析等,均可以在独立的网关层面解决。从这个角度来看,API 网关既可以替代 Nginx 的所有功能处理南北向的流量,也可以胜任 Istio 控制面和 Envoy 数据面的角色,处理东西向的流量。
目前已经有很多可选的网关产品,为什么我们还要进入这个行业进行摸索?我们对现有的产品进行了分析:
- ⾏业老大:大多基于 Java + JS,闭源性能差,不支持⼆次开发
行业老大们的技术方案大多基于 Java + JS 无一例外,因为他们都是十几年前起步,倒退到那个年代能选的方案也只有 Java 。如果阿里是现在才起步的,我相信他也会有不同的技术选择,但是在那个年代做大应用,只有 Java 可选。如果要做动态,基本也就只有 JS 这条路,最后的组合均为 JAVA + JS 技术方案。它的问题也比较明显:性能差,体态臃肿,二次开发较困难。
- 行业远见者:多基于 OpenResty 或 Golang,少数开源
在 Ganter 中远见者行列采用的技术方案目前多是基于 OpenResty 和 Golang,能够看到这些行业远见者在具体实现上,整体都比较重。代码量重往往代表结构复杂,最后也发现他们确实效率不高。
- Apache APISIX 机会:轻巧 + 极致性能 + 热插件
在起步之初,我们意识到必须要比远见者还要好十倍以上,我们才有成功的可能。此时我们看清了要走的一条路:第一要轻巧,第二需要性能极致。最后如果再有丰富的插件生态,就更完美了。
Apache APISIX 发展历程
4 月初,我们开始第一行代码,我们选择在 6 月 6 日开源,因为产品名叫 APISIX,我们希望它容易被大家记住。
7 月,APISIX 进入 CNCF 全景图,这是目前最火的软件基金会。
8 月,我们拥有了第一家商业用户,搞定商业用户的过程确实非常爽,借助 APISIX 内核前两周,就帮用户把 QPS 提升了一倍。
9 月,开源用户贝壳找房正式上线,现在每天至少有 1 亿的流量需要处理(截止目前已经有 2.5 亿日流量),它的 CPU 大约 1% 左右。
9 月我们也开始和 Apache 接触,着手准备捐赠,10 月就真正成功了。这应该是国内第一家由初创公司捐赠的 Apache 项目。通常一个项目要进入 Apache 基本都是以年为单位,但我们只用了一个月。
10 月,我们在继续奔跑,已实现了全平台支持。除了常见的操作系统,两大主流 X86 架构和 ARM64 架构也均全部支持,并经过完整用例回归。APISIX 是一个测试驱动的项目,测试覆盖率到 80% 以上,只要测试用例能完整运行,可以确保在生产中正常使用。
Apache APISIX 的优势
以下是 Apache APISIX 引以为傲的点,它们大多是是竞品完全没有的:
- ASF 第一个 API ⽹关类项⽬
- 极简核⼼代码量,不到 4000 ⾏,去除空行、注释行数甚至不到 3000 行
- 极致的动态转发性能,测试报告显示属于 NO.1
- 最低的平均请求延迟:740 us
- 插件热加载/卸载,新旧插件均可,同类竞品中独一无二
- 允许插件挂载 Nginx 任何阶段
- 所有的组件都是插件,包括路由自身,这在业内是独一份的,把自由交给用户
- 完整支持 ARM64
- 完整支持 IPv6
- 动态转发物联⽹ MQTT 协议
- 运行时可以是 OpenResty / Tengine ,自由选择
- 极致性能校验器 iresty / jsonschema ,已知 jsonschema 校验器实现方案中性能最高
Apache APISIX 技术选型
API 网关产品形态演化
如上图所示,图 ① 为网关最初的产品形态,左侧是客户端,右侧是服务,网关在他们中间;由于服务会做聚集分类,如图 ② 中服务分成两类,此时 API 网关的重要性就体现出来,它需要对外做无感知,需要根据用户请求的流量信息做分发,此时 API 网关就会成为单点故障;由此演化出图 ③ 的形态,有两个 API 网关,它们都可以访问后面的任何一个服务集群,互为备份,是一个高可用的基本形态,客户端可以请求任意一个网关;在图 ④ 中,API Gateway 负责流量转发,etcd 负责配置存储,API Gateway 是管理人员的控制台,所以如果只有 API Gateway 高可用是远远不够的。
真正能够让用户安心的方案应该是 API Gateway、配置中心、控制中心都能够完整支持高可用,作为一个微服务 API 网关需要部署灵活,API Gateway、etcd、管理控制台均需要满足任意数量伸缩,需要多少就部署多少。
这对我们的开源版本提出了一个非常高的挑战,安装形态到底应该什么样子?
我们需要有上图中的三种形态都允许用户去部署:Admin、Gateway、Gateway+Admin。我们的解决方案首先是 All In One,即只有一个 “Gateway+Admin” 的包,当用户需要将 Gateway 和 Admin 分别部署时,只需修改配置,是否启用 Admin 就可以实现。
我们通过配置的方式简单区分节点类型,而任何一个节点里面,既可以单独包含一部分,如 Admin 或者 Gateway,也可以同时包含二者,这种方式让用户能够很容易地解决一堆问题,实现高可用、弹性伸缩、分布式、集群以及故障自动转移。
API 网关基本架构
下面介绍 API 网关的基本架构,这里简单对它做了拆分:
整个流程是管理员通过 admin API 告诉网关需要做什么并保存下来,这也就是我们常说的控制面。相对的是数据面部分处理外部用户真实请求,要根据管理员的规则,对当前请求根据路由匹配得到配置,然后执行配置中的插件并转发到指定上游。
这里涉及三个最基本问题:
- 路由:匹配用户请求,需要功能强大,并且性能足够好
- 校验器:校验用户请求数据是否合法,需要通用、高性能
- 配置中心:存储配置,高可用易用,支持增量订阅
如果这三个基本问题回答好,那么这个网关质量也就基本确定了。
Apache APISIX 技术选型
核心思路:技术选型时需要思考到底需要解决什么问题?
- 配置中心:高可用、增量订阅、历史记录
- 语言或开发平台:动态、高性能、网关的周边资源丰富
- 数据校验:开放标准、有一定的生态系统
- 加分项:顶级路由实现
- 选型捷径:学习竞对,从 Ganter 报告中获取前辈列表,做分析和比较,尝试站在巨人肩膀总是对的
配置中心:etcd why?
APISIX 配置中心并没有选择传统的关系型数据库,而是选用了 etcd,当时主要考虑到以下要素:
- 优雅的集群支持
- 支持历史,可以获取到历史的修改记录
- 要能够支持事务,有些数据的存放是有条件的
- 低于毫秒级别的变化通知
通过分析发现 etcd 非常适合我们,当真正看到官方的 why etcd 的说明列表时(如下图),我们就知道我们选对了。
语言和开发平台:OpenResty
新选型 API 网关开发平台基本只有两条路,一个是Lua,即 OpenResty,另一个就是 Golang。Golang 是静态语言,其动态能力不如 Lua ,所以最后选择 OpenResty。我个人从 2014 年到现在一直沉浸在 OpenResty 社区,对它的理解和把控力也会更好。
我们是全新的项目,所以我们直接基于最新的版本来做,OpenResty >= 1.15.8,Tengine>= 2.3.2,二者都是基于 Nginx,搭配他们任何一个作为运行时都可以运行 APISIX。
我们需要借助更通用的语言来吸纳它的周边生态,这方面 Lua 与 C/C++ 是不在一个量级,常见做法可以通过调用 C/C++ 的动态库来这么做。此外,也可以调用基于 Golang 的库。从这个角度看,我们选择 OpenResty 作为基础平台开展 APISIX 业务开发会很顺畅,不用担心周边库匮乏的问题。而且 OpenResty 这几年被用在 API 网关比较多,有很多现成组件也可以利用,APISIX 可能只需要拿过来做二次整合。当然整合过程中也发现了一些项目的开源版本写得不好,二次优化的事情也没少干。
数据校验:jsonschema
jsonschema 的数据校验规范 Google 排名第一,换而言之,如果有校验规范且已经排名第一,我们没有必要自己造一个,知识一定要可以复用,于是选择了 jsonschema 这个标准。这个校验标准几乎涵盖了 C、Java、JS 等主流语言,而且官方提供现成的压测结果。我们任何选型都会格外关注性能表现,如果有现成的压测框架和结果就非常棒。
当然,在实际操作中经历了一些波折:最开始选型在 jsonschema 官方找实现,结果发现没有适合我们的,他们大多都是开源库中用了一点便声称支持,实际上耦合度比较高。
我们找到的第一个选型是 lua-rapidjson,它并不在 jsonschema 官方的推荐列表里,是腾讯开源的。但 rapidjson 有一个比较大的问题是编译条件高,它是一个 C/C++ 的实现,而我们做的是开源的项目,简单易用是我们追求的。此外 rapidjson 只支持了 draft4 里 95% 的内容,有些特性也不支持,比如经常用到的 default 。
于是我们根据一个开源的方案进行改造,实现了新的 iresty / jsonschema,主要增加了下面一些点:
- 运行时支持 OpenResty
- 完整支持 draft4
- 完整支持 draft6、draft 7
这个库采用了编译器的思维方式。我们对其进行了测试:一个简单的对象里面有两个字段,分别是字符串和一个 int 类型,反复进行循环压力测试,跑一百万次,将跑完的时间做比较。iresty / jsonschema 的性能是 lua-rapidjson 的 5-10倍,是 gojsonschema(golang) 性能的 500-1000 倍。
路由:为什么造了 resty-radixtree 路由?
路由是 API 网关的生命,没有高性能的路由,就没有快速的匹配过程,API 网关的性能无法提升。只有路由是 100% 每次参与用户请求的,配置中心和参数校验也不是,因此路由必须要高性能。同时路由匹配条件也要足够灵活和强大,除了要支持最基本的 uri、host,其他可选的如 IP 地址、请求参数、请求头、Cookie 等也需要。
原本以为做到这一步就可以了,但开源项目的用户还是会有其他的需求,最后我添加了自定义函数,用户可以写 Lua 脚本,这也再次使用了 Lua 的动态特性。换而言之,用户完全可以创建判断规则,涉及特别不好表达或还未支持的逻辑,都可以用自定义函数方式先绕着走。
集大成者的路由 resty-radixtree,目前单核心每秒可以达到百万次的匹配,相比之前的选型 libr3,radixtree 的性能至少提升了一个数量级。并且它允许引用任意的 nginx 的内置变量,索引的自由创建也让它轻松支持 uri 或 host+uri 的使用场景。
自此三个选型确定:路由 resty-radixtree,校验器 iresty / jsonschema,配置中心 etcd,Apache APISIX 雏形诞生。
Apache APISIX 架构
如上图,这是 Apache APISIX 目前的业务架构:左侧是管理员,右侧是用户请求。管理员把信息录入放到 etcd 里面缓存后,用户访问 APISIX 做路由,根据路由信息得到结果,匹配到路由交给具体的微服务、serverless 等。
如上图,APISIX 软件层面基本架构并没有采用传统的层层嵌套的方式,只有基础层和业务层,基础层完全脱离于 APISIX 内核,完全无业务绑定,大家可以在任何 OpenResty 项目中引用。
插件可以热插拔,不用重启服务。并且已经内置了常见的限流限速、身份认证、请求改写、URI 重定向、opentracing、serverless 等插件,开箱即用。APISIX 对插件的支持和友商不太一样,具体表现在以下几点:
- 按需“继承”
- 优先级排序
- 允许挂载 Nginx 所有阶段
- 插件热加载、卸载
- 插件临时禁⽤
总结 Apache APISIX 三板斧如下:
- 配置分发借助 etcd ,精简核心
- 基于 resty-radixtree 的高性能前缀匹配
- 高性能基础库apisix/core:Nginx 变量提取增强 ;错误日志优化;table 池优化
Apache APISIX 性能测试
Apache APISIX 目前已经具备 30 多个功能,已经基本超过大多开源竞品。通常来说,引入了前面提到的几十项功能,会伴随着性能的下降,那么究竟下降了多少呢?这里我做了一个性能的测试对比。
如上图,右侧是我为了测试写的一个虚假的服务,这个服务是空的,只是把 ngx_lua 里的一些变量拿出来,传给了什么都不做的 fake_fetch,后面的 http filter、log 阶段等一样,没有任何计算量。
随后对 APISIX 和右边的虚假服务分别跑压力测定,对比结果发现 APISIX 的性能仅仅下降了 15%,也就是说在接受了 15% 的性能下降的同时,就可以享受前面提到的所有功能。我们在阿里云的计算平台,单核下可以跑到 23-24k QPS,4 核可以跑到 68k 的 QPS。
以上就是王院生老师在 Open Talk 杭州站现场分享整理,温馨提示 12 月 14 日 API 网关与高性能服务最佳实践·广州站活动正在报名中 /jB9KO
演讲视频观看及 PPT 下载:
Apache APISIX 微服务网关极致性能架构解析