Apache APISIX 动态 API 网关
yaml version: '3'
services: apisix: image: apache/apisix:3.9.0-debian restart: always volumes: - ./apisix_conf/config.yaml:/usr/local/apisix/conf/config.yaml:ro ports: - "9080:9080" # 数据面代理端口 - "9180:9180" # Admin API 端口 environment: - APISIX_STAND_ALONE=false depends_on: - etcd networks: apisix:
etcd: image: bitnami/etcd:3.5 restart: always environment: - ALLOW_NONE_AUTHENTICATION=yes - ETCD_ADVERTISE_CLIENT_URLS=http://0.0.0.0:2379 ports: - "2379:2379" networks: apisix:
networks: apisix: driver: bridge
### 2. 准备 APISIX 配置文件
在相同目录下创建 `apisix_conf/config.yaml`,写入最小配置:
```yaml
apisix:
node_listen: 9080
enable_admin: true
enable_admin_cors: true
admin_key:
- name: admin
key: edd1c9f034335f136f87ad84b625c8f1
role: admin
etcd:
host:
- "http://etcd:2379"
admin_key用于调用 Admin API,生产环境请务必修改默认密钥。
3. 启动服务
在 docker-compose.yml 所在目录执行:
docker-compose up -d
等待镜像拉取完成后,检查容器状态:
docker-compose ps
如果 apisix 和 etcd 均处于 Up 状态,说明启动成功。
动态路由管理
路由(Route)是 APISIX 中的核心概念,它定义了客户端请求到上游服务的匹配规则。
创建路由(实时生效)
使用 Admin API 创建一条路由,将 /hello 请求转发到 httpbin.org:
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PUT -d '
{
"uri": "/hello",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
动态效果:命令执行后路由立即生效,无需任何重启操作。
测试路由:
curl http://127.0.0.1:9080/hello/get
返回 httpbin.org 的响应数据,说明代理成功。
修改路由配置
要修改路由的匹配路径或上游节点,只需再次 PUT 相同 ID:
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PUT -d '
{
"uri": "/v1/hello",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1,
"mock.api7.ai:80": 1
}
}
}'
配置修改即时生效,旧连接会平滑迁移到新规则。
删除路由
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X DELETE
同样无需重启,路由立即移除。
上游与负载均衡
上游(Upstream)是一组后端服务节点的抽象,支持多种负载均衡算法。
创建独立上游
可以将上游与路由分离管理,这样当后端节点变化时,只需更新上游配置即可。
curl -i http://127.0.0.1:9180/apisix/admin/upstreams/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PUT -d '
{
"type": "chash",
"key": "remote_addr",
"nodes": {
"httpbin.org:80": 1,
"mock.api7.ai:80": 2
}
}'
type: 负载均衡算法,此处chash为一致性哈希,key指定哈希依据(客户端 IP)。nodes中的数字为权重。
路由引用上游
修改路由,指向上游 ID:
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PUT -d '
{
"uri": "/hello",
"upstream_id": 1
}'
这样,当上游节点扩容或缩容时,只需更新 Upstream,所有关联路由自动生效。
插件系统
APISIX 拥有丰富的插件,并且可以动态地为单个路由、服务或全局启用插件。
为路由启用限流插件
假设我们要对 /hello 路由进行访问频率限制:每秒最多 2 次请求。
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PATCH -d '
{
"plugins": {
"limit-req": {
"rate": 2,
"burst": 0,
"rejected_code": 429,
"key": "remote_addr"
}
}
}'
动态效果:插件立即启用,频繁访问会收到 429 Too Many Requests。
动态禁用插件
只需将插件配置置空即可关闭该功能:
curl -i http://127.0.0.1:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PATCH -d '
{
"plugins": {
"limit-req": {}
}
}'
插件配置的即时修改
直接更新插件参数,比如将限流速率改为每秒 10 次:
curl ... -X PATCH -d '{"plugins":{"limit-req":{"rate":10}}}'
动态配置更新机制
APISIX 将所有配置(路由、上游、插件等)存储在 etcd 中。当通过 Admin API 修改配置时:
- Admin API 将变更写入 etcd。
- 各个 APISIX 数据面实例通过 watch 机制实时感知 etcd 中的变化。
- 数据面在内存中重建路由树、加载新插件,旧配置被优雅替换。
整个过程在毫秒级完成,完全不中断流量。这也就是为什么 APISIX 被称为“动态 API 网关”。
综合示例:创建动态路由并启用 JWT 鉴权
接下来,我们实现一个完整的常用场景:为后端 API 添加 JWT 鉴权,并且可以随时调整 JWT 密钥或关闭鉴权。
1. 创建消费者(Consumer)
消费者代表调用方,可以携带认证凭证。
curl -i http://127.0.0.1:9180/apisix/admin/consumers \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PUT -d '
{
"username": "user1",
"plugins": {
"jwt-auth": {
"key": "user-key",
"secret": "my-secret-123"
}
}
}'
2. 创建路由并启用 JWT 插件
curl -i http://127.0.0.1:9180/apisix/admin/routes/2 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PUT -d '
{
"uri": "/api/*",
"plugins": {
"jwt-auth": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
3. 测试鉴权
无 Token 访问会被拒绝:
curl -i http://127.0.0.1:9080/api/get
# 返回 401 Unauthorized
生成 JWT Token(可使用在线工具或 APISIX 提供的 Sign 接口),带上 Token 后即可正常访问。
4. 动态调整鉴权策略
如果临时需要关闭该路由的 JWT 校验(比如调试期间),可以直接禁用插件:
curl -i http://127.0.0.1:9180/apisix/admin/routes/2 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-X PATCH -d '
{
"plugins": {
"jwt-auth": null
}
}'