服务公告
Kong:服务发现
发布时间:2026-04-21 19:01
一、前言
搞过微服务的人都知道,最烦的是服务多了以后手动维护upstream——加一台机器要去Kong改配置、删一台机器要去Kong删配置,凌晨三点被报警叫醒改配置。Kong的服务发现功能就是来解决这个问题的,让你的API网关自动感知后端服务实例的增减。
二、操作步骤
步骤1:确认Kong版本支持服务发现
$ kong version
3.4.0# 输出预期
3.4.0Kong从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:集群管理