企业信息化系统 API 网关设计与实现
为什么需要 API 网关
随着企业信息化系统规模的扩大,微服务架构下服务数量急剧增加。API 网关作为统一入口,承担着认证授权、流量管控、协议转换、监控告警等核心功能,是微服务架构中不可或缺的组件。
网关核心功能
| 功能模块 | 说明 | 实现方式 |
|---|---|---|
| 身份认证 | 验证请求合法性 | JWT、OAuth2、Session |
| 权限校验 | 校验用户权限 | RBAC、ABAC |
| 限流熔断 | 保护后端服务 | 令牌桶、滑动窗口 |
| 路由转发 | 请求分发到后端 | 路径、Header、参数 |
| 日志监控 | 记录请求日志 | ELK、Prometheus |
Kong 网关部署配置
Kong 是流行的开源 API 网关,以下是基于 Nginx 的简化实现方案:
1. Nginx 网关配置
upstream backend_oa {
server oa-service:8080;
keepalive 32;
}
upstream backend_erp {
server erp-service:8080;
keepalive 32;
}
upstream backend_crm {
server crm-service:8080;
keepalive 32;
}
server {
listen 80;
server_name api.eims.js.cn;
# 请求体大小限制
client_max_body_size 10M;
# 限流配置 - 令牌桶
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
location /oa/ {
# JWT 认证
auth_jwt "EIMS API" keyring;
# 限流
limit_req zone=api_limit burst=20 nodelay;
# 路由转发
rewrite ^/oa/(.*) /$1 break;
proxy_pass http://backend_oa/;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
location /erp/ {
auth_jwt "EIMS API" keyring;
limit_req zone=api_limit burst=20 nodelay;
rewrite ^/erp/(.*) /$1 break;
proxy_pass http://backend_erp/;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
location /crm/ {
auth_jwt "EIMS API" keyring;
limit_req zone=api_limit burst=20 nodelay;
rewrite ^/crm/(.*) /$1 break;
proxy_pass http://backend_crm/;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
# 健康检查
location /health {
access_log off;
return 200 "OK";
}
}
2. JWT 认证中间件
// JWT 验证函数
function verifyJwt(token, secret) {
try {
const decoded = jwt.verify(token, secret, {
algorithms: ['HS256', 'RS256']
});
return decoded;
} catch (err) {
return null;
}
}
// 请求拦截处理
async function gatewayMiddleware(ctx, next) {
const path = ctx.path;
// 跳过健康检查和公开接口
if (path === '/health' || path.startsWith('/public/')) {
return await next();
}
// 获取 Token
const token = ctx.get('Authorization')?.replace('Bearer ', '');
if (!token) {
ctx.status = 401;
ctx.body = { error: '缺少认证令牌' };
return;
}
// 验证 Token
const user = verifyJwt(token, process.env.JWT_SECRET);
if (!user) {
ctx.status = 401;
ctx.body = { error: '认证令牌无效' };
return;
}
// 权限校验
const requiredPermission = getRequiredPermission(path, ctx.method);
if (requiredPermission && !user.permissions.includes(requiredPermission)) {
ctx.status = 403;
ctx.body = { error: '权限不足' };
return;
}
// 注入用户信息
ctx.state.user = user;
await next();
}
限流与熔断策略
1. 限流算法实现
// 令牌桶算法实现
class TokenBucket {
constructor(capacity, refillRate) {
this.capacity = capacity; // 桶容量
this.tokens = capacity; // 当前令牌数
this.refillRate = refillRate; // 每秒补充令牌数
this.lastRefill = Date.now();
}
tryConsume(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;
const tokensToAdd = elapsed * this.refillRate;
this.tokens = Math.min(this.capacity, this.tokens + tokensToAdd);
this.lastRefill = now;
}
}
2. 熔断器模式
// 熔断器实现
class CircuitBreaker {
constructor(threshold, timeout) {
this.threshold = threshold; // 失败阈值
this.timeout = timeout; // 熔断时长(毫秒)
this.failCount = 0;
this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
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 (err) {
this.onFailure();
throw err;
}
}
onSuccess() {
this.failCount = 0;
this.state = 'CLOSED';
}
onFailure() {
this.failCount++;
if (this.failCount >= this.threshold) {
this.state = 'OPEN';
this.nextAttempt = Date.now() + this.timeout;
}
}
}
监控与告警
- 请求延迟:P50、P95、P99 延迟指标
- 错误率:按服务、接口维度统计
- 限流触发:记录被限流请求详情
- 流量趋势:QPS、带宽使用情况
总结
API 网关是企业信息化系统的统一入口,通过合理的网关设计可以实现认证授权、限流熔断、日志监控等核心功能。建议根据实际业务规模选择合适的实现方案,对于中小型系统可以采用 Nginx + Lua 方案,大型复杂系统建议使用 Kong、APISIX 等专业网关。