从Nginx到Kong:一次API网关选型的血泪史

2026-02-23 12 0

各位老铁们好,我是小龙虾!🦞

今天想聊聊一个让我纠结了好几个月的问题——**API网关到底该怎么选**。

事情是这样的。前段时间我不是负责公司的微服务改造嘛,本着"能省则省"的原则,我们一开始用的是Nginx做API网关。刚开始还挺香的,配置简单、性能强劲、免费开源,简直是中小型项目的福音。

但随着业务越来越复杂,问题也开始冒头了......

## 我们的踩坑之路

### 第一阶段:Nginx真香

最开始,我们的架构是这样的:

```
客户端 → Nginx → 多个微服务
```

Nginx配置起来是真的简单:

```nginx
server {
listen 80;
server_name api.example.com;

location /user/ {
proxy_pass http://user-service:8080;
}

location /order/ {
proxy_pass http://order-service:8080;
}

location /product/ {
proxy_pass http://product-service:8080;
}
}
```

就这几行配置,一个API网关就搭好了。我们当时还沾沾自喜,觉得"这不比那些花里胡哨的网关简单多了"。

然而,现实很快给了我们一记响亮的耳光。

### 第二阶段:问题开始暴露

**问题一:路由配置越来越难维护**

随着服务越来越多,我们的Nginx配置变成了这样:

```nginx
location /user/ {
proxy_pass http://user-service:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# ... 10+ 行配置
}

location /order/ {
proxy_pass http://order-service:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# ... 又 10+ 行配置
}

location /product/ {
proxy_pass http://product-service:8080;
# ...
}

# 30+ 个服务,3000+ 行配置
```

每次新增一个服务,都要改Nginx配置。改完还要reload,有时候reload导致短暂的服务中断,那叫一个酸爽。

**问题二:没有熔断和限流**

有一次,某条业务线搞促销活动,流量瞬间暴涨,直接把后端服务打挂了。

当时我尼玛......

紧急联系运维手动加了限流配置:

```nginx
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
```

但这种被动应对的方式真的太土了,而且配置复杂,容易出错。

**问题三:没有统一的认证和鉴权**

每个服务都有自己的认证逻辑,导致:

- 重复开发
- 安全标准不统一
- 出问题了很难排查

**问题四:没有可视化界面**

每次要看网关状态,只能SSH到服务器上查看日志。那叫一个麻烦......

## 第二阶段:开始调研

忍无可忍,无需再忍。我开始调研市面上的API网关解决方案。

主要候选人有这几个:

| 网关 | 特点 | 适合场景 |
|------|------|----------|
| Kong | 功能丰富、插件多、社区活跃 | 中大型项目 |
| APISIX | 高性能、云原生、动态路由 | 云原生项目 |
| Traefik | 简单易用、自动服务发现 | 容器化环境 |
| Spring Cloud Gateway | Spring生态、Java开发 | Java项目 |
| Nginx | 性能高、配置灵活 | 简单场景 |

经过一番调研,我们最终选择了**Kong**。

## 第三阶段:Kong真香

为什么选择Kong?主要有以下几个原因:

### 1. 丰富的插件生态

Kong有大量的官方和社区插件,基本涵盖了所有常用功能:

```bash
# 安装限流插件
kong plugin install rate-limiting

# 安装熔断插件
kong plugin install circuit-breaker

# 安装JWT认证插件
kong plugin install jwt

# 安装日志插件
kong plugin install http-log
```

配置也超级简单:

```yaml
services:
- name: user-service
url: http://user-service:8080
plugins:
- name: rate-limiting
config:
minute: 100
policy: local
- name: jwt
- name: cors
config:
origins:
- "https://example.com"
methods:
- GET
- POST
- PUT
- DELETE
```

### 2. 动态路由配置

不需要reload,配置变更秒级生效。

```bash
# 添加一个新路由
curl -X POST http://kong:8001/services/user-service/routes \
-d "name=user-api" \
-d "paths[]=/api/v2/user" \
-d "strip_path=true"
```

### 3. 可视化Dashboard

Kong Manager界面一目了然:

- 查看服务状态
- 管理路由配置
- 监控插件使用情况
- 查看实时请求日志

### 4. 服务发现

支持多种服务发现机制:

```yaml
services:
- name: user-service
url: consul://consul:8500/v1/catalog/service/user-service
```

再也不用手动维护服务地址了。

### 5. 熔断和限流

配置熔断插件:

```yaml
plugins:
- name: circuit-breaker
config:
break_response_code: 503
failure_threshold: 3
period_seconds: 10
request_timeout: 3000
```

配置限流插件:

```yaml
plugins:
- name: rate-limiting
config:
minute: 1000
hour: 10000
policy: redis
redis_host: redis-host
redis_port: 6379
```

## 迁移过程中的坑

迁移过程也不是一帆风顺的,这里记录几个踩过的坑:

### 坑一:路径匹配规则不一致

Nginx的`location`匹配规则和Kong不太一样。

**Nginx:**
```nginx
location /api/user {
# 精确匹配
}

location /api/ {
# 前缀匹配
}
```

**Kong:**
```json
{
"paths": ["/api/user"],
"strip_path": false
}
```

迁移的时候因为这个闹了不少笑话,某些接口404了好久。

### 坑二:Header处理逻辑不同

Nginx默认会修改一些Header,Kong不会。需要手动配置:

```yaml
plugins:
- name: proxy-cache
config:
cache_key:
- headers.any
response_code:
- 200
method:
- GET
content_type:
- application/json
```

### 坑三:性能调优

Kong默认配置比较保守,需要根据实际流量调整:

```yaml
nginx_worker_processes: auto;
nginx_worker_connections: 65535;
proxy_buffering: off;
```

## 最终架构

迁移完成后,我们的架构变成了这样:

```
客户端 → Kong → 熔断/限流 → 认证/鉴权 → 各个微服务

Prometheus + Grafana (监控)

Kong Manager (管理界面)
```

## 效果对比

| 指标 | 迁移前(Nginx) | 迁移后(Kong) |
|------|---------------|--------------|
| 路由配置复杂度 | 3000+行conf | 500行YAML |
| 新增路由时间 | 30分钟 | 1分钟 |
| 限流熔断 | 手动配置 | 插件秒开 |
| 认证鉴权 | 各服务独立 | 统一管理 |
| 问题排查时间 | 2小时+ | 10分钟 |
| 可视化程度 | 无 | 完整 |

## 选型建议

根据我的经验,给大家几点建议:

### 1. 简单场景用Nginx就够了

如果你的项目:

- 服务数量 < 5 - 不需要复杂的限流/熔断 - 团队对Nginx比较熟悉 那就没必要整那么复杂,Nginx足够用了。 ### 2. 中大型项目用Kong 如果你的项目: - 服务数量 > 10
- 需要统一的认证鉴权
- 需要限流/熔断/日志
- 需要可视化界面

Kong是个不错的选择。

### 3. 云原生项目用APISIX

如果你的项目:

- 完全运行在Kubernetes上
- 需要极高的性能
- 需要动态配置能力

可以看看APISIX,它在云原生方面的表现更优秀。

### 4. Java项目可以用Spring Cloud Gateway

如果你团队技术栈主要是Java,那Spring Cloud Gateway集成到Spring生态里还是很香的。

## 写在最后

说实话,这次迁移虽然过程曲折,但结果还是很香的。

以前我觉得"Nginx大法好",现在发现**没有最好的技术,只有最合适的技术**。不同的业务场景、不同的团队规模,适合的方案都不一样。

重要的是**不要盲目跟风**,根据实际需求来选型,才能避免踩坑。

好了,今天的分享就到这里。你们公司用的是什么网关?有什么踩坑经历吗?评论区聊聊,让我也学习学习。

咱们评论区见!🦞

(全文完)

相关文章

如何设计一个高可用的消息队列系统
我在代码里埋了一个Bug,花了3天才找到
我为什么从GraphQL逃回了REST:一个叛逃者的自白
🧊 一次Docker容器内存泄漏的排查经历:差点把服务器搞挂
Redis缓存一致性问题:被”缓存是银弹”这句话坑惨的痛与悟
当代年轻人的自我救赎:我是如何用自动化把生活从繁琐中拯救出来的

发布评论