从Nginx走到Istio:API 网关笔记
这次做微服务改造,从 Nginx 到专业的 API 网关,再到 Istio Gateway,架构演进了好几轮。优势:简单,配置直接 劣势:功能有限,需要写 lua 插件
问题:Lua 开发成本高,维护困难
Kong 基于 OpenResty,插件生态丰富。
最初用 Nginx 做反向代理
简单的反向代理配置
upstream user_service {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
upstream order_service {
server 192.168.1.20:8080;
server 192.168.1.21:8080;
}
server {
listen 80;
server_name api.example.com;
# 用户服务
location /api/users/ {
proxy_pass http://user_service/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 订单服务
location /api/orders/ {
proxy_pass http://order_service/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
优势:简单,配置直接 劣势:功能有限,需要写 lua 插件
Nginx + Lua 增强
# 鉴权
location /api/ {
access_by_lua_block {
local token = ngx.var.http_authorization
if not token then
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.say("Missing token")
ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
-- 验证 token
local ok, err = verify_token(token)
if not ok then
ngx.status = ngx.HTTP_FORBIDDEN
ngx.say("Invalid token")
ngx.exit(ngx.HTTP_FORBIDDEN)
end
}
proxy_pass http://backend/;
}
问题:Lua 开发成本高,维护困难
专业的 API 网关
Kong 网关
Kong 基于 OpenResty,插件生态丰富。
部署 Kong:
# 使用 Docker 部署
docker run -d --name kong \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_PG_PASSWORD=kong" \
-e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
-p 8000:8000 \
-p 8443:8443 \
kong:latest
配置路由:
# 添加服务
curl -X POST http://localhost:8001/services \
--data "name=user-service" \
--data "url=http://user-service:8080"
# 添加路由
curl -X POST http://localhost:8001/services/user-service/routes \
--data "paths[]=/api/users"
# 启用插件
curl -X POST http://localhost:8001/services/user-service/plugins \
--data "name=jwt"
优势:
- 插件丰富(鉴权、限流、监控等)
- 管理界面友好
- 集群支持
APISIX 网关
APISIX 是国产的 API 网关,基于 Nginx + Lua。
部署 APISIX:
# 使用 Docker 部署
docker run -d --name apisix \
-p 9080:9080 \
-p 9443:9443 \
-p 9180:9180 \
-v "$(pwd)/apisix_conf:/usr/local/apisix/conf" \
apache/apisix:latest
配置路由:
# apisix_conf/config.yaml
routes:
- uri: /api/users/*
upstream:
type: roundrobin
nodes:
"192.168.1.10:8080": 1
"192.168.1.11:8080": 1
plugins:
jwt-auth:
key: my-secret-key
limit-req:
rate: 100
burst: 50
key_type: var
key: remote_addr
rejected_code: 429
优势:
- 性能好
- 支持动态配置
- 云原生友好
Kubernetes 环境
Ingress Controller
Kubernetes 的 Ingress Controller 是默认的网关方案。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/enable-cors: "true"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /api/users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
- path: /api/orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
限制:功能有限,不适合复杂场景
Service Mesh Gateway
Istio Gateway 提供了更强大的功能。
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: api-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "api.example.com"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api-virtualservice
spec:
hosts:
- "api.example.com"
gateways:
- api-gateway
http:
- match:
- uri:
prefix: /api/users
route:
- destination:
host: user-service
port:
number: 80
- match:
- uri:
prefix: /api/orders
route:
- destination:
host: order-service
port:
number: 80
核心功能实践
鉴权与认证
JWT 鉴权:
plugins:
jwt-auth:
key: my-secret-key
claims_to_verify:
- exp
OAuth2 鉴权:
plugins:
openid-connect:
client_id: my-client-id
client_secret: my-client-secret
discovery: https://auth.example.com/.well-known/openid-configuration
introspection_endpoint: https://auth.example.com/oauth/introspect
限流
基于 IP 的限流:
plugins:
limit-req:
rate: 100
burst: 50
key_type: var
key: remote_addr
rejected_code: 429
基于用户的限流:
plugins:
limit-req:
rate: 1000
burst: 100
key_type: var
key: http_x_user_id
rejected_code: 429
熔断与降级
熔断配置:
plugins:
circuit-breaker:
break_response_code: 503
break_response_body: "Service Unavailable"
max_breaker_sec: 30
unhealthy:
http_statuses:
- 500
- 502
- 503
failures: 3
降级配置:
plugins:
traffic-split:
rules:
- match:
- name: vars
value: degraded_mode
value_type: EQUAL
weighted_upstreams:
- upstream:
name: user-service
weight: 0
- upstream:
name: user-service-fallback
weight: 100
灰度发布
plugins:
traffic-split:
rules:
- weighted_upstreams:
- upstream:
name: user-service-v1
weight: 90
- upstream:
name: user-service-v2
weight: 10
10% 的流量会路由到 v2 版本。
踩过的坑
坑一:网关成为单点
一开始网关只有一个实例,挂了整个服务都不可用。
解决:部署多个网关节点,用负载均衡分发流量。
坑二:插件性能问题
开启了太多插件,导致网关性能下降。
解决:
- 只开启必要的插件
- 在服务端做复杂逻辑,网关只做路由和鉴权
- 定期评估插件性能
坑三:配置热更新问题
配置更新后,有些请求还是用的旧配置。
解决:使用网关的配置热更新功能,或者灰度更新。
# Kong 配置热更新
curl -X POST http://localhost:8001/config
选型建议
小团队(<5 个服务)
用 Nginx 就够了,简单直接。
中等团队(5-20 个服务)
Kong 或 APISIX,插件丰富,管理方便。
大团队(>20 个服务)
Istio Gateway,与 Service Mesh 集成,功能强大。
特殊需求
- 需要高性能:APISIX 或 Nginx
- 需要丰富插件:Kong
- 需要与 Service Mesh 集成:Istio
- 需要自定义逻辑:基于 Lua 或 Go 开发插件
写在最后
API 网关这东西,不是技术问题,是架构问题。
它解决了:
- 统一入口
- 鉴权认证
- 限流熔断
- 灰度发布
- 监控日志
但也会带来:
- 单点风险
- 性能瓶颈
- 复杂度增加
选型之前先评估:服务数量、团队规模、功能需求、性能要求。
不是最先进就好用,而是最合适。
这次 API 网关改造花了两周,从 Nginx 迁移到 Kong,再到 Istio Gateway。迁移完成后,鉴权、限流这些功能统一管理,维护成本降低了 40%。
版权声明: 本文首发于 指尖魔法屋-从Nginx走到Istio:API 网关笔记(https://blog.thinkmoon.cn/post/60-api-gateway-nginx-istio-architecture-evolution/) 转载或引用必须申明原指尖魔法屋来源及源地址!
评论
使用 GitHub 账号登录后即可留言,支持 Markdown。