作者 | 卞弘智
本文主要介绍了航空公司互联网能力持续提升的大背景下,国内某大型航空公司移动互联网基础架构团队针对南北向网关从 NGINX 升级到 APISIX 的历程。
深入解析 NGINX 网关的痛点
我们一直使用 NGINX 作为南北向网关。随着业务规模的发展和产品的增加,从流量的角度来说,NGINX 仍然能很好地满足我们的需求,然而,在其他方面我们遇到了越来越多的痛点:
剖析网关选型,精准匹配业务需求
针对 NGINX 所遇到的各种痛点,我们认真梳理了对新网关产品的三个主要基本需求:
在明确了对现有南北向网关的迭代升级和基本需求之后,我们对市面上流行的多款产品进行了调研,并最终选择了 APISIX 作为我们的新网关。
最终,我们决定采用 APISIX 作为新的网关产品,因为它在功能和性能上均得到了市场的认可。根据测试结果,APISIX 在压力测试下的性能表现相当出色,在没有开启插件的情况下,其性能是 Kong 的 2 倍;而在开启限流和 prometheus 插件后,性能甚至高出 Kong 的 10 倍,延迟仅为 Kong 的十分之一。此外,APISIX 基于 OpenResty 实现,拥有出色的路由功能,进一步增加了我们的信心。另外,与 Kong 相比,APISIX 吸引我们的特点主要集中在以下两个方面:
在前面提到的关于 NGINX 的痛点,也能够通过 APISIX 很好地解决:
NGINX 迁移 APISIX:探索先进解决方案
在 NGINX 中所有的域名管理以及其上的功能实现都是基于 NGINX 的配置文件来实现的。虽然 APISIX 仍然基于 NGINX 和 Openresty,但在 APISIX 中,我们采用了完全不同的方式,不再使用 NGINX 的配置文件来管理域名和实现功能。我们首先根据域名配置路由(route)和其上游(upstream),然后通过插件的形式实现路由上的各种附加功能。
从 NGINX 向 APISIX 的迁移的主要工作是将 NGINX 的各路由以及相关配置用 APISIX 的相关插件进行重构。实际迁移过程远比前面一句话更复杂,我们将这个迁移过程拆分为以下三个主要步骤:
这里我们以一个 CORS 跨域相关的配置来进行举例,我们先把 NGINX 中跨域相关配置提取出来。
add_header 'Access-Control-Allow-Origin' $corsHost;
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization,appver';
if ($request_method = 'OPTIONS') {
return 204;
}
首先理解这段 NGINX 的含义,用 add_header 在 NGINX response 中添加了一些关于跨域配置 header,然后如果 request 方法为 OPTIONS 的话就直接返回 204。在赋值的时候,这里我们还使用了一个变量 corsHost,其定义如下:
map $http_origin $corsHost {
default 0;
"~http://wap.test.com" http://wap.test.com;
"~https://wap.test.com" https://wap.test.com;
}
再从网络层面去理解下这段 NGINX 配置的含义,这一段配置其实是为了实现 CORS 跨域访问, 允许来自于 Access-Control-Allow-Origin 源的请求能够进行跨域访问,请求的方法由 Access-Control-Allow-Methods 定义,同时定义了允许的 Header 和请求可以包含 Cookie 等 credentials 信息。Options 返回 204 是 CORS 的预检要求的。更详细的信息可以在 mozilla 的网站上查看相关定义:https://developer.mozilla.org/。
要将这段 NGINX 的配置,在 APISIX 中进行实现,我们并不需要一行行的进行配置转换,而是可以基于 APISIX 的 cors 插件进行实现:
"cors": {
"allow_credential": true,
"allow_headers": "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization,appver",
"allow_methods": "GET,POST,PUT,OPTIONS",
"allow_origins": "https://wap.test.com,http://wap.test.com,",
},
针对 OPTIONS 请求返回 204 这部分配置,我们使用了 response-rewrite 插件来实现:
"response-rewrite": {
"status_code": 204,
"vars": [
[ "request_method",
"==",
"OPTIONS"
]
]
}
在 APISIX 中使用 cors 插件和 response-rewrite 插件实现了这段配置之后, 我们可以使用浏览器自带的网络工具进行迁移后的测试验证:
从截图可以看到,针对 Options 返回 204,在响应 Header 中也配置好了 Access-Control-Allow-Origin 等要求的值。
APISIX 和 NGINX 配置对比
这里我们直接对比下 NGINX 和 APISIX 的配置代码:
# NGINX conf
add_header 'Access-Control-Allow-Origin' $corsHost;
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization,appver';
if ($request_method = 'OPTIONS') {
return 204;
}
# APISIX plugins config
"cors": {
"allow_credential": true,
"allow_headers": "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept,Authorization,appver",
"allow_methods": "GET,POST,PUT,OPTIONS",
"allow_origins": "https://wap.test.com,http://wap.test.com,",
},
"response-rewrite": {
"status_code": 204,
"vars": [
[
"request_method",
"==",
"OPTIONS"
]
]
}
NGINX 的配置看起来更加简洁,但对于不熟悉 NGINX 和跨域的人来说,理解其背后的含义可能并不容易。相比之下,APISIX 对不同的业务功能进行了插件封装,使得配置更加模块化,基本上一眼就可以看出其实现的业务功能和背后的含义。
类似的 NGINX 的配置向 APISIX 进行迁移的代码案例我们还有很多,例如在 NGINX 中 websocket 协议需要进行如下配置:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ""Upgrade"";
proxy_http_version 1.1;
而在 APISIX 就进行了封装,非常简单明了:
"enable_websocket": true,
成功迁移后的回顾与展望
自从我们在 2023 年 4 月份首次接触 APISIX,到 7 月份在生产环境成功完成了从 NGINX 到 APISIX 的升级,整个迁移过程取得了令人满意的成果。在迁移初期,由于接手的生产 NGINX 存在各种历史遗留配置,有些甚至不清楚其真正意义,我们曾对 APISIX 的插件能否完全实现我们现有 NGINX 的所有功能感到担心。但最终的结果表明,APISIX 的插件完全胜任这一挑战。
NGINX 向 APISIX 迁移的核心是重新在 APISIX 中实现 NGINX 配置文件,这并不是一行 APISIX 配置对应一行 NGINX 的配置转换。我们需要深入理解相关 NGINX 配置模块背后的含义。在 APISIX 中,往往可以通过插件实现更加优雅的解决方案,例如跨域支持(cors)、WebSocket 等。
在整个升级过程中,我们发现在原有的 NGINX 中存在不少上古配置,其中很多地方甚至是毫无意义的复制粘贴配置。这次升级的过程也是对我们整个南北向网关的一次全面梳理,特别是基于 APISIX 的 plugin_config 等功能,我们在网关配置层面更容易实现模块化的管理和复用。
总体来说,APISIX 完美地解决了我们之前在 NGINX 中遇到的各种痛点,其丰富的插件使我们能够轻松应对客户端提出的各种新需求。在迁移过程中,社区小伙伴的大力帮助也为我们解决了一些故障,对此我们表示衷心的感谢。
作者简介
卞弘智:国内某大型航空公司研发工程师,拥有超过十年的 SRE 经验,工作经历涵盖 DevOps、监控和告警系统、日志处理系统、WAF 和网关等系统基础架构领域,致力于通过优秀的开源软件推动自动化和智能化基础架构平台的演进。