API 网关与服务发现:实现动态路由与智能请求转发的原理揭秘

​ 这是微服务架构中"API 网关 + 服务发现"最核心的协作机制。我在项目中使用的API网关是Kong,服务注册中心是Consul,这里就拿他们讲解。

我们来一步步、用通俗易懂的方式详细讲解这个过程,结合微服务项目场景来说明。

一、目标是什么?

想实现的效果是:

用户访问 /goods/list → 请求被 Kong 接收 → Kong 自动知道这个请求应该转发给 商品服务(goods-srv) → 并且能自动负载均衡到多个 goods-srv 实例上。

而且:

  • 不用手动写死 IP 地址
  • 商品服务扩容/缩容(实例增减)时,Kong 能自动感知
  • 新增一个服务(比如 order-srv),只需注册进 Consul,Kong 就能路由过去

这就叫:动态路由 + 动态服务发现


二、Kong 和 Consul 分别做什么?

组件 角色
Kong API 网关,负责接收所有外部请求,决定"这个请求该转发给谁"
Consul 服务注册中心,记录"每个服务叫什么名字、有哪些实例(IP+端口)、健康吗?"

它们配合起来,就像"快递分拣中心(Kong)"和"公司员工花名册(Consul)"。


三、核心机制:Kong 如何知道服务在哪?------"服务(Service)"的概念

Kong 内部有两个关键抽象:

1. Service(服务)

  • 表示一个后端微服务(如 goods-srv

  • 它不直接写死 IP,而是告诉 Kong:"你要找的商品服务,在 Consul 里叫 mxshop-goods-srv"

  • 配置示例:

    bash 复制代码
    curl -X POST http://kong:8001/services \
      -d "name=goods-service" \
      -d "url=consul://consul:8500/mxshop-goods-srv"
    • name=goods-service:这是 Kong 内部给这个后端服务起的名字。
    • url=consul://...:这是重点!它不是 http://192.168.1.10:8001 这种固定地址,而是指向 Consul 中注册的服务名 mxshop-goods-srv

✅ 所以,Kong 的 "Service" 是一个逻辑概念,它通过 Consul 动态获取真实地址。


2. Route(路由)

  • 表示"什么样的请求应该交给哪个 Service 处理"

  • 通常是基于 URL 路径或 Host 匹配

  • 配置示例:

    bash 复制代码
    curl -X POST http://kong:8001/services/goods-service/routes \
      -d "paths[]=/goods" \
      -d "methods[]=GET" \
      -d "methods[]=POST"
    • 意思是:所有以 /goods 开头的请求(如 /goods/list, /goods/detail),都交给 goods-service 这个 Service 处理。

四、完整请求流转过程(以 /goods/list 为例)

我们来走一遍用户请求的完整路径:

步骤 1️⃣:用户发起请求

arduino 复制代码
GET http://api.example.com/goods/list

步骤 2️⃣:Kong 接收到请求

Kong 检查所有 Route,发现 /goods 路径匹配 goods-service 这个 Service。

步骤 3️⃣:Kong 查询 Consul 获取真实地址

Kong 看到 goods-serviceurl=consul://.../mxshop-goods-srv,于是:

  • 向 Consul 发起查询:"mxshop-goods-srv" 这个服务现在有哪些健康的实例?"

  • Consul 返回:

    css 复制代码
    [  {"Address": "192.168.1.10", "Port": 50051},  {"Address": "192.168.1.11", "Port": 50051},  {"Address": "192.168.1.12", "Port": 50051}]

步骤 4️⃣:Kong 选择一个实例并转发

Kong 从这三个地址中按负载均衡策略(如轮询)选一个,比如 192.168.1.11:50051,然后把请求转发过去:

arduino 复制代码
GET http://192.168.1.11:50051/goods/list

✅ 最终结果

用户无感知地访问到了商品服务,而 Kong 完全不知道具体 IP,它只认"服务名"。


五、动态性体现在哪里?------服务扩缩容自动适配

假设你现在把商品服务从 3 个实例扩容到 5 个:

  1. 新的 goods-srv 实例启动 → 自动向 Consul 注册自己(服务名仍是 mxshop-goods-srv
  2. Consul 更新服务列表,新增两个实例
  3. Kong 通过 Consul 插件(定期轮询或监听事件)自动获取最新实例列表
  4. 下次请求来时,Kong 就可能把流量分发到新实例上

👉 整个过程不需要你手动改 Kong 配置!


六、新增一个服务(如 order-srv)怎么办?

  1. order-srv 启动 → 向 Consul 注册为 mxshop-order-srv

  2. 在 Kong 中创建新 Service:

    bash 复制代码
    curl -X POST http://kong:8001/services \
      -d "name=order-service" \
      -d "url=consul://consul:8500/mxshop-order-srv"
  3. 创建对应路由:

    bash 复制代码
    curl -X POST http://kong:8001/services/order-service/routes \
      -d "paths[]=/order"
  4. 用户访问 /order/create → 自动转发到 order-srv

✅ 只要服务在 Consul 注册了,Kong 就能通过服务名找到它。


七、总结:Kong + Consul 动态路由的本质

层级 配置项 作用 是否需要手动配置
1. 路由层 Route (/goods) 匹配 URL 路径 ✅ 需要(一次)
2. 服务层 Service (goods-service) 指向 Consul 中的服务名 ✅ 需要(一次)
3. 发现层 Consul (mxshop-goods-srv) 存储真实 IP 列表 ❌ 自动注册/更新

优势总结:

  • 解耦:Kong 不关心 IP,只关心"服务名"
  • 动态:实例增减,自动感知
  • 可维护:新增服务只需加 Route + Service,无需改代码
  • 高可用:结合健康检查,自动剔除不健康实例

Kong 的 Consul 插件是如何工作的?

Kong 通过内置的 consul 协议支持,或使用 kong-plugin-consul-discovery 插件,实现以下功能:

  • 定期向 Consul 查询服务实例列表(默认每 5~10 秒)
  • 支持长轮询(Watch)模式,变更更实时
  • 支持健康检查过滤,只返回健康实例
  • 支持负载均衡(Kong 内置轮询、哈希等策略)

你现在完全可以这样理解:

API网关 是"指挥官",它不亲自打仗(处理业务),而是根据"花名册"(服务注册中心Consul)上的名单,把任务(请求)分配给正确的"士兵"(微服务实例)。名单变了,指挥官自动调整,无需重新训练。

这就是项目中实现的"动态路由"的精髓!

相关推荐
怒码ing5 小时前
分布式事务----spring操作多个数据库,事务以及事务回滚还有用吗
数据库·分布式·spring
你我约定有三5 小时前
分布式微服务--Nacos作为配置中心(一)
分布式·微服务·架构
小熊h5 小时前
【分布式的个人博客部署】
linux·运维·服务器·分布式
你我约定有三5 小时前
分布式微服务--Nacos作为配置中心(补)关于bosststrap.yml与@RefreshScope
java·分布式·spring cloud·微服务·架构
宸津-代码粉碎机7 小时前
LLM 模型部署难题的技术突破:从轻量化到分布式推理的全栈解决方案
java·大数据·人工智能·分布式·python
老友@11 小时前
RabbitMQ 延时队列插件安装与使用详解(基于 Delayed Message Plugin)
运维·分布式·docker·rabbitmq·延时队列
陈鋆14 小时前
分布式ID方案(标记)
分布式
bing_15815 小时前
如何将 Redis 监控集成到微服务整体的监控体系中( 如 Prometheus + Grafana)
redis·微服务·prometheus
非极限码农16 小时前
基于Deepseek的语言润色助手API实现与部署指南
python·微服务·自然语言处理