API 网关是微服务架构的核心组件,承担着请求路由、认证授权、限流熔断、日志监控等功能。本文详细介绍 IMS 系统的 API 网关设计与实现。
一、API 网关概述
API 网关是系统的统一入口,所有外部请求都经过网关转发到后端服务。主要功能包括:
- 请求路由:根据路径、参数将请求路由到对应服务
- 认证授权:验证 Token、检查权限
- 限流熔断:保护后端服务,防止过载
- 日志监控:记录请求日志,便于分析
- 协议转换:支持 HTTP、gRPC、WebSocket 等
二、网关架构设计
/* API 网关架构 */ ┌─────────────────────────────────────────────────────┐ │ API Gateway │ ├─────────────────────────────────────────────────────┤ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 请求 │ │ 路由 │ │ 认证 │ │ │ │ 解析 │ │ 转发 │ │ 拦截 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 限流 │ │ 熔断 │ │ 日志 │ │ │ │ 控制 │ │ 保护 │ │ 记录 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └───────────────────────┬─────────────────────────────┘ ↓ ┌──────────────┬──────────────┬──────────────┐ │ 用户服务 │ 订单服务 │ 商品服务 │ │ /api/user │ /api/order │ /api/product │ └──────────────┴──────────────┴──────────────┘
三、请求路由实现
/* 路由配置 */ const routes = [ { "path": "/api/user/**", "service": "user-service", "version": "v2", "timeout": 5000 }, { "path": "/api/order/**", "service": "order-service", "version": "v1", "timeout": 10000 }, { "path": "/api/product/**", "service": "product-service", "stripPath": true } ]; /* 路由匹配逻辑 */ function matchRoute(path) { for (const route of routes) { if (matchPath(path, route.path)) { return route; } } return null; }
四、认证授权
/* 认证中间件 */ async authMiddleware(ctx, next) { // 1. 提取 Token const token = extractToken(ctx.get('Authorization')); if (!token) { return ctx.throw(401, '缺少认证令牌'); } // 2. 验证 Token try { const payload = jwt.verify(token, SECRET_KEY); ctx.user = payload; } catch (e) { return ctx.throw(401, '无效的认证令牌'); } // 3. 检查权限 const requiredPermission = getRequiredPermission(ctx.get('path'), ctx.get('method')); if (requiredPermission && !ctx.user.permissions.includes(requiredPermission)) { return ctx.throw(403, '权限不足'); } // 4. 放行 await next(); }
权限模型设计
| 操作 | 说明 |
|---|---|
| user:read | 查看用户 |
| user:create | 创建用户 |
| user:update | 修改用户 |
| user:delete | 删除用户 |
| order:* | 订单所有操作 |
最佳实践:
- 使用 JWT Token,支持分布式验证
- Token 短期有效,refresh token 长期有效
- 敏感接口增加二次验证(短信、邮件)
五、限流策略
/* 限流器实现 - 令牌桶 */ class TokenBucket { constructor(rate, capacity) { this.rate = rate; // 每秒添加的令牌数 this.capacity = capacity; // 桶的容量 this.tokens = capacity; this.lastRefill = Date.now(); } consume(tokens = 1) { this.refill(); if (this.tokens >= tokens) { this.tokens -= tokens; return true; } return false; // 被限流 } refill() { const now = Date.now(); const elapsed = (now - this.lastRefill) / 1000; this.tokens = Math.min(this.capacity, this.tokens + elapsed * this.rate); this.lastRefill = now; } } /* 全局限流配置 */ const globalLimiter = new TokenBucket(1000, 2000); // 1000 QPS /* 端点限流配置 */ const endpointLimiters = { 'POST /api/order': new TokenBucket(50, 100), 'POST /api/user/login': new TokenBucket(5, 10) };
六、熔断保护
/* 熔断器实现 */ class CircuitBreaker { constructor(options) { this.failureThreshold = options.failureThreshold || 5; this.successThreshold = options.successThreshold || 2; this.timeout = options.timeout || 30000; this.state = 'CLOSED'; // CLOSED/OPEN/HALF_OPEN this.failures = 0; this.successes = 0; this.nextAttempt = 0; } async execute(fn) { if (this.state === 'OPEN') { if (Date.now() < this.nextAttempt) { throw new Error('服务不可用 (熔断打开)'); } this.state = 'HALF_OPEN'; } try { const result = await fn(); this.onSuccess(); return result; } catch (e) { this.onFailure(); throw e; } } onSuccess() { if (this.state === 'HALF_OPEN') { this.successes++; if (this.successes >= this.successThreshold) { this.state = 'CLOSED'; this.failures = 0; this.successes = 0; } } } onFailure() { this.failures++; if (this.failures >= this.failureThreshold) { this.state = 'OPEN'; this.nextAttempt = Date.now() + this.timeout; } } }
七、日志与监控
/* 请求日志记录 */ async loggingMiddleware(ctx, next) { const startTime = Date.now(); const requestId = generateId(); ctx.set('X-Request-ID', requestId); try { await next(); // 记录成功日志 logger.info({ requestId, method: ctx.method, path: ctx.path, status: ctx.status, duration: Date.now() - startTime, userId: ctx.user?.id }); } catch (e) { // 记录错误日志 logger.error({ requestId, method: ctx.method, path: ctx.path, error: e.message, stack: e.stack, duration: Date.now() - startTime }); throw e; } }
八、总结
- API 网关是系统统一入口,负责请求路由、认证、限流等功能
- 路由配置支持路径匹配、服务版本、超时设置
- 认证采用 JWT,结合权限模型实现细粒度授权
- 限流使用令牌桶算法,支持全局和端点级别限流
- 熔断器保护后端服务,防止故障扩散
- 完善的日志记录有助于问题排查和性能分析