-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcache.js
More file actions
152 lines (130 loc) · 3.78 KB
/
cache.js
File metadata and controls
152 lines (130 loc) · 3.78 KB
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/**
* MCP 代理服务器缓存管理模块
* 提供智能缓存策略,提升响应速度
*/
const NodeCache = require('node-cache');
const crypto = require('crypto');
class CacheManager {
constructor() {
// 初始化缓存实例
this.cache = new NodeCache({
stdTTL: 300, // 默认 TTL 5分钟
checkperiod: 60, // 每分钟检查过期键
useClones: false, // 性能优化:不克隆对象
maxKeys: 1000 // 最大缓存键数量
});
// 不同方法的缓存时间配置(秒)
this.cacheTTL = {
'initialize': 600, // 初始化缓存 10分钟
'tools/list': 300, // 工具列表缓存 5分钟
'tools/call': 0 // 工具调用不缓存
};
// 缓存统计
this.stats = {
hits: 0,
misses: 0,
sets: 0
};
}
/**
* 生成缓存键
* @param {string} serverId - 服务器 ID
* @param {Object} mcpRequest - MCP 请求对象
* @returns {string} 缓存键
*/
generateCacheKey(serverId, mcpRequest) {
const { method, params } = mcpRequest;
const paramsHash = params ?
crypto.createHash('md5').update(JSON.stringify(params)).digest('hex') :
'no-params';
return `${serverId}:${method}:${paramsHash}`;
}
/**
* 检查是否应该缓存该方法
* @param {string} method - MCP 方法名
* @returns {boolean} 是否应该缓存
*/
shouldCache(method) {
const ttl = this.cacheTTL[method];
return ttl !== undefined && ttl > 0;
}
/**
* 获取方法的缓存 TTL
* @param {string} method - MCP 方法名
* @returns {number} TTL(秒)
*/
getCacheTTL(method) {
return this.cacheTTL[method] || 0;
}
/**
* 从缓存获取数据
* @param {string} serverId - 服务器 ID
* @param {Object} mcpRequest - MCP 请求对象
* @returns {Object|null} 缓存的响应或 null
*/
get(serverId, mcpRequest) {
if (!this.shouldCache(mcpRequest.method)) {
return null;
}
const key = this.generateCacheKey(serverId, mcpRequest);
const cached = this.cache.get(key);
if (cached) {
this.stats.hits++;
console.log(`缓存命中: ${key}`);
return cached;
}
this.stats.misses++;
return null;
}
/**
* 设置缓存数据
* @param {string} serverId - 服务器 ID
* @param {Object} mcpRequest - MCP 请求对象
* @param {Object} response - 响应数据
*/
set(serverId, mcpRequest, response) {
if (!this.shouldCache(mcpRequest.method)) {
return;
}
// 只缓存成功的响应
if (response.error) {
return;
}
const key = this.generateCacheKey(serverId, mcpRequest);
const ttl = this.getCacheTTL(mcpRequest.method);
this.cache.set(key, response, ttl);
this.stats.sets++;
console.log(`缓存设置: ${key}, TTL: ${ttl}秒`);
}
/**
* 清除特定服务器的所有缓存
* @param {string} serverId - 服务器 ID
*/
clearServerCache(serverId) {
const keys = this.cache.keys();
const serverKeys = keys.filter(key => key.startsWith(serverId + ':'));
serverKeys.forEach(key => this.cache.del(key));
console.log(`清除服务器 ${serverId} 的 ${serverKeys.length} 个缓存项`);
}
/**
* 获取缓存统计信息
* @returns {Object} 缓存统计
*/
getStats() {
const hitRate = this.stats.hits + this.stats.misses > 0 ?
(this.stats.hits / (this.stats.hits + this.stats.misses) * 100).toFixed(2) : 0;
return {
...this.stats,
hitRate: `${hitRate}%`,
keys: this.cache.keys().length
};
}
/**
* 清除所有缓存
*/
clearAll() {
this.cache.flushAll();
console.log('已清除所有缓存');
}
}
module.exports = CacheManager;