Kong 网关是当前最主流的开源 API 网关之一,它把「反向代理 + 插件化流量治理」合并到同一个入口,让后端的订单、用户、支付等服务在对外暴露时拥有统一的鉴权、限流与可观测能力。本文用最小可行的部署一步一步带你把 Kong 网关跑起来,并讲清它和 Nginx 反向代理的取舍边界。
一、为什么需要 API 网关
当后端从单体拆成十几个微服务后,每个服务都有自己的地址、端口和鉴权方式。客户端如果直连,会面临跨域、证书、限流四处散落的问题。API 网关把这些横切关注点收敛到一个入口:外部只认网关的 8000 端口,网关再按路由把请求转发到对应服务,并统一施加限流、鉴权、日志等策略。
Kong 网关的特别之处在于「插件化」:治理逻辑不是写死在配置文件里,而是以插件形式挂载到服务、路由或消费者上,增删一个能力就是一次 API 调用,无需改 Nginx 的 conf 再 reload。
二、Kong 架构与核心概念
动手前先厘清四个对象,它们之间是逐级包含关系:
- Service(服务):代表一个上游 API 的抽象,本质是一个 host + 端口 + 路径。
- Route(路由):决定什么外部请求(路径、域名、方法)映射到哪个 Service。
- Upstream / Target(上游与节点):Service 背后可以挂一组 Target,实现负载均衡与健康检查。
- Plugin(插件):限流、key-auth、cors、jwt 等治理能力,可作用于全局、Service、Route 或 Consumer。
Kong 有两条端口:8000 是代理端口(对外收流量),8001 是 Admin API 端口(对内管配置,切勿暴露到公网)。
三、快速起步:用 Docker Compose 部署
生产环境推荐 DB 模式(Kong + PostgreSQL),便于插件配置持久化。下面是一份最小可用的编排文件:
version: "3.8"
services:
kong-db:
image: postgres:15
environment:
POSTGRES_DB: kong
POSTGRES_USER: kong
POSTGRES_PASSWORD: kongpw
healthcheck:
test: ["CMD", "pg_isready", "-U", "kong"]
interval: 5s
timeout: 5s
retries: 10
kong:
image: kong:3.6
depends_on:
kong-db:
condition: service_healthy
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-db
KONG_PG_USER: kong
KONG_PG_PASSWORD: kongpw
KONG_PG_DATABASE: kong
KONG_ADMIN_LISTEN: 0.0.0.0:8001
KONG_PROXY_LISTEN: 0.0.0.0:8000
ports:
- "8000:8000"
- "8001:8001"
首次启动前必须先初始化数据库schema,用一次性容器执行迁移:
docker compose run --rm kong kong migrations bootstrap
docker compose up -d
验证网关是否就绪:
curl -i http://localhost:8001/
返回 200 且带 server: kong/3.6 头即可。这种容器化部署方式与我们在Docker 多容器编排中讲的网络模型完全一致。
四、声明第一个 Service 与 Route
假设后端有一个订单服务跑在 http://orders.internal:8080,我们通过 Admin API 把它登记进 Kong:
curl -i -X POST http://localhost:8001/services \
--data name=order-service \
--data url=http://orders.internal:8080
再为它挂一条路由,让外部 /api/orders 开头的请求进入该服务:
curl -i -X POST http://localhost:8001/services/order-service/routes \
--data name=order-route \
--data 'paths[]=/api/orders' \
--data strip_path=false
此时访问网关代理端口即可转发到后端:
curl -i http://localhost:8000/api/orders/123
这正是Nginx 反向代理能做的转发,但 Kong 把映射关系变成了可 API 化管理的资源。
五、负载均衡:Upstream 与 Target
当订单服务横向扩成两个实例,不需要改路由,只需在 Upstream 下挂 Target:
curl -X POST http://localhost:8001/upstreams --data name=order-upstream
curl -X POST http://localhost:8001/upstreams/order-upstream/targets \
--data target=10.0.0.11:8080
curl -X POST http://localhost:8001/upstreams/order-upstream/targets \
--data target=10.0.0.12:8080
然后把 Service 的 host 指向 Upstream 名(order-upstream),Kong 会自动轮询两个节点并剔除不健康实例。在 Kubernetes 环境里,Upstream 的概念与 Service 的 Endpoint 异曲同工。
六、插件化流量治理
Kong 的真正价值在插件。下面给订单服务加上「每分钟 100 次」限流(用 redis 做集群共享计数):
curl -X POST http://localhost:8001/services/order-service/plugins \
--data name=rate-limiting \
--data config.minute=100 \
--data config.policy=redis \
--data config.redis_host=redis.internal
再叠加 key-auth,先建消费者,再发密钥:
curl -X POST http://localhost:8001/consumers --data username=mobile-app
curl -X POST http://localhost:8001/consumers/mobile-app/key-auth \
--data key=APP_SECRET_KEY
curl -X POST http://localhost:8001/services/order-service/plugins \
--data name=key-auth
之后客户端必须带 key 才能访问:
curl -i http://localhost:8000/api/orders/123 \
-H "apikey: APP_SECRET_KEY"
七、Kong 与 Nginx / Caddy 的取舍
三者都能做反向代理,但定位不同,选型时看这张对照表:
| 维度 | Kong 网关 | Nginx | Caddy |
|---|---|---|---|
| 核心定位 | API 网关 | 通用反向代理 | 自动 HTTPS 轻量代理 |
| 流量治理 | 插件化(限流/鉴权/可观测) | 靠 Lua/conf 硬编码 | 基础中间件 |
| 配置方式 | Admin API / 声明式 kong.yml | 静态 conf | Caddyfile |
| 最佳场景 | 微服务统一出入口 | 静态站/通用转发 | 小站自动证书 |
一句话结论:单站或静态转发用 Nginx/Caddy 足够;一旦要治理一批 API,Kong 的插件体系能省下大量重复轮子。
八、插件如何组合:CORS 与可观测性
限流和鉴权只是起点。真实网关往往需要同时开放跨域、采集指标。插件之间是按资源叠加的,互不冲突:给订单服务再挂一个 cors 插件,前端即可跨域调用;挂 prometheus 插件后,Kong 会在 /metrics 暴露请求计数、延迟分布,直接喂给 Docker 编排里的监控栈。
curl -X POST http://localhost:8001/services/order-service/plugins \
--data name=cors \
--data config.origins=https://app.example.com \
--data config.methods=GET,POST
curl -X POST http://localhost:8001/services/order-service/plugins \
--data name=prometheus
这种「声明一个能力就多挂一个插件」的模式,是 Kong 相比在 Nginx 里手写 Lua 的最大爽点:治理能力的增删都是幂等的 API 操作,可以写进 CI 做自动化校验,而不是靠运维手动改 conf 再 reload。
九、声明式配置与 GitOps
用 Admin API 一条条 curl 适合调试,生产更推荐声明式:把配置写成 kong.yml,用 decK 工具同步到网关,纳入 Git 版本管理。
_format_version: "3.0"
services:
- name: order-service
url: http://orders.internal:8080
routes:
- name: order-route
paths:
- /api/orders
plugins:
- name: rate-limiting
config:
minute: 100
- name: key-auth
执行 deck sync 即可让网关状态与文件一致,回滚也只需 git revert,比手工改 Admin 状态安全得多。
常见故障排查
上线后最常遇到的两类问题:一是请求返回 503 Service Unavailable,多半是 Service 的 url 指向的后端不可达或 Upstream 的 Target 健康检查失败,先用 curl -i http://localhost:8001/upstreams/order-upstream/health 看节点状态;二是插件不生效,通常是插件的作用域(全局 / Service / Route / Consumer)挂错了对象,用 GET /services/order-service/plugins 核对挂载点。记住 Admin API 永远先查状态再改配置,不要凭记忆硬改。
十、生产实践清单
- Admin API 绝不公网暴露:用防火墙或单独网络隔离 8001 端口。
- 限流策略放 redis:多节点部署时,本地计数会导致每个网关节点各限一次。
- 用 decK 管理配置:避免「谁在 Admin 上随手加了个插件」导致环境漂移。
- Upstream 开启主动健康检查:自动摘掉挂掉的 Target,减少 502。
- 插件粒度从 Service 入手:通用策略挂 Service,特殊策略再下沉到 Route。
十一、总结
Kong 网关把「转发」升级为「治理」:Service/Route 定义流量地图,Upstream 负责均衡,Plugin 负责把限流、鉴权、可观测等横切能力即插即用。它与 Nginx 反向代理并不互斥——Nginx 做底层四七层转发,Kong 坐在更上层做 API 语义治理,是很多中大型后端的标配组合。从本文的 Docker Compose 起步,再迁移到 decK 声明式管理,你就能拥有一条可版本化、可回滚的 API 网关流水线。当下次业务方说「再加一个限流」时,你只需要一次 API 调用,而不是一次停服发版。




