4. Kong 基础配置:Service、Route、Upstream 的创建与管理

好,我们直接进入正题。Kong 网关的核心抽象其实就三个东西:Service、Route 和 Upstream。很多人一开始会被这些概念绕晕,觉得不过是换个名字的负载均衡。我刚开始接触时也这么想,直到在生产环境踩了坑……嗯,咱们今天把这几个东西彻底捋清楚。

4.1 Service:你后端服务的“门牌号”

Service 就是后端业务服务的抽象。举个例子,你有一个用户服务跑在 10.0.1.5:8080,Kong 把它的地址、协议、超时等信息注册成一个 Service。客户端不需要知道这个 IP 和端口,只需要知道 Service 的名字。

核心字段

  • name:唯一标识,比如 user-service
  • host:目标主机地址(可以是域名或 IP)
  • port:目标端口
  • protocol:http / https / grpc 等
  • connect_timeout、read_timeout、write_timeout:超时控制

创建 Service 有两种方式:Admin API 或声明式配置文件。我个人更推荐先用 API 做快速验证,再固化到声明式配置里。

# 使用 Admin API 创建一个 Service
curl -X POST http://localhost:8001/services \
  -H "Content-Type: application/json" \
  -d '{
    "name": "user-service",
    "host": "10.0.1.5",
    "port": 8080,
    "protocol": "http",
    "connect_timeout": 5000,
    "read_timeout": 30000
  }'

一个小技巧:如果后端服务是 HTTPS,记得把 protocol 设为 https,Kong 会自动处理 TLS 握手。我曾因为忘记改协议,导致客户端一直报连接被重置,排查了半小时才发现是协议不匹配。

4.2 Route:流量进来的“规则引擎”

Service 定义好了,但客户端怎么找到它?这时就需要 Route。Route 决定了哪些请求匹配到哪个 Service。说白了,它就是一组转发规则:匹配路径、方法、Host、Header 等等。

一个 Service 可以挂载多个 Route,一个 Route 只能属于一个 Service。这种设计挺合理的——你想像一下,一个用户服务可能同时提供 RESTful API 和 WebSocket 连接,用不同 Route 区分就好。

Route 关键匹配条件

字段 说明 示例
paths 路径前缀或精确路径 ["/api/users"]
methods HTTP 方法 ["GET", "POST"]
hosts 请求的 Host 头 ["api.example.com"]
headers 自定义 Header 匹配 {"X-Version": "v2"}
protocols 协议类型 ["http", "https"]
# 为刚才的 user-service 创建 Route
curl -X POST http://localhost:8001/routes \
  -H "Content-Type: application/json" \
  -d '{
    "name": "user-api-route",
    "service": {
      "name": "user-service"
    },
    "paths": ["/api/users"],
    "methods": ["GET", "POST"],
    "strip_path": true
  }'

注意 strip_path 这个坑:strip_path 默认是 true,意思是从请求路径里把匹配的前缀去掉再转发给后端。比如请求 /api/users/info,Kong 会转发给后端 /info。如果后端不期望路径被裁剪,记得设为 false。我曾经因为这个导致上游收到路径不对,接口返回 404,折腾了半天。

4.3 Upstream:负载均衡与健康检查

生产环境里,后端服务往往不止一个实例。Upstream 就是用来描述一组后端节点,并让 Kong 在它们之间做负载均衡。它还可以配置健康检查,自动踢掉挂掉的节点。

我建议在服务实例数量超过 2 个时,一定要配 Upstream 而不是直接指向单个 IP。否则某个节点挂了,你的服务就全瘫了。

Upstream 的主要参数

  • name:Upstream 唯一名称,比如 user-upstream
  • algorithm:均衡算法,支持 round-robin、consistent-hashing、least-connections 等
  • healthchecks:主动/被动健康检查配置
  • slots:节点槽位数(默认 10000,一般不用改)
# 创建一个 Upstream
curl -X POST http://localhost:8001/upstreams \
  -H "Content-Type: application/json" \
  -d '{
    "name": "user-upstream",
    "algorithm": "round-robin",
    "healthchecks": {
      "active": {
        "type": "http",
        "http_path": "/health",
        "interval": 10,
        "healthy": {
          "interval": 10,
          "successes": 2
        },
        "unhealthy": {
          "interval": 5,
          "http_failures": 3
        }
      }
    }
  }'

# 添加目标节点
curl -X POST http://localhost:8001/upstreams/user-upstream/targets \
  -H "Content-Type: application/json" \
  -d '{"target": "10.0.1.5:8080", "weight": 100}'

curl -X POST http://localhost:8001/upstreams/user-upstream/targets \
  -H "Content-Type: application/json" \
  -d '{"target": "10.0.1.6:8080", "weight": 100}'

健康检查的间隔别设太短:我见过有人设成 1 秒一次,结果后端被请求刷爆。推荐生产环境主动检查间隔设为 10~30 秒,被动检查(根据代理请求判定)设 60 秒恢复时间。

4.4 三者如何串联?一张图看懂

你一定好奇这些概念怎么配合工作。来,我画张图把流程串起来:客户端请求发到 Kong,Kong 根据 Route 匹配规则找到 Service,Service 关联到 Upstream,Upstream 再从节点列表里选一个健康的实例转发。

Kong 请求流转逻辑 客户端 Kong Gateway (匹配 Route) Service (路由到 Upstream) Upstream (负载均衡 + 健康检查) 实例 10.0.1.5:8080 实例 10.0.1.6:8080 简要说明: 1. 客户端请求到达 Kong,Kong 根据 Route 的 paths/methods/hosts 等条件匹配 2. 匹配到的 Route 关联到一个 Service,Service 记录后端服务的逻辑名称 3. Service 可以指向固定地址,更推荐指向 Upstream(实现负载均衡) 4. Upstream 管理一组目标节点,支持健康检查和多种均衡算法 5. 最终请求被转发到健康节点上,完成一次代理

4.5 实战:一个完整的创建流程

我们用手上的 API 串起来做一个完整的例子:先建 Upstream 并加入两个后端节点,再建 Service 指向这个 Upstream,最后创建 Route 把流量引进来。

# Step 1: 创建 Upstream
curl -s -X POST http://localhost:8001/upstreams \
  -d '{"name": "user-upstream", "algorithm": "least-connections"}'

curl -s -X POST http://localhost:8001/upstreams/user-upstream/targets \
  -d '{"target": "10.0.1.5:8080", "weight": 50}'
curl -s -X POST http://localhost:8001/upstreams/user-upstream/targets \
  -d '{"target": "10.0.1.6:8080", "weight": 50}'

# Step 2: 创建 Service,指向 Upstream
curl -s -X POST http://localhost:8001/services \
  -d '{
    "name": "user-service",
    "host": "user-upstream",
    "port": 80,
    "protocol": "http"
  }'

# 注意:host 填的是 Upstream 名字,不是实例 IP
# Kong 内部会自动解析为 Upstream 的负载均衡节点

# Step 3: 创建 Route
curl -s -X POST http://localhost:8001/routes \
  -d '{
    "name": "user-route",
    "service": {"name": "user-service"},
    "paths": ["/api/users"],
    "strip_path": false,
    "methods": ["GET", "POST"]
  }'

验证是否生效:用 curl 请求 http://localhost:8000/api/users,看响应是否来自后端节点。也可以查看 /routes、/services、/upstreams 的列表接口确认。

4.6 避坑指南

坑 现象 解决方法
Service 的 host 写成了实例 IP 而不是 Upstream 名 负载均衡不生效,流量只转发到一个节点 检查 Service 的 host 字段,应填 Upstream 的 name
Route 的 strip_path 设置错误 后端收到路径与实际不符,404 根据后端期望的路径决定是否裁剪
Upstream 目标节点权重为 0 或超出范围 节点被自动忽略,流量倾斜 权重范围 0~65535,0 表示不接受新连接
健康检查路径配置不对 节点被误判为不健康 确保 http_path 是后端真实的健康端点

特别提醒:Kong 的 Upstream 目标节点更新不是实时的?其实更改后 Kong 会在几秒内生效,无需重启。但如果你改了 Upstream 的算法,建议重新请求一下路由刷新缓存。我曾经改完算法发现流量没变,后来查到是 Kong 的缓存机制,加个空请求就好了。

4.7 管理建议与总结

说真的,Service、Route、Upstream 这三个概念掌握好了,Kong 的 80% 的配置工作你就拿下了。个人习惯是先画一个流量图(就像我上面那张 SVG),明确每个路由要走到哪个后端集群,然后再动手建资源。

还有个小建议:生产环境用声明式配置(比如 decK 或 YAML),不要全靠 Admin API 手敲,否则迁移或回滚时会很痛苦。我早期就是在测试环境用 API 堆了大几十个路由,后来要导出到生产,一个个 curl 调接口,差点奔溃。

本章的内容就这些。记住——Service 是抽象服务,Route 是匹配规则,Upstream 是后端节点池。三者缺一不可,配合起来才能让 Kong 稳定地处理流量。