第一部分:基础概念
第二部分:核心原理
第三部分:功能特性
第四部分:技术实现
第五部分:最佳实践
第六部分:实战应用
API网关(API Gateway)是一种应用程序架构模式,它作为系统的统一入口,负责接收、处理和路由所有的API请求。API网关位于客户端和后端服务之间,充当反向代理的角色,为微服务架构提供统一的访问接口。
核心定义:
API网关是微服务架构中的关键组件,它提供了一个统一的入口点来管理、监控和保护所有的API调用,同时简化了客户端与后端服务之间的交互复杂性。
统一入口点
服务聚合
横切关注点处理
在单体架构时代,应用程序通常作为一个整体部署,客户端直接与单一的应用服务器交互。这种模式简单直接,但随着业务复杂度的增长,单体架构的局限性逐渐暴露:
面向服务架构(SOA)的出现标志着分布式架构的开始。在SOA架构中:
ESB在某种程度上可以看作是API网关的前身,但它主要关注企业内部服务的集成,而非面向互联网的API管理。
微服务架构的普及带来了新的挑战:
API网关应运而生,作为微服务架构的重要组件,解决了这些挑战。
在云原生时代,API网关进一步演进:
没有API网关的问题:
客户端复杂性增加
横切关注点重复实现
安全性风险
API网关的优势:
简化客户端
集中处理横切关注点
提高安全性
1. 客户端接入层
2. API网关层
这是整个架构的核心层,包含多个关键组件:
3. 业务服务层
4. 基础设施层
1. 单实例部署
适用于小型应用,简单但存在单点故障风险。
2. 高可用部署
多实例部署,消除单点故障,提高系统可用性。
3. 分区部署
跨地域部署,提供更好的性能和容灾能力。
1. 请求接收与预处理
// 请求预处理示例
function preprocessRequest(request) {
// 提取请求头信息
const headers = request.headers;
const userAgent = headers['user-agent'];
const contentType = headers['content-type'];
// 解析请求路径
const url = new URL(request.url);
const path = url.pathname;
const queryParams = url.searchParams;
// 请求验证
if (!isValidRequest(request)) {
throw new Error('Invalid request format');
}
return {
method: request.method,
path: path,
headers: headers,
query: Object.fromEntries(queryParams),
body: request.body
};
}
2. 身份认证流程
API网关支持多种认证方式:
// JWT认证示例
function authenticateJWT(token) {
try {
const decoded = jwt.verify(token, SECRET_KEY);
return {
valid: true,
userId: decoded.userId,
roles: decoded.roles,
exp: decoded.exp
};
} catch (error) {
return {
valid: false,
error: error.message
};
}
}
3. 权限授权检查
// 权限检查示例
function checkPermission(user, resource, action) {
const userRoles = user.roles;
const requiredPermission = `${resource}:${action}`;
return userRoles.some(role => {
return rolePermissions[role].includes(requiredPermission);
});
}
4. 限流与熔断
// 限流算法示例(令牌桶)
class TokenBucket {
constructor(capacity, refillRate) {
this.capacity = capacity;
this.tokens = capacity;
this.refillRate = refillRate;
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 timePassed = (now - this.lastRefill) / 1000;
const tokensToAdd = timePassed * this.refillRate;
this.tokens = Math.min(this.capacity, this.tokens + tokensToAdd);
this.lastRefill = now;
}
}
5. 路由解析与服务发现
// 路由规则示例
const routingRules = [
{
pattern: '/api/users/*',
service: 'user-service',
version: 'v1',
weight: 100
},
{
pattern: '/api/orders/*',
service: 'order-service',
version: 'v2',
weight: 80
}
];
function resolveRoute(path) {
for (const rule of routingRules) {
if (matchPattern(path, rule.pattern)) {
return {
service: rule.service,
version: rule.version,
targetUrl: serviceRegistry.getServiceUrl(rule.service)
};
}
}
throw new Error('No matching route found');
}
1. 连接池管理
// HTTP连接池配置
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 10,
timeout: 60000
});
2. 响应缓存
// 响应缓存策略
function getCachedResponse(cacheKey) {
const cached = cache.get(cacheKey);
if (cached && !isExpired(cached)) {
return cached.data;
}
return null;
}
function setCachedResponse(cacheKey, data, ttl = 300) {
cache.set(cacheKey, {
data: data,
timestamp: Date.now(),
ttl: ttl * 1000
});
}
3. 异步处理
// 异步请求处理
async function handleRequest(request) {
try {
// 并行执行多个操作
const [authResult, rateLimitResult] = await Promise.all([
authenticateUser(request),
checkRateLimit(request)
]);
if (!authResult.valid) {
return createErrorResponse(401, 'Unauthorized');
}
if (!rateLimitResult.allowed) {
return createErrorResponse(429, 'Rate limit exceeded');
}
const response = await forwardRequest(request);
return response;
} catch (error) {
return createErrorResponse(500, 'Internal server error');
}
}
路由引擎是API网关的核心组件,负责将客户端请求路由到正确的后端服务。
路由匹配算法:
// 路由引擎实现
class Router {
constructor() {
this.routes = [];
}
addRoute(pattern, handler, options = {}) {
this.routes.push({
pattern: this.compilePattern(pattern),
handler: handler,
method: options.method || 'GET',
priority: options.priority || 0
});
// 按优先级排序
this.routes.sort((a, b) => b.priority - a.priority);
}
compilePattern(pattern) {
// 将路径模式编译为正则表达式
const regexPattern = pattern
.replace(/\*/g, '.*')
.replace(/\?/g, '.')
.replace(/\{(\w+)\}/g, '(?<$1>[^/]+)');
return new RegExp(`^${regexPattern}$`);
}
match(path, method) {
for (const route of this.routes) {
if (route.method === method || route.method === 'ALL') {
const match = path.match(route.pattern);
if (match) {
return {
handler: route.handler,
params: match.groups || {}
};
}
}
}
return null;
}
}
负载均衡器决定如何在多个后端服务实例之间分配请求。
常见负载均衡算法:
负载均衡算法实现:
// 负载均衡器实现
class LoadBalancer {
constructor(algorithm = 'round-robin') {
this.algorithm = algorithm;
this.services = [];
this.currentIndex = 0;
this.connections = new Map();
}
addService(service) {
this.services.push({
...service,
weight: service.weight || 1,
currentWeight: 0
});
}
selectService(request) {
switch (this.algorithm) {
case 'round-robin':
return this.roundRobin();
case 'weighted-round-robin':
return this.weightedRoundRobin();
case 'least-connections':
return this.leastConnections();
case 'ip-hash':
return this.ipHash(request.clientIP);
default:
return this.roundRobin();
}
}
roundRobin() {
const service = this.services[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.services.length;
return service;
}
weightedRoundRobin() {
let totalWeight = 0;
let selected = null;
for (const service of this.services) {
service.currentWeight += service.weight;
totalWeight += service.weight;
if (!selected || service.currentWeight > selected.currentWeight) {
selected = service;
}
}
selected.currentWeight -= totalWeight;
return selected;
}
leastConnections() {
return this.services.reduce((min, service) => {
const connections = this.connections.get(service.id) || 0;
const minConnections = this.connections.get(min.id) || 0;
return connections < minConnections ? service : min;
});
}
ipHash(clientIP) {
const hash = this.simpleHash(clientIP);
const index = hash % this.services.length;
return this.services[index];
}
simpleHash(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash + str.charCodeAt(i)) & 0xffffffff;
}
return Math.abs(hash);
}
}
缓存管理器提供多层缓存策略,提高系统性能。
缓存架构:
缓存策略实现:
// 多层缓存管理器
class CacheManager {
constructor(options = {}) {
this.l1Cache = new LRUCache({ max: options.l1Size || 1000 });
this.l2Cache = new RedisClient(options.redis);
this.defaultTTL = options.defaultTTL || 300;
}
async get(key) {
// 先查L1缓存
let value = this.l1Cache.get(key);
if (value) {
return { data: value, source: 'L1' };
}
// 再查L2缓存
value = await this.l2Cache.get(key);
if (value) {
// 回写到L1缓存
this.l1Cache.set(key, value);
return { data: JSON.parse(value), source: 'L2' };
}
return null;
}
async set(key, value, ttl = this.defaultTTL) {
// 同时写入L1和L2缓存
this.l1Cache.set(key, value);
await this.l2Cache.setex(key, ttl, JSON.stringify(value));
}
async invalidate(pattern) {
// 清理匹配的缓存项
this.l1Cache.clear();
const keys = await this.l2Cache.keys(pattern);
if (keys.length > 0) {
await this.l2Cache.del(...keys);
}
}
generateCacheKey(request) {
const { path, method, query, userId } = request;
return `${method}:${path}:${JSON.stringify(query)}:${userId || 'anonymous'}`;
}
}
监控组件收集各种指标数据,提供系统可观测性。
监控指标分类:
mindmap
root((监控指标))
业务指标
请求总数
成功率
错误率
响应时间分布
系统指标
CPU使用率
内存使用率
网络IO
磁盘IO
自定义指标
用户活跃度
业务转化率
功能使用情况
指标收集器实现:
// 指标收集器
class MetricsCollector {
constructor() {
this.metrics = new Map();
this.histograms = new Map();
this.counters = new Map();
this.gauges = new Map();
}
incrementCounter(name, labels = {}, value = 1) {
const key = this.createKey(name, labels);
const current = this.counters.get(key) || 0;
this.counters.set(key, current + value);
}
recordHistogram(name, value, labels = {}) {
const key = this.createKey(name, labels);
if (!this.histograms.has(key)) {
this.histograms.set(key, []);
}
this.histograms.get(key).push({
value: value,
timestamp: Date.now()
});
}
setGauge(name, value, labels = {}) {
const key = this.createKey(name, labels);
this.gauges.set(key, {
value: value,
timestamp: Date.now()
});
}
createKey(name, labels) {
const labelStr = Object.entries(labels)
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => `${k}="${v}"`)
.join(',');
return `${name}{${labelStr}}`;
}
// 记录请求指标
recordRequest(request, response, duration) {
const labels = {
method: request.method,
status: response.status,
service: request.targetService
};
this.incrementCounter('api_requests_total', labels);
this.recordHistogram('api_request_duration_seconds', duration / 1000, labels);
if (response.status >= 400) {
this.incrementCounter('api_errors_total', labels);
}
}
// 导出Prometheus格式指标
exportPrometheusMetrics() {
let output = '';
// 导出计数器
for (const [key, value] of this.counters) {
output += `${key} ${value}\n`;
}
// 导出直方图
for (const [key, values] of this.histograms) {
const sortedValues = values.map(v => v.value).sort((a, b) => a - b);
const count = sortedValues.length;
const sum = sortedValues.reduce((a, b) => a + b, 0);
output += `${key}_count ${count}\n`;
output += `${key}_sum ${sum}\n`;
// 计算分位数
[0.5, 0.9, 0.95, 0.99].forEach(quantile => {
const index = Math.floor(quantile * (count - 1));
const value = sortedValues[index] || 0;
const quantileKey = key.replace('{', `{quantile="${quantile}",`);
output += `${quantileKey} ${value}\n`;
});
}
return output;
}
}
基于内容的路由:
// 基于请求内容的路由策略
class ContentBasedRouter {
constructor() {
this.rules = [];
}
addRule(condition, target, priority = 0) {
this.rules.push({ condition, target, priority });
this.rules.sort((a, b) => b.priority - a.priority);
}
route(request) {
for (const rule of this.rules) {
if (this.evaluateCondition(rule.condition, request)) {
return rule.target;
}
}
throw new Error('No matching route found');
}
evaluateCondition(condition, request) {
switch (condition.type) {
case 'header':
return request.headers[condition.key] === condition.value;
case 'query':
return request.query[condition.key] === condition.value;
case 'body':
return this.checkBodyCondition(condition, request.body);
case 'user':
return this.checkUserCondition(condition, request.user);
default:
return false;
}
}
checkBodyCondition(condition, body) {
try {
const data = typeof body === 'string' ? JSON.parse(body) : body;
return data[condition.key] === condition.value;
} catch {
return false;
}
}
checkUserCondition(condition, user) {
if (!user) return false;
switch (condition.property) {
case 'role':
return user.roles.includes(condition.value);
case 'region':
return user.region === condition.value;
case 'plan':
return user.plan === condition.value;
default:
return false;
}
}
}
// 使用示例
const router = new ContentBasedRouter();
// 根据用户角色路由
router.addRule(
{ type: 'user', property: 'role', value: 'premium' },
{ service: 'premium-api', version: 'v2' },
100
);
// 根据地理位置路由
router.addRule(
{ type: 'user', property: 'region', value: 'asia' },
{ service: 'asia-api', version: 'v1' },
90
);
// 根据请求头路由
router.addRule(
{ type: 'header', key: 'x-api-version', value: 'beta' },
{ service: 'beta-api', version: 'v3' },
80
);
A/B测试路由:
// A/B测试路由实现
class ABTestRouter {
constructor() {
this.experiments = new Map();
}
createExperiment(name, config) {
this.experiments.set(name, {
name: name,
variants: config.variants,
allocation: config.allocation,
criteria: config.criteria
});
}
route(request, experimentName) {
const experiment = this.experiments.get(experimentName);
if (!experiment) {
return this.getDefaultRoute(request);
}
// 检查用户是否符合实验条件
if (!this.matchesCriteria(request, experiment.criteria)) {
return this.getDefaultRoute(request);
}
// 根据分配策略选择变体
const variant = this.selectVariant(request, experiment);
return {
service: variant.service,
version: variant.version,
experiment: experimentName,
variant: variant.name
};
}
selectVariant(request, experiment) {
// 使用用户ID确保一致性
const userId = this.getUserId(request);
const hash = this.hash(userId + experiment.name);
const percentage = hash % 100;
let cumulativeWeight = 0;
for (const variant of experiment.variants) {
cumulativeWeight += experiment.allocation[variant.name];
if (percentage < cumulativeWeight) {
return variant;
}
}
// 默认返回第一个变体
return experiment.variants[0];
}
matchesCriteria(request, criteria) {
if (!criteria) return true;
for (const [key, value] of Object.entries(criteria)) {
switch (key) {
case 'userType':
if (request.user?.type !== value) return false;
break;
case 'platform':
if (request.headers['x-platform'] !== value) return false;
break;
case 'version':
if (request.headers['x-app-version'] !== value) return false;
break;
}
}
return true;
}
getUserId(request) {
return request.user?.id || request.sessionId || request.ip;
}
hash(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash + str.charCodeAt(i)) & 0xffffffff;
}
return Math.abs(hash);
}
}
与Consul集成:
// Consul服务发现集成
class ConsulServiceDiscovery {
constructor(consulClient) {
this.consul = consulClient;
this.services = new Map();
this.watchers = new Map();
}
async discoverService(serviceName) {
try {
const result = await this.consul.health.service({
service: serviceName,
passing: true // 只返回健康的服务实例
});
const instances = result.map(item => ({
id: item.Service.ID,
address: item.Service.Address,
port: item.Service.Port,
tags: item.Service.Tags,
meta: item.Service.Meta,
health: 'healthy'
}));
this.services.set(serviceName, instances);
return instances;
} catch (error) {
console.error(`Failed to discover service ${serviceName}:`, error);
return [];
}
}
watchService(serviceName, callback) {
if (this.watchers.has(serviceName)) {
return; // 已经在监听
}
const watcher = this.consul.watch({
method: this.consul.health.service,
options: {
service: serviceName,
passing: true
}
});
watcher.on('change', (data) => {
const instances = data.map(item => ({
id: item.Service.ID,
address: item.Service.Address,
port: item.Service.Port,
tags: item.Service.Tags,
meta: item.Service.Meta,
health: 'healthy'
}));
this.services.set(serviceName, instances);
callback(serviceName, instances);
});
watcher.on('error', (error) => {
console.error(`Service discovery error for ${serviceName}:`, error);
});
this.watchers.set(serviceName, watcher);
}
getServiceInstances(serviceName) {
return this.services.get(serviceName) || [];
}
async registerService(serviceConfig) {
try {
await this.consul.agent.service.register({
name: serviceConfig.name,
id: serviceConfig.id,
address: serviceConfig.address,
port: serviceConfig.port,
tags: serviceConfig.tags,
check: {
http: `http://${serviceConfig.address}:${serviceConfig.port}/health`,
interval: '10s',
timeout: '5s'
}
});
console.log(`Service ${serviceConfig.name} registered successfully`);
} catch (error) {
console.error(`Failed to register service ${serviceConfig.name}:`, error);
}
}
}
基于响应时间的负载均衡:
// 智能负载均衡器
class IntelligentLoadBalancer {
constructor() {
this.services = [];
this.stats = new Map();
this.circuitBreakers = new Map();
}
addService(service) {
this.services.push(service);
this.initializeStats(service.id);
this.initializeCircuitBreaker(service.id);
}
initializeStats(serviceId) {
this.stats.set(serviceId, {
responseTime: [],
errorCount: 0,
requestCount: 0,
lastResponseTime: Date.now()
});
}
initializeCircuitBreaker(serviceId) {
this.circuitBreakers.set(serviceId, {
state: 'CLOSED', // CLOSED, OPEN, HALF_OPEN
failureCount: 0,
nextAttempt: 0,
failureThreshold: 5,
timeout: 60000 // 1分钟
});
}
selectService(request) {
// 过滤掉熔断的服务
const availableServices = this.services.filter(service =>
this.isServiceAvailable(service.id)
);
if (availableServices.length === 0) {
throw new Error('No available services');
}
// 基于响应时间和错误率选择最佳服务
return this.selectBestService(availableServices);
}
selectBestService(services) {
let bestService = null;
let bestScore = -Infinity;
for (const service of services) {
const score = this.calculateServiceScore(service.id);
if (score > bestScore) {
bestScore = score;
bestService = service;
}
}
return bestService;
}
calculateServiceScore(serviceId) {
const stats = this.stats.get(serviceId);
if (!stats || stats.requestCount === 0) {
return 1.0; // 新服务给予较高优先级
}
// 计算平均响应时间
const avgResponseTime = stats.responseTime.length > 0
? stats.responseTime.reduce((a, b) => a + b, 0) / stats.responseTime.length
: 1000;
// 计算错误率
const errorRate = stats.errorCount / stats.requestCount;
// 响应时间越短,错误率越低,分数越高
const timeScore = 1000 / (avgResponseTime + 1);
const errorScore = 1 - errorRate;
return timeScore * errorScore;
}
isServiceAvailable(serviceId) {
const breaker = this.circuitBreakers.get(serviceId);
const now = Date.now();
switch (breaker.state) {
case 'CLOSED':
return true;
case 'OPEN':
if (now >= breaker.nextAttempt) {
breaker.state = 'HALF_OPEN';
return true;
}
return false;
case 'HALF_OPEN':
return true;
default:
return false;
}
}
recordResponse(serviceId, responseTime, isError = false) {
const stats = this.stats.get(serviceId);
const breaker = this.circuitBreakers.get(serviceId);
if (!stats || !breaker) return;
// 更新统计信息
stats.requestCount++;
stats.responseTime.push(responseTime);
if (stats.responseTime.length > 100) {
stats.responseTime.shift(); // 保持最近100个响应时间
}
if (isError) {
stats.errorCount++;
breaker.failureCount++;
// 检查是否需要打开熔断器
if (breaker.state === 'CLOSED' &&
breaker.failureCount >= breaker.failureThreshold) {
this.openCircuitBreaker(serviceId);
} else if (breaker.state === 'HALF_OPEN') {
this.openCircuitBreaker(serviceId);
}
} else {
// 成功响应,重置失败计数
if (breaker.state === 'HALF_OPEN') {
this.closeCircuitBreaker(serviceId);
} else {
breaker.failureCount = Math.max(0, breaker.failureCount - 1);
}
}
}
openCircuitBreaker(serviceId) {
const breaker = this.circuitBreakers.get(serviceId);
breaker.state = 'OPEN';
breaker.nextAttempt = Date.now() + breaker.timeout;
console.log(`Circuit breaker opened for service ${serviceId}`);
}
closeCircuitBreaker(serviceId) {
const breaker = this.circuitBreakers.get(serviceId);
breaker.state = 'CLOSED';
breaker.failureCount = 0;
console.log(`Circuit breaker closed for service ${serviceId}`);
}
}
OAuth 2.0实现:
JWT Token验证:
// JWT认证处理器
class JWTAuthenticator {
constructor(config) {
this.publicKey = config.publicKey;
this.algorithm = config.algorithm || 'RS256';
this.issuer = config.issuer;
this.audience = config.audience;
this.clockTolerance = config.clockTolerance || 60; // 60秒容错
}
async authenticate(token) {
try {
// 验证JWT令牌
const decoded = jwt.verify(token, this.publicKey, {
algorithms: [this.algorithm],
issuer: this.issuer,
audience: this.audience,
clockTolerance: this.clockTolerance
});
// 检查令牌是否在黑名单中
if (await this.isTokenBlacklisted(decoded.jti)) {
throw new Error('Token is blacklisted');
}
// 检查用户状态
if (decoded.sub && !await this.isUserActive(decoded.sub)) {
throw new Error('User is inactive');
}
return {
valid: true,
user: {
id: decoded.sub,
username: decoded.username,
email: decoded.email,
roles: decoded.roles || [],
permissions: decoded.permissions || [],
exp: decoded.exp,
iat: decoded.iat
}
};
} catch (error) {
return {
valid: false,
error: error.message
};
}
}
async isTokenBlacklisted(jti) {
if (!jti) return false;
// 检查Redis黑名单
const blacklisted = await redis.get(`blacklist:${jti}`);
return blacklisted === 'true';
}
async isUserActive(userId) {
// 检查用户状态
const user = await userService.getUser(userId);
return user && user.status === 'active';
}
async blacklistToken(jti, exp) {
if (!jti) return;
// 计算剩余有效时间
const now = Math.floor(Date.now() / 1000);
const ttl = exp - now;
if (ttl > 0) {
// 将令牌加入黑名单,直到过期
await redis.setex(`blacklist:${jti}`, ttl, 'true');
}
}
}
API Key管理:
// API Key认证处理器
class APIKeyAuthenticator {
constructor() {
this.keyStore = new Map();
this.rateLimits = new Map();
}
async generateAPIKey(clientId, config = {}) {
const apiKey = this.generateSecureKey();
const hashedKey = await this.hashKey(apiKey);
const keyInfo = {
clientId: clientId,
hashedKey: hashedKey,
createdAt: Date.now(),
expiresAt: config.expiresAt,
permissions: config.permissions || [],
rateLimit: config.rateLimit || { requests: 1000, window: 3600 },
status: 'active'
};
// 存储到数据库
await this.storeAPIKey(hashedKey, keyInfo);
return {
apiKey: apiKey,
keyId: hashedKey.substring(0, 8),
expiresAt: keyInfo.expiresAt
};
}
async authenticate(apiKey) {
try {
const hashedKey = await this.hashKey(apiKey);
const keyInfo = await this.getAPIKeyInfo(hashedKey);
if (!keyInfo) {
return { valid: false, error: 'Invalid API key' };
}
if (keyInfo.status !== 'active') {
return { valid: false, error: 'API key is disabled' };
}
if (keyInfo.expiresAt && Date.now() > keyInfo.expiresAt) {
return { valid: false, error: 'API key has expired' };
}
// 检查速率限制
const rateLimitResult = await this.checkRateLimit(hashedKey, keyInfo.rateLimit);
if (!rateLimitResult.allowed) {
return {
valid: false,
error: 'Rate limit exceeded',
retryAfter: rateLimitResult.retryAfter
};
}
return {
valid: true,
client: {
id: keyInfo.clientId,
permissions: keyInfo.permissions,
rateLimit: keyInfo.rateLimit
}
};
} catch (error) {
return { valid: false, error: error.message };
}
}
generateSecureKey() {
// 生成256位的安全密钥
const buffer = crypto.randomBytes(32);
return buffer.toString('base64url');
}
async hashKey(apiKey) {
// 使用SHA-256哈希API密钥
const hash = crypto.createHash('sha256');
hash.update(apiKey);
return hash.digest('hex');
}
async checkRateLimit(keyId, rateLimit) {
const window = rateLimit.window; // 时间窗口(秒)
const maxRequests = rateLimit.requests; // 最大请求数
const now = Math.floor(Date.now() / 1000);
const windowStart = now - (now % window);
const key = `ratelimit:${keyId}:${windowStart}`;
const currentRequests = await redis.incr(key);
if (currentRequests === 1) {
// 设置过期时间
await redis.expire(key, window);
}
if (currentRequests > maxRequests) {
const retryAfter = window - (now % window);
return { allowed: false, retryAfter: retryAfter };
}
return {
allowed: true,
remaining: maxRequests - currentRequests,
resetTime: windowStart + window
};
}
}
RBAC(基于角色的访问控制):
// RBAC权限控制系统
class RBACAuthorizationEngine {
constructor() {
this.roles = new Map();
this.permissions = new Map();
this.userRoles = new Map();
}
// 定义权限
definePermission(name, resource, action, conditions = {}) {
this.permissions.set(name, {
name: name,
resource: resource,
action: action,
conditions: conditions
});
}
// 定义角色
defineRole(name, permissions = []) {
this.roles.set(name, {
name: name,
permissions: new Set(permissions),
inherited: new Set()
});
}
// 角色继承
inheritRole(childRole, parentRole) {
const child = this.roles.get(childRole);
const parent = this.roles.get(parentRole);
if (child && parent) {
child.inherited.add(parentRole);
// 继承父角色的所有权限
for (const permission of parent.permissions) {
child.permissions.add(permission);
}
}
}
// 为用户分配角色
assignRole(userId, roleName) {
if (!this.userRoles.has(userId)) {
this.userRoles.set(userId, new Set());
}
this.userRoles.get(userId).add(roleName);
}
// 检查权限
checkPermission(userId, resource, action, context = {}) {
const userRoles = this.userRoles.get(userId);
if (!userRoles) {
return false;
}
// 收集用户的所有权限
const userPermissions = new Set();
for (const roleName of userRoles) {
const role = this.roles.get(roleName);
if (role) {
for (const permission of role.permissions) {
userPermissions.add(permission);
}
}
}
// 检查每个权限是否匹配
for (const permissionName of userPermissions) {
const permission = this.permissions.get(permissionName);
if (permission &&
this.matchResource(permission.resource, resource) &&
this.matchAction(permission.action, action) &&
this.evaluateConditions(permission.conditions, context)) {
return true;
}
}
return false;
}
matchResource(permissionResource, requestedResource) {
// 支持通配符匹配
if (permissionResource === '*') return true;
if (permissionResource === requestedResource) return true;
// 支持前缀匹配
if (permissionResource.endsWith('*')) {
const prefix = permissionResource.slice(0, -1);
return requestedResource.startsWith(prefix);
}
return false;
}
matchAction(permissionAction, requestedAction) {
if (permissionAction === '*') return true;
return permissionAction === requestedAction;
}
evaluateConditions(conditions, context) {
for (const [key, value] of Object.entries(conditions)) {
switch (key) {
case 'timeRange':
if (!this.checkTimeRange(value, context.timestamp)) {
return false;
}
break;
case 'ipRange':
if (!this.checkIPRange(value, context.clientIP)) {
return false;
}
break;
case 'userAttribute':
if (!this.checkUserAttribute(value, context.user)) {
return false;
}
break;
}
}
return true;
}
checkTimeRange(timeRange, timestamp) {
const now = timestamp || Date.now();
const currentHour = new Date(now).getHours();
return currentHour >= timeRange.start && currentHour <= timeRange.end;
}
checkIPRange(ipRange, clientIP) {
// 简单的IP范围检查实现
return ipRange.includes(clientIP);
}
checkUserAttribute(attribute, user) {
return user && user[attribute.key] === attribute.value;
}
}
// 使用示例
const rbac = new RBACAuthorizationEngine();
// 定义权限
rbac.definePermission('read_users', 'users', 'read');
rbac.definePermission('write_users', 'users', 'write');
rbac.definePermission('admin_all', '*', '*');
// 定义角色
rbac.defineRole('viewer', ['read_users']);
rbac.defineRole('editor', ['read_users', 'write_users']);
rbac.defineRole('admin', ['admin_all']);
// 分配角色
rbac.assignRole('user123', 'editor');
// 检查权限
const canRead = rbac.checkPermission('user123', 'users', 'read');
const canDelete = rbac.checkPermission('user123', 'users', 'delete');
安全中间件链:
// 安全中间件管理器
class SecurityMiddlewareChain {
constructor() {
this.middlewares = [];
}
use(middleware) {
this.middlewares.push(middleware);
}
async execute(request, response) {
let index = 0;
const next = async () => {
if (index >= this.middlewares.length) {
return; // 所有中间件执行完毕
}
const middleware = this.middlewares[index++];
await middleware(request, response, next);
};
await next();
}
}
// CORS中间件
function corsMiddleware(options = {}) {
const allowedOrigins = options.origins || ['*'];
const allowedMethods = options.methods || ['GET', 'POST', 'PUT', 'DELETE'];
const allowedHeaders = options.headers || ['Content-Type', 'Authorization'];
return async (request, response, next) => {
const origin = request.headers.origin;
// 检查Origin是否被允许
if (allowedOrigins.includes('*') || allowedOrigins.includes(origin)) {
response.setHeader('Access-Control-Allow-Origin', origin || '*');
}
response.setHeader('Access-Control-Allow-Methods', allowedMethods.join(', '));
response.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));
response.setHeader('Access-Control-Max-Age', '86400'); // 24小时
// 处理预检请求
if (request.method === 'OPTIONS') {
response.status(200).end();
return;
}
await next();
};
}
// CSRF防护中间件
function csrfMiddleware(options = {}) {
const tokenHeader = options.tokenHeader || 'x-csrf-token';
const cookieName = options.cookieName || 'csrf-token';
return async (request, response, next) => {
// 安全的HTTP方法不需要CSRF保护
if (['GET', 'HEAD', 'OPTIONS'].includes(request.method)) {
await next();
return;
}
const tokenFromHeader = request.headers[tokenHeader];
const tokenFromCookie = request.cookies[cookieName];
if (!tokenFromHeader || !tokenFromCookie || tokenFromHeader !== tokenFromCookie) {
response.status(403).json({ error: 'CSRF token mismatch' });
return;
}
await next();
};
}
// XSS防护中间件
function xssMiddleware(options = {}) {
return async (request, response, next) => {
// 设置XSS防护头
response.setHeader('X-XSS-Protection', '1; mode=block');
response.setHeader('X-Content-Type-Options', 'nosniff');
response.setHeader('X-Frame-Options', 'DENY');
// 清理请求数据
if (request.body) {
request.body = sanitizeObject(request.body);
}
if (request.query) {
request.query = sanitizeObject(request.query);
}
await next();
};
}
function sanitizeObject(obj) {
if (typeof obj === 'string') {
return sanitizeString(obj);
}
if (Array.isArray(obj)) {
return obj.map(item => sanitizeObject(item));
}
if (obj && typeof obj === 'object') {
const sanitized = {};
for (const [key, value] of Object.entries(obj)) {
sanitized[key] = sanitizeObject(value);
}
return sanitized;
}
return obj;
}
function sanitizeString(str) {
return str
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/\//g, '/');
}
// 使用示例
const securityChain = new SecurityMiddlewareChain();
securityChain.use(corsMiddleware({ origins: ['https://example.com'] }));
securityChain.use(csrfMiddleware());
securityChain.use(xssMiddleware());
滑动窗口限流:
// 滑动窗口限流算法
class SlidingWindowRateLimiter {
constructor(windowSize, maxRequests) {
this.windowSize = windowSize; // 窗口大小(毫秒)
this.maxRequests = maxRequests; // 最大请求数
this.windows = new Map(); // 存储每个键的窗口数据
}
isAllowed(key) {
const now = Date.now();
const windowStart = Math.floor(now / this.windowSize) * this.windowSize;
if (!this.windows.has(key)) {
this.windows.set(key, new Map());
}
const keyWindows = this.windows.get(key);
// 清理过期窗口
this.cleanupExpiredWindows(keyWindows, now);
// 获取当前窗口的请求计数
const currentCount = keyWindows.get(windowStart) || 0;
if (currentCount >= this.maxRequests) {
return {
allowed: false,
remaining: 0,
resetTime: windowStart + this.windowSize
};
}
// 增加计数
keyWindows.set(windowStart, currentCount + 1);
return {
allowed: true,
remaining: this.maxRequests - currentCount - 1,
resetTime: windowStart + this.windowSize
};
}
cleanupExpiredWindows(keyWindows, now) {
const cutoff = now - this.windowSize * 2; // 保留两个窗口的数据
for (const [windowStart] of keyWindows) {
if (windowStart < cutoff) {
keyWindows.delete(windowStart);
}
}
}
}
滑动日志限流:
// 滑动日志限流算法
class SlidingLogRateLimiter {
constructor(windowSize, maxRequests) {
this.windowSize = windowSize;
this.maxRequests = maxRequests;
this.logs = new Map();
}
isAllowed(key) {
const now = Date.now();
const windowStart = now - this.windowSize;
if (!this.logs.has(key)) {
this.logs.set(key, []);
}
const requestLog = this.logs.get(key);
// 移除窗口外的请求记录
while (requestLog.length > 0 && requestLog[0] <= windowStart) {
requestLog.shift();
}
if (requestLog.length >= this.maxRequests) {
return {
allowed: false,
remaining: 0,
oldestRequest: requestLog[0],
resetTime: requestLog[0] + this.windowSize
};
}
// 记录当前请求
requestLog.push(now);
return {
allowed: true,
remaining: this.maxRequests - requestLog.length,
oldestRequest: requestLog[0],
resetTime: requestLog[0] + this.windowSize
};
}
}
分布式限流(基于Redis):
// 基于Redis的分布式限流
class RedisRateLimiter {
constructor(redisClient, algorithm = 'sliding-window') {
this.redis = redisClient;
this.algorithm = algorithm;
}
async isAllowed(key, windowSize, maxRequests) {
switch (this.algorithm) {
case 'fixed-window':
return await this.fixedWindowLimiter(key, windowSize, maxRequests);
case 'sliding-window':
return await this.slidingWindowLimiter(key, windowSize, maxRequests);
case 'token-bucket':
return await this.tokenBucketLimiter(key, windowSize, maxRequests);
default:
throw new Error(`Unsupported algorithm: ${this.algorithm}`);
}
}
async fixedWindowLimiter(key, windowSize, maxRequests) {
const now = Date.now();
const window = Math.floor(now / windowSize);
const redisKey = `ratelimit:fixed:${key}:${window}`;
const multi = this.redis.multi();
multi.incr(redisKey);
multi.expire(redisKey, Math.ceil(windowSize / 1000));
const results = await multi.exec();
const currentRequests = results[0][1];
if (currentRequests > maxRequests) {
return {
allowed: false,
remaining: 0,
resetTime: (window + 1) * windowSize,
currentRequests: currentRequests
};
}
return {
allowed: true,
remaining: maxRequests - currentRequests,
resetTime: (window + 1) * windowSize,
currentRequests: currentRequests
};
}
async slidingWindowLimiter(key, windowSize, maxRequests) {
const now = Date.now();
const windowStart = now - windowSize;
const redisKey = `ratelimit:sliding:${key}`;
// 使用Lua脚本确保原子性
const luaScript = `
local key = KEYS[1]
local window_start = tonumber(ARGV[1])
local now = tonumber(ARGV[2])
local max_requests = tonumber(ARGV[3])
-- 移除窗口外的记录
redis.call('ZREMRANGEBYSCORE', key, 0, window_start)
-- 获取当前窗口内的请求数
local current_requests = redis.call('ZCARD', key)
if current_requests >= max_requests then
return {0, current_requests, 0}
end
-- 添加当前请求
redis.call('ZADD', key, now, now)
redis.call('EXPIRE', key, math.ceil(ARGV[4] / 1000))
return {1, current_requests + 1, max_requests - current_requests - 1}
`;
const result = await this.redis.eval(
luaScript,
1,
redisKey,
windowStart,
now,
maxRequests,
windowSize
);
return {
allowed: result[0] === 1,
currentRequests: result[1],
remaining: result[2],
resetTime: now + windowSize
};
}
async tokenBucketLimiter(key, refillRate, bucketSize) {
const now = Date.now();
const redisKey = `ratelimit:bucket:${key}`;
const luaScript = `
local key = KEYS[1]
local now = tonumber(ARGV[1])
local refill_rate = tonumber(ARGV[2])
local bucket_size = tonumber(ARGV[3])
local bucket = redis.call('HMGET', key, 'tokens', 'last_refill')
local tokens = tonumber(bucket[1]) or bucket_size
local last_refill = tonumber(bucket[2]) or now
-- 计算需要添加的令牌数
local time_passed = (now - last_refill) / 1000
local tokens_to_add = time_passed * refill_rate
tokens = math.min(bucket_size, tokens + tokens_to_add)
if tokens >= 1 then
tokens = tokens - 1
redis.call('HMSET', key, 'tokens', tokens, 'last_refill', now)
redis.call('EXPIRE', key, 3600)
return {1, math.floor(tokens)}
else
redis.call('HMSET', key, 'tokens', tokens, 'last_refill', now)
redis.call('EXPIRE', key, 3600)
return {0, 0}
end
`;
const result = await this.redis.eval(
luaScript,
1,
redisKey,
now,
refillRate,
bucketSize
);
return {
allowed: result[0] === 1,
remaining: result[1]
};
}
}
自适应限流:
// 自适应限流系统
class AdaptiveRateLimiter {
constructor(baseConfig) {
this.baseConfig = baseConfig;
this.metrics = new Map();
this.adjustmentHistory = [];
this.learningEnabled = true;
}
async adjustRateLimit(serviceId, metrics) {
const currentConfig = this.getCurrentConfig(serviceId);
const newConfig = await this.calculateOptimalConfig(serviceId, metrics, currentConfig);
if (this.shouldAdjust(currentConfig, newConfig, metrics)) {
await this.applyNewConfig(serviceId, newConfig);
this.recordAdjustment(serviceId, currentConfig, newConfig, metrics);
}
return newConfig;
}
async calculateOptimalConfig(serviceId, metrics, currentConfig) {
const {
responseTime,
errorRate,
cpuUsage,
memoryUsage,
queueLength,
throughput
} = metrics;
let adjustmentFactor = 1.0;
// 基于响应时间的调整
if (responseTime > currentConfig.targetResponseTime) {
const overageRatio = responseTime / currentConfig.targetResponseTime;
adjustmentFactor *= Math.max(0.7, 1 / overageRatio);
} else if (responseTime < currentConfig.targetResponseTime * 0.8) {
adjustmentFactor *= 1.1; // 可以适当增加限制
}
// 基于错误率的调整
if (errorRate > currentConfig.maxErrorRate) {
adjustmentFactor *= Math.max(0.5, 1 - errorRate);
}
// 基于系统负载的调整
const loadFactor = Math.max(cpuUsage, memoryUsage);
if (loadFactor > 0.8) {
adjustmentFactor *= Math.max(0.6, 1 - loadFactor);
}
// 基于队列长度的调整
if (queueLength > currentConfig.maxQueueLength) {
adjustmentFactor *= Math.max(0.8, currentConfig.maxQueueLength / queueLength);
}
const newRateLimit = Math.floor(currentConfig.rateLimit * adjustmentFactor);
return {
...currentConfig,
rateLimit: Math.max(currentConfig.minRateLimit,
Math.min(currentConfig.maxRateLimit, newRateLimit)),
adjustmentFactor: adjustmentFactor,
adjustedAt: Date.now()
};
}
shouldAdjust(currentConfig, newConfig, metrics) {
// 避免频繁调整
const timeSinceLastAdjustment = Date.now() - (currentConfig.adjustedAt || 0);
if (timeSinceLastAdjustment < 30000) { // 30秒内不重复调整
return false;
}
// 只有在显著变化时才调整
const changePercentage = Math.abs(
(newConfig.rateLimit - currentConfig.rateLimit) / currentConfig.rateLimit
);
return changePercentage > 0.1; // 变化超过10%才调整
}
recordAdjustment(serviceId, oldConfig, newConfig, metrics) {
this.adjustmentHistory.push({
serviceId: serviceId,
timestamp: Date.now(),
oldRateLimit: oldConfig.rateLimit,
newRateLimit: newConfig.rateLimit,
metrics: { ...metrics },
effectiveness: null // 稍后评估
});
// 保留最近的调整记录
if (this.adjustmentHistory.length > 1000) {
this.adjustmentHistory.shift();
}
// 延迟评估调整效果
setTimeout(() => {
this.evaluateAdjustmentEffectiveness(serviceId);
}, 60000); // 1分钟后评估
}
async evaluateAdjustmentEffectiveness(serviceId) {
const recentAdjustments = this.adjustmentHistory
.filter(adj => adj.serviceId === serviceId && !adj.effectiveness)
.slice(-5); // 最近5次调整
for (const adjustment of recentAdjustments) {
const beforeMetrics = adjustment.metrics;
const afterMetrics = await this.getMetrics(serviceId);
const improvement = this.calculateImprovement(beforeMetrics, afterMetrics);
adjustment.effectiveness = improvement;
// 如果调整效果不佳,学习调整策略
if (this.learningEnabled && improvement < 0) {
await this.adjustStrategy(adjustment);
}
}
}
calculateImprovement(before, after) {
// 计算多个指标的综合改善度
const responseTimeImprovement = (before.responseTime - after.responseTime) / before.responseTime;
const errorRateImprovement = (before.errorRate - after.errorRate) / Math.max(before.errorRate, 0.01);
const throughputImprovement = (after.throughput - before.throughput) / before.throughput;
// 加权计算总体改善度
return responseTimeImprovement * 0.4 + errorRateImprovement * 0.3 + throughputImprovement * 0.3;
}
}
智能熔断器:
// 智能熔断器实现
class IntelligentCircuitBreaker {
constructor(config) {
this.config = {
failureThreshold: config.failureThreshold || 5,
successThreshold: config.successThreshold || 3,
timeout: config.timeout || 60000,
monitoringWindow: config.monitoringWindow || 10000,
volumeThreshold: config.volumeThreshold || 10,
...config
};
this.state = 'CLOSED';
this.failureCount = 0;
this.successCount = 0;
this.nextAttempt = 0;
this.recentRequests = [];
this.metrics = {
totalRequests: 0,
totalFailures: 0,
averageResponseTime: 0,
lastFailureTime: 0
};
}
async execute(operation, fallback = null) {
if (!this.canExecute()) {
if (fallback) {
return await fallback();
}
throw new Error('Circuit breaker is open');
}
const startTime = Date.now();
try {
const result = await operation();
this.onSuccess(Date.now() - startTime);
return result;
} catch (error) {
this.onFailure(Date.now() - startTime, error);
throw error;
}
}
canExecute() {
const now = Date.now();
switch (this.state) {
case 'CLOSED':
return true;
case 'OPEN':
if (now >= this.nextAttempt) {
this.state = 'HALF_OPEN';
this.successCount = 0;
return true;
}
return false;
case 'HALF_OPEN':
return true;
default:
return false;
}
}
onSuccess(responseTime) {
this.metrics.totalRequests++;
this.updateAverageResponseTime(responseTime);
this.recordRequest(true, responseTime);
switch (this.state) {
case 'CLOSED':
this.resetFailureCount();
break;
case 'HALF_OPEN':
this.successCount++;
if (this.successCount >= this.config.successThreshold) {
this.closeCircuit();
}
break;
}
}
onFailure(responseTime, error) {
this.metrics.totalRequests++;
this.metrics.totalFailures++;
this.metrics.lastFailureTime = Date.now();
this.updateAverageResponseTime(responseTime);
this.recordRequest(false, responseTime, error);
switch (this.state) {
case 'CLOSED':
this.failureCount++;
if (this.shouldOpenCircuit()) {
this.openCircuit();
}
break;
case 'HALF_OPEN':
this.openCircuit();
break;
}
}
shouldOpenCircuit() {
// 检查请求量是否达到阈值
const recentRequests = this.getRecentRequests();
if (recentRequests.length < this.config.volumeThreshold) {
return false;
}
// 计算失败率
const failures = recentRequests.filter(req => !req.success).length;
const failureRate = failures / recentRequests.length;
return failureRate >= (this.config.failureThreshold / 100);
}
getRecentRequests() {
const now = Date.now();
const cutoff = now - this.config.monitoringWindow;
// 清理过期的请求记录
this.recentRequests = this.recentRequests.filter(
req => req.timestamp > cutoff
);
return this.recentRequests;
}
recordRequest(success, responseTime, error = null) {
this.recentRequests.push({
timestamp: Date.now(),
success: success,
responseTime: responseTime,
error: error ? error.message : null
});
// 限制记录数量
if (this.recentRequests.length > 1000) {
this.recentRequests.shift();
}
}
openCircuit() {
this.state = 'OPEN';
this.nextAttempt = Date.now() + this.config.timeout;
this.notifyStateChange('OPEN');
}
closeCircuit() {
this.state = 'CLOSED';
this.resetCounts();
this.notifyStateChange('CLOSED');
}
resetCounts() {
this.failureCount = 0;
this.successCount = 0;
}
resetFailureCount() {
this.failureCount = Math.max(0, this.failureCount - 1);
}
updateAverageResponseTime(responseTime) {
const alpha = 0.1; // 指数移动平均的平滑因子
this.metrics.averageResponseTime =
this.metrics.averageResponseTime * (1 - alpha) + responseTime * alpha;
}
notifyStateChange(newState) {
console.log(`Circuit breaker state changed to: ${newState}`);
// 这里可以添加监控通知逻辑
}
getMetrics() {
const recentRequests = this.getRecentRequests();
const recentFailures = recentRequests.filter(req => !req.success).length;
const failureRate = recentRequests.length > 0 ?
(recentFailures / recentRequests.length) * 100 : 0;
return {
state: this.state,
totalRequests: this.metrics.totalRequests,
totalFailures: this.metrics.totalFailures,
overallFailureRate: this.metrics.totalRequests > 0 ?
(this.metrics.totalFailures / this.metrics.totalRequests) * 100 : 0,
recentFailureRate: failureRate,
averageResponseTime: this.metrics.averageResponseTime,
lastFailureTime: this.metrics.lastFailureTime,
nextAttemptTime: this.nextAttempt
};
}
}
协议转换架构:
协议处理器实现:
// 协议转换管理器
class ProtocolConverter {
constructor() {
this.converters = new Map();
this.registerDefaultConverters();
}
registerDefaultConverters() {
this.register('http-to-grpc', new HTTPToGRPCConverter());
this.register('grpc-to-http', new GRPCToHTTPConverter());
this.register('websocket-to-http', new WebSocketToHTTPConverter());
this.register('graphql-to-rest', new GraphQLToRESTConverter());
}
register(name, converter) {
this.converters.set(name, converter);
}
async convert(fromProtocol, toProtocol, request, config = {}) {
const converterName = `${fromProtocol}-to-${toProtocol}`;
const converter = this.converters.get(converterName);
if (!converter) {
throw new Error(`No converter found for ${converterName}`);
}
return await converter.convert(request, config);
}
}
// HTTP到gRPC转换器
class HTTPToGRPCConverter {
constructor() {
this.protoRegistry = new Map();
}
loadProtoDefinition(serviceName, protoPath) {
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDefinition = protoLoader.loadSync(protoPath);
const proto = grpc.loadPackageDefinition(packageDefinition);
this.protoRegistry.set(serviceName, proto);
}
async convert(httpRequest, config) {
const { serviceName, methodName, serviceUrl } = config;
const proto = this.protoRegistry.get(serviceName);
if (!proto) {
throw new Error(`Proto definition not found for service: ${serviceName}`);
}
// 创建gRPC客户端
const ServiceClient = proto[serviceName];
const client = new ServiceClient(serviceUrl, grpc.credentials.createInsecure());
// 转换HTTP请求到gRPC消息
const grpcMessage = this.convertHTTPToGRPCMessage(httpRequest);
return new Promise((resolve, reject) => {
client[methodName](grpcMessage, (error, response) => {
if (error) {
reject(this.convertGRPCErrorToHTTPError(error));
} else {
resolve(this.convertGRPCResponseToHTTPResponse(response));
}
});
});
}
convertHTTPToGRPCMessage(httpRequest) {
// 从HTTP请求中提取参数
const params = {
...httpRequest.query,
...httpRequest.body
};
// 根据proto定义转换数据类型
return this.transformDataTypes(params);
}
transformDataTypes(data) {
const transformed = {};
for (const [key, value] of Object.entries(data)) {
if (typeof value === 'string' && /^\d+$/.test(value)) {
transformed[key] = parseInt(value);
} else if (typeof value === 'string' && /^\d+\.\d+$/.test(value)) {
transformed[key] = parseFloat(value);
} else if (value === 'true' || value === 'false') {
transformed[key] = value === 'true';
} else {
transformed[key] = value;
}
}
return transformed;
}
convertGRPCResponseToHTTPResponse(grpcResponse) {
return {
status: 200,
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(grpcResponse)
};
}
convertGRPCErrorToHTTPError(grpcError) {
const statusMap = {
0: 200, // OK
1: 499, // CANCELLED
2: 500, // UNKNOWN
3: 400, // INVALID_ARGUMENT
4: 504, // DEADLINE_EXCEEDED
5: 404, // NOT_FOUND
6: 409, // ALREADY_EXISTS
7: 403, // PERMISSION_DENIED
8: 429, // RESOURCE_EXHAUSTED
9: 400, // FAILED_PRECONDITION
10: 409, // ABORTED
11: 416, // OUT_OF_RANGE
12: 501, // UNIMPLEMENTED
13: 500, // INTERNAL
14: 503, // UNAVAILABLE
15: 500, // DATA_LOSS
16: 401 // UNAUTHENTICATED
};
const httpStatus = statusMap[grpcError.code] || 500;
return {
status: httpStatus,
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
error: grpcError.message,
code: grpcError.code,
details: grpcError.details
})
};
}
}
// WebSocket到HTTP转换器
class WebSocketToHTTPConverter {
constructor() {
this.connections = new Map();
this.messageQueue = new Map();
}
async convert(wsMessage, config) {
const { targetUrl, method = 'POST', headers = {} } = config;
// 解析WebSocket消息
const messageData = this.parseWebSocketMessage(wsMessage);
// 转换为HTTP请求
const httpRequest = {
method: method,
url: targetUrl,
headers: {
'content-type': 'application/json',
...headers
},
body: JSON.stringify(messageData.payload)
};
// 发送HTTP请求
const response = await this.sendHTTPRequest(httpRequest);
// 转换响应为WebSocket消息
return this.convertHTTPResponseToWSMessage(response, messageData.id);
}
parseWebSocketMessage(message) {
try {
const data = JSON.parse(message);
return {
id: data.id || this.generateMessageId(),
type: data.type || 'request',
payload: data.payload || data
};
} catch (error) {
return {
id: this.generateMessageId(),
type: 'request',
payload: { message: message }
};
}
}
convertHTTPResponseToWSMessage(httpResponse, messageId) {
return JSON.stringify({
id: messageId,
type: 'response',
status: httpResponse.status,
payload: httpResponse.body
});
}
generateMessageId() {
return Math.random().toString(36).substring(2) + Date.now().toString(36);
}
async sendHTTPRequest(request) {
// 实现HTTP请求发送逻辑
const fetch = require('node-fetch');
const response = await fetch(request.url, {
method: request.method,
headers: request.headers,
body: request.body
});
const body = await response.text();
return {
status: response.status,
headers: Object.fromEntries(response.headers.entries()),
body: body
};
}
}
// GraphQL到REST转换器
class GraphQLToRESTConverter {
constructor() {
this.schemaMapping = new Map();
}
registerSchema(schemaName, mapping) {
this.schemaMapping.set(schemaName, mapping);
}
async convert(graphqlQuery, config) {
const { schemaName } = config;
const mapping = this.schemaMapping.get(schemaName);
if (!mapping) {
throw new Error(`Schema mapping not found: ${schemaName}`);
}
// 解析GraphQL查询
const parsedQuery = this.parseGraphQLQuery(graphqlQuery);
// 转换为REST调用
const restCalls = this.convertToRESTCalls(parsedQuery, mapping);
// 并行执行REST调用
const results = await Promise.all(
restCalls.map(call => this.executeRESTCall(call))
);
// 合并结果
return this.mergeResults(results, parsedQuery);
}
parseGraphQLQuery(query) {
// 简化的GraphQL解析器
const lines = query.trim().split('\n');
const operation = lines[0].trim();
const fields = [];
for (let i = 1; i < lines.length; i++) {
const line = lines[i].trim();
if (line && !line.startsWith('{') && !line.startsWith('}')) {
fields.push(line.replace(/[,{}]/g, '').trim());
}
}
return {
operation: operation,
fields: fields
};
}
convertToRESTCalls(parsedQuery, mapping) {
const calls = [];
for (const field of parsedQuery.fields) {
const restMapping = mapping.fields[field];
if (restMapping) {
calls.push({
field: field,
url: restMapping.url,
method: restMapping.method || 'GET',
headers: restMapping.headers || {}
});
}
}
return calls;
}
async executeRESTCall(call) {
const fetch = require('node-fetch');
const response = await fetch(call.url, {
method: call.method,
headers: call.headers
});
const data = await response.json();
return {
field: call.field,
data: data
};
}
mergeResults(results, parsedQuery) {
const merged = {};
for (const result of results) {
merged[result.field] = result.data;
}
return {
data: merged
};
}
}
通用数据转换器:
// 数据格式转换器
class DataFormatConverter {
constructor() {
this.converters = new Map();
this.validators = new Map();
this.registerDefaultConverters();
}
registerDefaultConverters() {
this.register('json-to-xml', new JSONToXMLConverter());
this.register('xml-to-json', new XMLToJSONConverter());
this.register('json-to-yaml', new JSONToYAMLConverter());
this.register('yaml-to-json', new YAMLToJSONConverter());
this.register('csv-to-json', new CSVToJSONConverter());
this.register('json-to-protobuf', new JSONToProtobufConverter());
}
register(name, converter) {
this.converters.set(name, converter);
}
async convert(fromFormat, toFormat, data, schema = null) {
const converterName = `${fromFormat}-to-${toFormat}`;
const converter = this.converters.get(converterName);
if (!converter) {
throw new Error(`No converter found for ${converterName}`);
}
// 验证输入数据
if (schema) {
await this.validateData(data, schema, fromFormat);
}
const result = await converter.convert(data);
// 验证输出数据
if (schema && schema.output) {
await this.validateData(result, schema.output, toFormat);
}
return result;
}
async validateData(data, schema, format) {
const validator = this.validators.get(format);
if (validator) {
const isValid = await validator.validate(data, schema);
if (!isValid) {
throw new Error(`Data validation failed for format: ${format}`);
}
}
}
}
// JSON到XML转换器
class JSONToXMLConverter {
convert(jsonData) {
return this.jsonToXml(jsonData, 'root');
}
jsonToXml(obj, rootName) {
let xml = `<${rootName}>`;
if (Array.isArray(obj)) {
for (const item of obj) {
xml += this.jsonToXml(item, 'item');
}
} else if (typeof obj === 'object' && obj !== null) {
for (const [key, value] of Object.entries(obj)) {
if (Array.isArray(value)) {
for (const item of value) {
xml += this.jsonToXml(item, key);
}
} else if (typeof value === 'object' && value !== null) {
xml += this.jsonToXml(value, key);
} else {
xml += `<${key}>${this.escapeXml(value)}${key}>`;
}
}
} else {
xml += this.escapeXml(obj);
}
xml += `${rootName}>`;
return xml;
}
escapeXml(unsafe) {
if (unsafe === null || unsafe === undefined) {
return '';
}
return unsafe.toString()
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
}
// XML到JSON转换器
class XMLToJSONConverter {
convert(xmlData) {
const xml2js = require('xml2js');
const parser = new xml2js.Parser({
explicitArray: false,
mergeAttrs: true,
normalizeTags: true
});
return new Promise((resolve, reject) => {
parser.parseString(xmlData, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
}
// 数据模式验证器
class DataSchemaValidator {
constructor() {
this.schemas = new Map();
}
registerSchema(name, schema) {
this.schemas.set(name, schema);
}
async validateJSON(data, schemaName) {
const Ajv = require('ajv');
const ajv = new Ajv();
const schema = this.schemas.get(schemaName);
if (!schema) {
throw new Error(`Schema not found: ${schemaName}`);
}
const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) {
return {
valid: false,
errors: validate.errors
};
}
return { valid: true };
}
async validateXML(xmlData, xsdSchema) {
const libxml = require('libxmljs');
try {
const xmlDoc = libxml.parseXml(xmlData);
const xsdDoc = libxml.parseXml(xsdSchema);
const isValid = xmlDoc.validate(xsdDoc);
return {
valid: isValid,
errors: isValid ? [] : xmlDoc.validationErrors
};
} catch (error) {
return {
valid: false,
errors: [{ message: error.message }]
};
}
}
}
自动内容协商实现:
// 内容协商处理器
class ContentNegotiator {
constructor() {
this.supportedFormats = new Map();
this.defaultFormat = 'application/json';
this.registerDefaultFormats();
}
registerDefaultFormats() {
this.supportedFormats.set('application/json', {
name: 'JSON',
parser: this.parseJSON,
serializer: this.serializeJSON,
quality: 1.0
});
this.supportedFormats.set('application/xml', {
name: 'XML',
parser: this.parseXML,
serializer: this.serializeXML,
quality: 0.9
});
this.supportedFormats.set('text/yaml', {
name: 'YAML',
parser: this.parseYAML,
serializer: this.serializeYAML,
quality: 0.8
});
this.supportedFormats.set('text/csv', {
name: 'CSV',
parser: this.parseCSV,
serializer: this.serializeCSV,
quality: 0.7
});
}
negotiate(request) {
const acceptHeader = request.headers.accept || this.defaultFormat;
const contentTypeHeader = request.headers['content-type'];
return {
requestFormat: this.parseContentType(contentTypeHeader),
responseFormat: this.selectBestFormat(acceptHeader),
charset: this.parseCharset(acceptHeader),
encoding: this.parseEncoding(request.headers['accept-encoding'])
};
}
selectBestFormat(acceptHeader) {
const acceptedTypes = this.parseAcceptHeader(acceptHeader);
let bestFormat = null;
let bestQuality = 0;
for (const acceptedType of acceptedTypes) {
const format = this.supportedFormats.get(acceptedType.type);
if (format && acceptedType.quality > bestQuality) {
bestFormat = acceptedType.type;
bestQuality = acceptedType.quality;
}
}
return bestFormat || this.defaultFormat;
}
parseAcceptHeader(acceptHeader) {
const types = acceptHeader.split(',');
const parsed = [];
for (const type of types) {
const parts = type.trim().split(';');
const mediaType = parts[0].trim();
let quality = 1.0;
for (let i = 1; i < parts.length; i++) {
const param = parts[i].trim();
if (param.startsWith('q=')) {
quality = parseFloat(param.substring(2)) || 1.0;
}
}
parsed.push({
type: mediaType,
quality: quality
});
}
return parsed.sort((a, b) => b.quality - a.quality);
}
parseContentType(contentTypeHeader) {
if (!contentTypeHeader) return this.defaultFormat;
const parts = contentTypeHeader.split(';');
return parts[0].trim();
}
parseCharset(acceptHeader) {
const charsetRegex = /charset=([^;,\s]+)/i;
const match = acceptHeader.match(charsetRegex);
return match ? match[1] : 'utf-8';
}
parseEncoding(acceptEncodingHeader) {
if (!acceptEncodingHeader) return null;
const encodings = acceptEncodingHeader.split(',')
.map(enc => enc.trim())
.filter(enc => enc !== 'identity');
return encodings.length > 0 ? encodings[0] : null;
}
async convertRequest(request, targetFormat) {
const sourceFormat = this.parseContentType(request.headers['content-type']);
if (sourceFormat === targetFormat) {
return request.body;
}
const sourceHandler = this.supportedFormats.get(sourceFormat);
const targetHandler = this.supportedFormats.get(targetFormat);
if (!sourceHandler || !targetHandler) {
throw new Error(`Unsupported format conversion: ${sourceFormat} -> ${targetFormat}`);
}
// 解析源格式
const data = await sourceHandler.parser(request.body);
// 转换为目标格式
return await targetHandler.serializer(data);
}
async convertResponse(data, targetFormat) {
const handler = this.supportedFormats.get(targetFormat);
if (!handler) {
throw new Error(`Unsupported response format: ${targetFormat}`);
}
return await handler.serializer(data);
}
// 格式解析器和序列化器
parseJSON(data) {
return JSON.parse(data);
}
serializeJSON(data) {
return JSON.stringify(data, null, 2);
}
parseXML(data) {
const xml2js = require('xml2js');
const parser = new xml2js.Parser();
return new Promise((resolve, reject) => {
parser.parseString(data, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
}
serializeXML(data) {
const xml2js = require('xml2js');
const builder = new xml2js.Builder();
return builder.buildObject(data);
}
parseYAML(data) {
const yaml = require('js-yaml');
return yaml.load(data);
}
serializeYAML(data) {
const yaml = require('js-yaml');
return yaml.dump(data);
}
parseCSV(data) {
const Papa = require('papaparse');
const result = Papa.parse(data, {
header: true,
dynamicTyping: true
});
return result.data;
}
serializeCSV(data) {
const Papa = require('papaparse');
return Papa.unparse(data);
}
}
(未完,下一篇续)
关键词:API网关、微服务架构、服务治理、性能优化、安全认证、负载均衡、监控运维、云原生、数字化转型