【发布时间】:2020-06-04 02:29:03
【问题描述】:
如上图所示,我在 Redis 运行一段时间后遇到了性能问题;特别是 6 小时。
我正在使用 Redis 缓存来自 API 的响应,因此我不必在每个请求上重新获取数十行,我想 - 嘿,这应该可行。显然没有。
module.exports = (app, csrfProtection, jsonParser) => {
app.get("/api/steam/getPlayerSummaries", [steamRateLimits.getPlayerSummaries, jsonParser, csrfProtection], async(req, res) => {
redisClient.hmget("steam_user", req.query.steamids, (err, reply) => {
if(err) return res.status(500).send({ message: `Could not read from Redis with error ${err}`});
redisClient.hmget(`steam_user_expires_${req.query.steamids}`, "expires", (err, expire) => {
if(err) return res.status(500).send({ message: `Could not read from Redis with error ${err}`});
if(reply[0] && (CURRENT_UNIX_TIME - expire < REDIS_EXPIRE_LIMIT)) return res.status(200).send(JSON.parse(reply));
const queryParams = querystring.stringify({
key: process.env.STEAM_API_KEY,
steamids: req.query.steamids
}),
options = {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
};
http.get(`http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?${queryParams}`, options, response => {
const { statusCode } = response;
if(statusCode != 200) {
response.resume();
return res.status(statusCode).send({ message: `Could not fetch Steam API getPlayerSummaries with status code ${statusCode}`});
}
response.setEncoding("utf8");
let rawData = "";
response.on("data", chunk => rawData += chunk);
response.on("end", _ => {
try {
const parsedData = JSON.parse(rawData);
redisClient.hmset(["steam_user", req.query.steamids, rawData]);
redisClient.hmset([`steam_user_expires_${req.query.steamids}`, "expires", CURRENT_UNIX_TIME]);
return res.status(200).send(parsedData);
} catch (e) {
console.error(e.message);
}
});
}).on("error", e => {
console.error(`Got error: ${e.message}`);
return res.status(500).send(e);
});
});
});
});
}
以下是用户尝试访问此路线时按时间顺序发生的进度概览:
- 用户加载索引(默认)网页。这个页面可以有20多个 需要从远程 API 运行 20 个 API 查询的行(其中一个 我缓存这个的原因)。
- 检查用户是否已经缓存在redis中
- 检查是否存在上述 Steam 用户的过期密钥(即使不存在)。
- 如果缓存存在并且它是在不到 15 分钟前提取的,则显示来自 Redis 缓存的结果。
- 如果缓存不存在,我们会查询远程 API。
- 如果请求成功,将数据缓存到 Redis 并返回响应。
由于某种原因,这本身就陷入了困境,并且在运行 Redis 一段时间后使用了如此多的 CPU 和 RAM,这太疯狂了,我认为我处理得当。
我还使用 shell 脚本和 crontab 每天清除一次所有缓存。
redis-cli KEYS "steam_user*" | xargs redis-cli DEL
为什么它会继续消耗更多的 CPU 和 RAM(即使实际上没有访客,而且我不敢想象如果有很多访客会发生什么),我该如何解决这个问题修复它?
【问题讨论】:
标签: javascript node.js redis