服务公告

服务公告 > 综合新闻 > Kong:服务发现

Kong:服务发现

发布时间:2026-04-21 19:01

一、前言

搞过微服务的人都知道,最烦的是服务多了以后手动维护upstream——加一台机器要去Kong改配置、删一台机器要去Kong删配置,凌晨三点被报警叫醒改配置。Kong的服务发现功能就是来解决这个问题的,让你的API网关自动感知后端服务实例的增减。

二、操作步骤

步骤1:确认Kong版本支持服务发现

$ kong version 3.4.0
# 输出预期 3.4.0

Kong从1.3版本开始支持服务发现,当前主流版本都带这个功能。如果是老版本,先升级。

步骤2:安装配置Consul作为服务发现后端

# CentOS/RHEL 安装Consul $ sudo yum install -y consul # Ubuntu 安装Consul $ sudo apt install -y consul
# 输出预期(CentOS) Installed: consul-1.15.0-1.el7.x86_64
# 输出预期(Ubuntu) consul is already the newest version (1.15.0).
$ consul agent -server -bootstrap-expect=1 -data-dir=/tmp/consul -node=consul-server-1 -bind=127.0.0.1 -client=127.0.0.1 -ui=true
# 输出预期 ==> Starting Consul agent... ==> Consul agent running! ==> Node name: consul-server-1 ==> Datacenter: dc1 ==> Server: true (bootstrap: true) ==> Listen Address: 127.0.0.1

步骤3:在Consul注册测试服务

$ curl -X PUT http://127.0.0.1:8500/v1/catalog/register -d '{ "Node": "user-service-1", "Address": "192.168.1.101", "Service": { "ID": "user-service-1", "Service": "user-service", "Port": 8080 } }'
# 输出预期 true
$ curl -X PUT http://127.0.0.1:8500/v1/catalog/register -d '{ "Node": "user-service-2", "Address": "192.168.1.102", "Service": { "ID": "user-service-2", "Service": "user-service", "Port": 8080 } }'
# 输出预期 true
$ curl -s http://127.0.0.1:8500/v1/catalog/service/user-service
# 输出预期 [ { "ID": "user-service-1", "ServiceName": "user-service", "ServiceAddress": "192.168.1.101", "ServicePort": 8080 }, { "ID": "user-service-2", "ServiceAddress": "192.168.1.102", "ServicePort": 8080 } ]

步骤4:配置Kong服务发现插件

$ cat /etc/kong/kong.conf | grep -E "^(dns_|registry)"
# 输出预期(需要确认的配置项) dns_resolver = 10.0.0.2:53 registry_sync_rate = 5
# 在kong.yml中配置服务发现 $ cat /etc/kong/kong.yml
# 输出预期 _format_version: "3.0" services: - name: user-service-sd url: http://user-service:8080/api routes: - name: user-route paths: - /api/users plugins: - name: consul-service-discovery config: datacenter: dc1 host: 127.0.0.1 port: 8500 service_name: user-service refresh_interval: 5 tags: - production weights: - weight: 50 target: user-service-1 - weight: 50 target: user-service-2

步骤5:验证服务发现生效

$ kong config parse /etc/kong/kong.yml
# 输出预期 Successfully parsed configuration
$ curl -i http://localhost:8001/services/user-service-sd
# 输出预期 HTTP/1.1 200 OK { "name": "user-service-sd", "url": "http://user-service:8080/api", "routes": [...], "plugins": [...] }
$ curl http://localhost:8001/upstreams/user-service-sd/targets
# 输出预期 { "data": [ { "created_at": 1712304000, "target": "192.168.1.101:8080", "weight": 50, "upstream": { "id": "uuid-xxx" } }, { "created_at": 1712304001, "target": "192.168.1.102:8080", "weight": 50, "upstream": {...} } ], "total": 2 }

可以看到Kong自动从Consul同步了服务实例,并创建了upstream的targets。

步骤6:模拟服务实例变更

# 新增第三个实例 $ curl -X PUT http://127.0.0.1:8500/v1/catalog/register -d '{ "Node": "user-service-3", "Address": "192.168.1.103", "Service": { "ID": "user-service-3", "Service": "user-service", "Port": 8080 } }'
# 输出预期 true
# 等待5秒(refresh_interval配置值),然后检查 $ sleep 6 && curl http://localhost:8001/upstreams/user-service-sd/targets
# 输出预期 { "data": [ { "target": "192.168.1.101:8080", "weight": 50 }, { "target": "192.168.1.102:8080", "weight": 50 }, { "target": "192.168.1.103:8080", "weight": 50 } ], "total": 3 }
# 下线一个实例 $ curl -X PUT http://127.0.0.1:8500/v1/catalog/deregister -d '{ "Node": "user-service-2", "ServiceID": "user-service-2" }'
# 输出预期 true
$ sleep 6 && curl http://localhost:8001/upstreams/user-service-sd/targets
# 输出预期 { "data": [ { "target": "192.168.1.101:8080", "weight": 50 }, { "target": "192.168.1.103:8080", "weight": 50 } ], "total": 2 }

Kong自动感知到了服务的增减,不需要手动改配置。

步骤7:配置健康检查确保可用性

$ curl -X PATCH http://localhost:8001/upstreams/user-service-sd -H "Content-Type: application/json" -d '{ "healthchecks": { "active": { "type": "https", "http_path": "/health", "timeout": 5, "concurrency": 10, "healthy": { "interval": 5, "successes": 2 }, "unhealthy": { "interval": 5, "http_failures": 3 } }, "passive": { "type": "http", "healthy": { "successes": 3 }, "unhealthy": { "http_failures": 3 } } } }'
# 输出预期 { "name": "user-service-sd", "healthchecks": { "active": {...}, "passive": {...} } }

三、常见问题FAQ

Q1:服务发现和静态配置upstream比,性能有没有损失?

A:说实话,有一点。Kong默认每5秒去服务发现后端同步一次,这个间隔会影响实例变更的感知速度。但实际生产中,5秒的延迟对于绝大多数场景完全能接受。如果你要毫秒级响应,那就用DNS-Based的服务发现配合Kong的dns_resolver,也能达到秒级感知。别迷信什么实时同步,分布式系统里强实时没意义。

Q2:Consul挂了怎么办?Kong会自动fallback到缓存吗?

A:会,Kong会缓存服务发现的结果,默认缓存时间是300秒。Consul恢复后会自动重新同步。但我建议你至少部署3个Consul节点组成集群,别搞单机。生产环境玩单机consul挂了就是灾难,到时候背锅的是你自己。还有个坑——Kong重启后会清空缓存,所以首次启动时upstream可能是空的。

Q3:能不能同时用服务发现和静态配置?某些实例我想固定IP不参与自动发现。

A:可以。先通过服务发现创建upstream,然后用静态target添加固定实例。但注意权重配置——动态发现的target默认权重50,静态添加的默认也是50,你可能需要手动调整权重比例。另外静态配置有个恶心的地方:Kong管理界面显示的是合并后的targets,看不出来哪个是动态哪个是静态,得用API查created_at字段判断。

Q4:多机房部署怎么搞?服务发现后端在不同机房。

A:这是个大坑。Consul支持跨机房复制,但配置比较复杂。我见过几种方案:1)每个机房部署独立的Kong集群,服务发现后端只管本地实例,通过DNS做跨机房路由;2)用Consul的WAN Gossip实现跨机房同步,但延迟高;3)用服务网格(Istio/Kuma)替代Kong的服务发现,这是更现代的方案。建议如果业务规模大,直接上服务网格,别在API网关上死磕。

四、总结

核心要点:

  • Kong服务发现解决了手动维护upstream的痛苦,支持Consul、etcd等主流后端
  • 配置很简单,在kong.yml里声明service_name和后端地址即可
  • 服务变更通过refresh_interval控制同步间隔,默认5秒够用
  • 健康检查是必须的,配合服务发现才能实现真正的自动化
  • Consul高可用是关键,生产环境至少3节点集群

延伸阅读:

  • Kong官方文档:Service Discovery
  • Consul官方文档:Service Registration
  • Kong Health Check API:/upstreams/{upstream}/health
  • 服务网格对比:Istio vs Kuma vs Consul Connect

最后说一句:服务发现是好东西,但别为了用而用。如果你的服务实例少于10个,手动维护upstream可能还更简单清晰。上了服务发现,你就多了一个依赖组件,出了问题排查链路更长。技术选型要看业务规模,不是越复杂越好。

上一篇: WAF:性能优化

下一篇: Rancher:集群管理