nodejs实现简单的网关

微服务分布式网关简介

微服务分布式网关是微服务架构中的关键组件,它作为系统的统一入口,负责请求路由、协议转换、权限校验、流量控制、监控日志等功能。其核心作用包括:

  1. 统一入口:简化客户端与微服务的交互,隐藏内部服务结构
  2. 请求路由:根据请求路径或条件将请求转发至对应服务
  3. 横切关注点处理:统一实现认证、限流、日志等功能,避免重复开发
  4. 协议适配:支持多种协议转换(如HTTP转gRPC)
  5. 负载均衡:在多个服务实例间分配请求

常见的开源网关包括:Nginx、Kong、APISIX、Spring Cloud Gateway等。

Node.js实现分布式网关

Node.js因其高并发特性成为实现API网关的理想选择。以下是一个基于Node.js的简单分布式网关实现示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
const http = require('http');
const https = require('https');
const httpProxy = require('http-proxy');
const jwt = require('jsonwebtoken');
const Redis = require('ioredis');

// 服务映射配置
const serviceMap = {
'/api/users': 'http://users-service:3001',
'/api/products': 'http://products-service:3002',
'/api/orders': 'http://orders-service:3003'
};

// 创建代理服务器
const proxy = httpProxy.createProxyServer({});

// Redis连接(用于限流)
const redisClient = new Redis({
host: 'redis',
port: 6379
});

// 认证中间件
function authenticate(req, res, next) {
const token = req.headers['authorization'];

if (!token) {
return res.status(401).send('Authentication required');
}

try {
// 验证JWT令牌
const decoded = jwt.verify(token.split(' ')[1], 'your-secret-key');
req.user = decoded;
next();
} catch (err) {
res.status(403).send('Invalid token');
}
}

// 限流中间件
async function rateLimit(req, res, next) {
const ip = req.ip;
const endpoint = req.path;
const key = `${ip}:${endpoint}`;

try {
// 检查请求次数
const current = await redisClient.incr(key);

if (current === 1) {
await redisClient.expire(key, 60); // 1分钟过期
}

if (current > 100) { // 限制每分钟100次请求
return res.status(429).send('Too many requests');
}

next();
} catch (err) {
console.error('Rate limit error:', err);
next(); // 出错时继续处理请求
}
}

// 创建HTTP服务器
const server = http.createServer(async (req, res) => {
try {
// 查找匹配的服务
const target = Object.keys(serviceMap).find(prefix => req.url.startsWith(prefix));

if (!target) {
return res.status(404).send('Service not found');
}

// 应用中间件
await authenticate(req, res, () => {});
await rateLimit(req, res, () => {});

// 转发请求
proxy.web(req, res, {
target: serviceMap[target],
changeOrigin: true,
pathRewrite: {
[`^${target}`]: '' // 移除路径前缀
}
});
} catch (err) {
console.error('Gateway error:', err);
res.status(500).send('Internal server error');
}
});

// 错误处理
proxy.on('error', (err, req, res) => {
console.error('Proxy error:', err);
res.status(502).send('Bad Gateway');
});

// 启动服务器
server.listen(3000, () => {
console.log('API Gateway running on port 3000');
});

关键组件说明

  1. 路由转发:使用http-proxy模块根据路径前缀将请求转发至对应的后端服务

  2. 认证授权

    • JWT令牌验证
    • 用户身份信息注入请求上下文
    • 权限校验(示例中简化处理)
  3. 流量控制

    • 基于Redis的计数器实现限流
    • 支持IP+端点的细粒度限流策略
    • 滑动窗口或令牌桶算法可进一步优化限流效果
  4. 弹性模式

    • 错误处理与熔断机制
    • 服务健康检查与自动重试
    • 降级策略(示例中未体现)
  5. 监控日志

    • 请求日志记录
    • 性能指标收集
    • 错误监控上报

扩展与优化建议

  1. 服务发现集成

    • 连接Consul、Etcd或Nacos等服务注册中心
    • 动态更新服务映射关系
  2. 负载均衡

    • 实现轮询、随机、权重等负载均衡算法
    • 集成服务健康检查
  3. 安全增强

    • 添加WAF功能
    • 实现请求参数校验
    • 支持HTTPS
  4. 性能优化

    • 引入缓存机制
    • 使用集群模式部署
    • 实现长连接支持
  5. 可观测性

    • 集成Prometheus和Grafana进行监控
    • 添加分布式追踪(如Zipkin、Jaeger)
    • 实现告警机制

这个示例展示了Node.js实现分布式网关的基本架构,实际生产环境中还需要根据具体需求进行扩展和优化。