从 NGINX 迁移到 APISIX
用户从 NGINX 迁移到 APISIX 是因为它的易用性和可扩展性。例如,APISIX:
- 支持配置热加载,无需停机。
- 开箱即用地支持 金丝雀发布、认证 和 可观测性。
- 可以通过 Admin API 或 YAML 配置文件 进行配置。
- 提供可扩展性,允许用户 使用 Lua 和其他编程语言开发自定义插件。
本指南将引导你完成将典型场景的 NGINX 配置迁移到等效 APISIX 配置的过程。
在部署到生产环境之前,请确在沙箱环境中测试迁移后的配置。
配置反向代理
充当代理并将请求转发到上游服务器是 NGINX 和 APISIX 的主要功能。
此示例使用 NGINX 和 APISIX 将对 /anything/ 路径的请求转发到上游 httpbin.org。
要在 NGINX 中代理请求,使用 proxy_pass 指令:
http {
server {
// Annotate 1
listen 80;
// Annotate 2
location /anything/ {
// Annotate 3
proxy_pass http://httpbin.org:80;
}
}
}
❶ 在端口 80 上监听请求。
❷ 匹配以 /anything/ 开头的位置。
❸ 将匹配的请求代理到 httpbin.org。
APISIX 通过 路由 实现相同的配置。
创建一个路由,如下所示:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-anything",
// Annotate 1
"uri": "/anything/*",
"upstream": {
"type": "roundrobin",
"nodes": {
// Annotate 2
"httpbin.org:80": 1
}
}
}'
❶ 匹配所有路径前缀为 /anything/ 的请求。
❷ 将匹配的请求代理到 httpbin.org。
向创建的路由发送请求:
curl -i "http://127.0.0.1:9080/anything/nothing"
你应该看到带有以下内容的 HTTP/1.1 200 OK 响应:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "127.0.0.1",
"User-Agent": "curl/8.4.0",
"X-Amzn-Trace-Id": "Root=1-661fc252-35c621bc2d2b961c6ce98366",
"X-Forwarded-Host": "127.0.0.1"
},
"json": null,
"method": "GET",
"origin": "192.168.289.1, 45.253.168.124",
"url": "http://127.0.0.1/anything/nothing"
}
有关更复杂的路由场景,请参阅 流量管理指南。
配置负载均衡
NGINX 也广泛用作负载均衡器,在多个上游服务器之间分发传入请求。
此示例使用 NGINX 和 APISIX 在两个上游 httpbin.org 和 mock.api7.ai 之间平衡负载,同时保留一个故障转移服务器 192.0.0.1 用于故障情况。
这些上游在 NGINX 配置中的 upstream 块(上下文)中指定:
http {
// Annotate 1
upstream backend {
// Annotate 2
server httpbin.org:443;
// Annotate 2
server mock.api7.ai:443;
// Annotate 3
server 192.0.0.1:443 backup;
}
server {
listen 80;
location / {
proxy_pass https://backend;
}
}
}
❶ 创建一个名为 backend 的上游。
❷ 配置上游节点 httpbin.org 和 mock.api7.ai。
❸ 配置故障转移服务器 192.0.0.1,以便在上述节点发生故障时回退。
APISIX 通过 上游 配置中的 nodes 属性实现相同的配置。
创建一个具有多个上游节点的路由:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-headers",
"uri": "/headers",
"upstream" : {
// Annotate 1
"type": "roundrobin",
"nodes": [
// Annotate 2
{ "host": "httpbin.org", "port": 443, "weight": 3 },
// Annotate 2
{ "host": "mock.api7.ai", "port": 443, "weight": 1 },
// Annotate 3
{ "host": "192.0.0.1", "port": 443, "priority": -1 }
],
"pass_host": "node",
"scheme": "https"
}
}'
❶ 使用加权轮询算法进行负载均衡。有关其他选项,请参阅 负载均衡。
❷ 配置上游节点 httpbin.org 和 mock.api7.ai。
❸ 配置故障转移服务器 192.0.0.1,以便在上述节点发生故障时回退。
向创建的路由发送 50 个请求以验证负载均衡:
resp=$(seq 50 | xargs -I{} curl "http://127.0.0.1:9080/headers" -sL) && \
count_httpbin=$(echo "$resp" | grep "httpbin.org" | wc -l) && \
count_mockapi7=$(echo "$resp" | grep "mock.api7.ai" | wc -l) && \
echo httpbin.org: $count_httpbin, mock.api7.ai: $count_mockapi7
你应该看到类似的响应:
httpbin.org: 49, mock.api7.ai: 1
服务静态文件
NGINX 和 APISIX 可以直接服务静态文件。这通常包括 HTML、CSS、JavaScript、图像、字体和其他无需修改即可提供给客户端的媒体文件。
此示例使用 NGINX 和 APISIX 缓存并代理来自 Web 超文本应用技术工作组 (WHATWG) 公共 GitHub 仓库 的静态文件。
NGINX 支持在 location 块中使用正则表达式来根据文件扩展名匹配文件,如下所示:
http {
// Annotate 1
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m;
server {
listen 80;
// Annotate 2
proxy_cache mycache;
// Annotate 3
location ~* ^/whatwg/(.+\.(jpeg|html))$ {
// Annotate 4
proxy_pass https://raw.githubusercontent.com;
}
}
}
❶ 将缓存内容存储在 /data/nginx/cache 中,并使用 10 MB 的共享内存区域来存储缓存键。
❷ 使用创建的缓存 mycache。
❸ 使用正则表达式匹配前缀为 /whatwg/ 且文件扩展名为 .jpeg 或 .html 的请求。
❹ 将匹配的请求代理到 raw.githubusercontent.com。
APISIX 使用 变量 来匹配路径。然后,为了缓存响应,APISIX 使用 proxy-cache 插件。
创建一个启用 proxy-cache 的路由:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-whatwg",
"uri": "/whatwg/*",
// Annotate 1
"vars": [["uri", "~~", "(.jpeg|.html)$"]],
"plugins": {
// Annotate 2
"proxy-cache": {}
},
"upstream": {
"type": "roundrobin",
"scheme": "https",
"pass_host": "node",
"nodes": {
// Annotate 3
"raw.githubusercontent.com": 1
}
}
}'
❶ 使用 uri 变量匹配以 .jpeg 或 .html 结尾的请求。
❷ 启用 proxy-cache 以缓存响应。
❸ 将匹配的请求代理到 raw.githubusercontent.com。
向创建的路由发送 HTML 文件请求:
curl -i "http://127.0.0.1:9080/whatwg/html/main/404.html"
你应该收到一个 HTTP/1.1 200 OK 响应,并看到以下文件内容:
<!DOCTYPE html>
<script src="/link-fixup.js" defer></script>
<title>404 Not Found</title>
<style>
body.loading div.failed,
body.failed div.loading,
div.failed {
display: none;
}
body.loading div.loading,
body.failed div.failed,
div.loading {
display: block;
}
</style>
<body onload="document.body.className = 'failed'">
<script>
document.body.className = "loading";
</script>
<div class="loading">
<p>Loading...</p>
</div>
<div class="failed">
<h1>Not Found</h1>
<p>The page you are looking for is no longer available at this URL.</p>
<p>
Links to the multipage version of the specification are unfortunately
likely to break over time. You might be able to find what you want from
<a href="/multipage/">the contents page</a>.
</p>
<p>
If you have found a broken link on the WHATWG site itself, please
<a href="https://github.com/whatwg/html/issues/new">file an issue</a>. If
you found a broken link from another site pointing to the WHATWG site,
please let that site know of the problem instead. Thanks!
</p>
</div>
</body>
配置 SSL 终止
NGINX 可以终止来自客户端的 HTTPS 流量,以减轻上游的解密负担。APISIX 也开箱即用地支持此功能。
此示例使用 NGINX 和 APISIX 在通过 HTTP 将请求代理到上游 httpbin.org 之前终止 SSL。
NGINX 使用提供的 SSL 证书设置 SSL 终止:
http {
server {
// Annotate 1
listen 443 ssl;
server_name www.test.com;
// Annotate 2
ssl_certificate /etc/nginx/ssl/website.com/certificate.crt;
// Annotate 3
ssl_certificate_key /etc/nginx/ssl/website.com/private.key;
location /ip {
proxy_pass http://httpbin.org:80;
}
}
}
❶ 在端口 443 上监听 HTTPS 请求。
❷ 配置 SSL 证书路径。
❸ 配置 SSL 证书密钥路径。
APISIX 使用 SSL 证书对象来存储证书和私钥:
curl -i "http://127.0.0.1:9180/apisix/admin/ssls" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-test-com-ssl",
"sni": "www.test.com",
// Annotate 1
"cert": "'"$(cat certificate.crt)"'",
// Annotate 2
"key": "'"$(cat private.key)"'"
}'
❶ 配置 SSL 证书。
❷ 配置 SSL 证书密钥。
请参阅 配置客户端和 APISIX 之间的 HTTPS 以获取有关配置 SSL 的详细指南。
将 HTTP 重定向到 HTTPS
除了终止 HTTPS 流量外,还可以配置 NGINX 将 HTTP 流量重定向到 HTTPS。
NGINX 使用 return 指令通过 301 Moved Permanently 状态代码进行重定向:
http {
server {
listen 80;
server_name www.test.com;
// Annotate 1
return 301 https://$host$request_uri;
}
}
❶ 重定向到请求 URI 的 HTTPS 版本。
APISIX 使用 redirect 插件来实现相同的行为:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-redirect",
"uri": "/*",
"plugins": {
"redirect": {
// Annotate 1
"http_to_https": true,
// Annotate 2
"ret_code": 301
}
}
}'
❶ 将 HTTP 请求重定向到 HTTPS。
❷ 在重定向时返回 301 Moved Permanently 状态代码。
向路由发送 HTTP 请求:
curl -i "http://127.0.0.1:9080/anything"
你应该看到 HTTP/1.1 301 Moved Permanently 响应。
配置 IP 访问控制
使用 NGINX 作为防火墙的一种方法是限制特定 IP 地址对你的服务的访问。这有助于防止未经授权的访问和恶意用户。
此示例使用 NGINX 和 APISIX 仅允许来自 IP 地址 192.168.1.0/24 的请求。
NGINX 使用 allow 指令允许访问 IP 地址,使用 deny 指令拒绝访问,如下所示:
http {
server {
listen 80;
location /anything/ {
// Annotate 1
allow 192.168.1.0/24;
// Annotate 2
deny all;
proxy_pass http://httpbin.org:80;
}
}
}
❶ 允许访问 IP 地址 192.168.1.0/24。
❷ 拒绝所有其他 IP 地址的访问。
APISIX 通过 ip-restriction 插件实现相同的配置。
创建一个启用 ip-restriction 的路由:
curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" -d '
{
"id": "apisix-anything",
"uri": "/anything",
"plugins": {
"ip-restriction": {
// Annotate 1
"whitelist": ["192.168.1.0/24"]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'
❶ 将 IP 地址 192.168.1.0/24 添加到白名单以允许访问。
向创建的路由发送请求:
curl -i "http://127.0.0.1:9080/anything"
如果你的 IP 被允许,你应该收到 HTTP/1.1 200 OK 响应。如果没有,你应该收到 HTTP/1.1 403 Forbidden 响应和以下错误消息:
{"message":"Access denied"}
自定义 APISIX 生成的 NGINX 配置
APISIX 根据 apisix/cli/config.lua 中的配置生成 NGINX 配置文件。要自定义 NGINX 配置,请将代码片段添加到 conf/config.yaml 文件的 nginx_config 字段中。
下面的示例展示了可用的代码片段和示例:
nginx_config:
// Annotate 1
main_configuration_snippet: |
daemon on;
// Annotate 2
http_configuration_snippet: |
server
{
listen 45651;
server_name _;
access_log off;
location /ysec_status {
req_status_show;
allow 127.0.0.1;
deny all;
}
}
chunked_transfer_encoding on;
// Annotate 3
http_server_configuration_snippet: |
set $my "var";
// Annotate 4
http_admin_configuration_snippet: |
log_format admin "$request_time $pipe";
// Annotate 5
http_end_configuration_snippet: |
server_names_hash_bucket_size 128;
// Annotate 6
stream_configuration_snippet: |
tcp_nodelay off;
❶ 将自定义指令添加到 main 上下文(在其他上下文之外)。
❷ 将自定义配置添加到 http 上下文。
❸ 将自定义指令添加到 server 上下文。
❹ 将自定义指令添加到 admin server 上下文。
❺ 将自定义指令添加到 http 上下文的末尾。
❻ 将自定义配置添加到 stream 上下文。
确保正确缩进自定义配置。不正确的缩进可能会导致 APISIX 在生成 NGINX 配置时失败。
常见问题解答和故障排除
HTTP 请求自动重定向到 HTTPS,状态代码为 HTTP/1.1 301 Moved Permanently 或 HTTP/1.1 308 Permanent Redirect
APISIX 不会强制将 301 重定向到 HTTPS,除非如 [上节](#将 HTTP 重定向到 HTTPS) 所示配置了 redirect 插件。
如果你打算在同一个域上同时支持 HTTP 和 HTTPS,则无需配置启用了 http_to_https 的 redirect 插件。