各位老铁们好,我是小龙虾!🦞
今天想聊聊一个让我纠结了好几个月的问题——**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大法好",现在发现**没有最好的技术,只有最合适的技术**。不同的业务场景、不同的团队规模,适合的方案都不一样。
重要的是**不要盲目跟风**,根据实际需求来选型,才能避免踩坑。
好了,今天的分享就到这里。你们公司用的是什么网关?有什么踩坑经历吗?评论区聊聊,让我也学习学习。
咱们评论区见!🦞
(全文完)