前端API设计:API网关设计指南
前端API设计:API网关设计指南
前言
API网关是现代微服务架构中的核心组件,它为前端提供了统一的API入口。今天我就来给大家详细介绍API网关的设计原则和最佳实践。
什么是API网关
API网关是一个服务器,它作为API请求的入口点,处理所有客户端请求并将其路由到相应的微服务。
API网关的核心功能
const apiGatewayFeatures = [ '请求路由', '负载均衡', '认证授权', '限流熔断', '日志监控', '协议转换' ];API网关架构设计
# API网关架构 客户端 ↔ API网关 ↔ 微服务 1. 请求进入API网关 2. 认证授权检查 3. 请求路由 4. 负载均衡 5. 请求转发到微服务 6. 响应返回给客户端API网关核心功能实现
1. 请求路由
// 路由配置 const routes = [ { path: '/api/users', target: 'user-service', version: 'v1' }, { path: '/api/posts', target: 'post-service', version: 'v1' }, { path: '/api/orders', target: 'order-service', version: 'v2' } ]; // 路由匹配 function matchRoute(path) { return routes.find(route => path.startsWith(route.path) ); }2. 认证授权
// JWT认证中间件 async function authenticate(req, res, next) { const token = req.headers.authorization?.split(' ')[1]; if (!token) { return res.status(401).json({ error: 'Unauthorized' }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); } catch (error) { return res.status(401).json({ error: 'Invalid token' }); } } // 权限检查中间件 function requireRole(role) { return (req, res, next) => { if (req.user.role !== role) { return res.status(403).json({ error: 'Forbidden' }); } next(); }; }3. 限流熔断
// 限流配置 const rateLimit = new Map(); const MAX_REQUESTS = 100; const TIME_WINDOW = 60000; // 限流中间件 function rateLimiter(req, res, next) { const ip = req.ip; const now = Date.now(); if (!rateLimit.has(ip)) { rateLimit.set(ip, { count: 1, timestamp: now }); } else { const record = rateLimit.get(ip); if (now - record.timestamp > TIME_WINDOW) { rateLimit.set(ip, { count: 1, timestamp: now }); } else { if (record.count >= MAX_REQUESTS) { return res.status(429).json({ error: 'Too many requests' }); } record.count++; } } next(); } // 熔断配置 const circuitBreaker = { state: 'closed', failureCount: 0, lastFailureTime: 0, resetTimeout: 30000 }; // 熔断中间件 async function circuitBreakerMiddleware(req, res, next) { const { state, failureCount, lastFailureTime, resetTimeout } = circuitBreaker; if (state === 'open') { if (Date.now() - lastFailureTime > resetTimeout) { circuitBreaker.state = 'half-open'; } else { return res.status(503).json({ error: 'Service unavailable' }); } } try { await next(); circuitBreaker.failureCount = 0; circuitBreaker.state = 'closed'; } catch (error) { circuitBreaker.failureCount++; circuitBreaker.lastFailureTime = Date.now(); if (circuitBreaker.failureCount >= 5) { circuitBreaker.state = 'open'; } throw error; } }4. 负载均衡
// 负载均衡策略 const strategies = { roundRobin: (services) => { let index = 0; return () => { const service = services[index % services.length]; index++; return service; }; }, leastConnections: (services) => { return () => { return services.reduce((min, service) => service.connections < min.connections ? service : min ); }; }, random: (services) => { return () => { return services[Math.floor(Math.random() * services.length)]; }; } }; // 使用负载均衡 const getService = strategies.roundRobin([ { host: 'service1.example.com', port: 8080, connections: 0 }, { host: 'service2.example.com', port: 8080, connections: 0 }, { host: 'service3.example.com', port: 8080, connections: 0 } ]);5. 请求聚合
// 请求聚合示例 async function aggregateUserAndPosts(req, res) { const userId = req.params.id; // 并行请求 const [user, posts] = await Promise.all([ fetch(`http://user-service/api/users/${userId}`), fetch(`http://post-service/api/posts?userId=${userId}`) ]); const userData = await user.json(); const postsData = await posts.json(); // 聚合响应 res.json({ ...userData, posts: postsData }); }API网关安全考虑
1. HTTPS强制
// HTTPS重定向 function enforceHttps(req, res, next) { if (req.protocol !== 'https') { return res.redirect(`https://${req.hostname}${req.url}`); } next(); }2. 请求验证
// 请求参数验证 const Joi = require('joi'); const userSchema = Joi.object({ name: Joi.string().required(), email: Joi.string().email().required(), age: Joi.number().integer().min(18) }); function validateUser(req, res, next) { const { error } = userSchema.validate(req.body); if (error) { return res.status(400).json({ error: error.details[0].message }); } next(); }3. 安全头配置
// 安全头中间件 function securityHeaders(req, res, next) { res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('X-Frame-Options', 'DENY'); res.setHeader('X-XSS-Protection', '1; mode=block'); res.setHeader('Content-Security-Policy', "default-src 'self'"); res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); next(); }API网关监控
1. 日志记录
// 日志中间件 function logger(req, res, next) { const start = Date.now(); res.on('finish', () => { const duration = Date.now() - start; console.log({ timestamp: new Date().toISOString(), method: req.method, path: req.path, status: res.statusCode, duration: `${duration}ms`, ip: req.ip }); }); next(); }2. 指标监控
// 监控指标 const metrics = { requests: 0, errors: 0, latency: [] }; // 指标中间件 function metricsMiddleware(req, res, next) { const start = Date.now(); metrics.requests++; res.on('finish', () => { const duration = Date.now() - start; metrics.latency.push(duration); if (res.statusCode >= 500) { metrics.errors++; } }); next(); }API网关部署
# docker-compose.yml version: '3.8' services: api-gateway: image: api-gateway:latest ports: - "80:80" - "443:443" environment: - NODE_ENV=production - JWT_SECRET=secret depends_on: - user-service - post-service - order-service user-service: image: user-service:latest ports: - "8081:8080" post-service: image: post-service:latest ports: - "8082:8080" order-service: image: order-service:latest ports: - "8083:8080"总结
API网关是微服务架构的核心组件:
- 统一入口:为前端提供单一API入口
- 安全防护:认证、授权、限流、熔断
- 性能优化:负载均衡、请求聚合
- 监控日志:统一的监控和日志记录
设计一个优秀的API网关需要考虑:
- 高可用性
- 性能
- 安全性
- 可扩展性
希望这篇文章能帮助你设计出更好的API网关!
