开源网关的技术总结
1. 开源网关的测试分析
脱离场景谈性能,都是“耍流氓”。性能就像温度,不同的场合下标准是不一样的。同样是18摄氏度,老人觉得冷,年轻人觉得合适,企鹅觉得热,冰箱里的蔬菜可能容易坏了。
同样基准条件下,不同的参数和软件,相对而言的横向比较才有价值。比如同样的机器(比如16GB内存/4核),同样的Server(用Spring Boot,配置路径为api/hello,返回一个helloworld),同样的压测方式和工具(比如用wrk,10个线程,20个并发连接)。我们测试直接访问Server得到的极限QPS(QPS-Direct,29K);配置了一个Spring Cloud Gateway做网关访问的极限QPS(QPS-SCG,11K);同样方式配置一个Zuul 2做网关压测得到的极限QPS(QPS-Zuul2,13K);Kong得到的极限QPS(QPS-Kong,21K);OpenResty得到的极限QPS(QPS-OR,19K)。这个对比就有意义了。
Kong的性能非常不错,非常适合做流量网关,并且对于service、route、upstream、consumer、plugins的抽象,也是自研网关值得借鉴的。
对于复杂系统,不建议业务网关用Kong,或者更明确地说是不建议在Java技术栈的系统深度定制Kong或OpenResty,主要是出于工程性方面的考虑。举个例子:假如我们有多个不同业务线,鉴权方式五花八门,都是与业务多少有点相关的。这时如果把鉴权在网关实现,就需要维护大量的Lua脚本,引入一个新的复杂技术栈是一个成本不低的事情。
Spring Cloud Gateway/Zuul 2对于Java技术栈来说比较方便,可以依赖业务系统的一些通用的类库。Lua不方便,不光是语言的问题,更是复用基础设施的问题。另外,对于网关系统来说,性能不会差一个数量级,问题不大,多加2台机器就可以“搞定”。
从测试的结果来看,如果后端API服务的延迟都较低(例如2ms级别),直连的吞吐量假如是100QPS,Kong可以达到60QPS,OpenResty是50QPS,Zuul 2和Spring CloudGateway大概是35QPS,如果服务本身的延迟(latency)大一点,那么这些差距会逐步缩小。
目前来看Zuul 2的“坑”还是比较多的:
(1)刚出不久,不成熟,没什么文档,还没有太多的实际应用案例。
(2)高并发时出错率较高,1000并发时我们的测试场景有近50%的出错率。
简单使用或轻度定制业务网关系统,目前建议使用Spring CloudGateway作为基础骨架。
2. 各类网关的Demo与测试
以上测试用到的模拟服务和网关Demo代码,大部分可以在这里找到:
https://github.com/ kimmking/atlantis。
我们使用Vert.x实现了一个简单网关,性能跟Zuul 2和Spring Cloud Gateway差不多。另外也简单模拟了一个Node.js做的网关Demo,加了keep-alive和pool,Demo的性能测试结果大概是直连的1/9,也就是Spring Cloud Gateway或Zuul 2的1/4左右。
百亿流量交易系统API网关设计
百亿流量交易系统API网关的现状和面临问题
1. 百亿流量系统面对的业务现状
百亿流量系统面对的业务现状如图7-11所示。
我们目前面临的现状是日常十几万的并发在线长连接数(不算短连接),每天长连接总数为3000万+,每天API的调用次数超过100亿次,每天交易订单数为1.5亿个。
在这种情况下,API网关设计的一个重要目标就是:如何借助API网关为各类客户提供精准、专业、个性化的服务,保障客户实时地获得业务系统的数据和业务能力。
2. 网关系统与其他系统的关系
某交易系统的API网关系统与其他系统的关系大致如图7-12所示。
3. 网关系统典型的应用场景
我们的API网关系统为Web端、移动App端客户提供服务,也为大量API客户提供API调用服务,同时支持REST API和WebSocket协议。
作为实时交易系统的前置系统,必须精准及时为客户提供最新的行情和交易信息。一旦出现数据的延迟或错误,都会给客户造成无法挽回的损失。
另外针对不同的客户和渠道,网关系统需要提供不同的安全、验证、流控、缓存策略,同时可以随时聚合不同视角的数据进行预处理,保障系统的稳定可靠和数据的实时精确。
4. 交易系统API的特点
作为一个全球性的交易系统,我们的API特点总结如下。
- 访问非常集中:最核心的一组API占据了访问量的一半以上;
- 访问非常频繁:QPS非常高,日均访问量非常大;
- 数据格式固定:交易系统处理的数据格式非常固定;
- 报文数据量小:每次请求传输的数据一般不超过10KB;
- 用户全世界分布:客户分布在全世界的各个国家;
- 分内部调用和外部调用:除了API客户直接调用的API,其他的API都是由内部其他系统调用的;
- 7×24小时不间断服务:系统需要提供高可用、不间断的服务能力,以满足不同时区客户的交易和自动化策略交易;
- 外部用户有一定技术能力:外部API客户,一般是集成我们的API,实现自己的交易系统。
5. 交易系统API网关面临的问题
问题1:流量不断增加。
如何合理控制流量,如何应对突发流量,如何最大限度地保障系统稳定,都是重要的问题。特别是网关作为一个直接面对客户的系统,出现的任何问题都会放大百倍。很多千奇百怪的从来没人遇到的问题随时都可能出现。
问题2:网关系统越来越复杂。
现有的业务网关经过多年发展,里面有大量的业务嵌入,并且存在多个不同的业务网关,相互之间没有任何关系,也没有沉淀出基础设施。
同时技术债务太多,系统里硬编码实现了全局性网关策略及很多业务规则,导致维护成本较大。
问题3:API网关管理比较困难。
海量并发下API的监控指标设计和数据的收集也是一个不小的问题。7×24小时运行的技术支持也导致维护成本较高。
问题4:选择推送还是拉取。
使用短连接还是长连接,REST API还是WebSocket?业务渠道较多(多个不同产品线的Web、App、API等形成十几个不同的渠道),导致用户的使用行为难以控制。
业务网关的设计与最佳实践
1. API网关1.0
我们的API网关1.0版本是多年前开发的,是直接使用OpenResty定制的,全局的安全测试、流量的路由转发策略、针对不同级别的限流等都是直接用Lua脚本实现。
这样就导致在经历了业务飞速发展以后,系统里存在非常多的相同功能或不同功能的Lua脚本,每次上线或维护都需要找到受影响的其中几个或几十个Lua脚本,进行策略调整,非常不方便,策略控制的粒度也不够细。
2. API网关2.0
在区分了流量网关和业务网关以后,2017年开始实现了流量网关和业务网关的分离,流量网关继续使用OpenResty定制,只保留少量全局性、不经常改动的配置功能和对应的Lua脚本。
业务网关使用Vert.x实现的Java系统,部署在流量网关和后端业务服务系统之间,利用Vert.x的响应式编程能力和异步非阻塞I/O能力、分布式部署的扩展能力,初步解决了问题1和问题2,如图7-13所示。