Redis использует 100% CPU после 6 часов безотказной работы - PullRequest
1 голос
/ 19 февраля 2020

enter image description here

Как видно на изображении выше, у меня возникают проблемы с производительностью 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);
                });
            });
        });
    });
}

Вот обзор хода выполнения того, что происходит в хронологическом порядке, когда пользователь пытается получить доступ к этому маршруту:

  1. Пользователь загружает веб-страницу индекса (по умолчанию). На этой странице может быть более 20 строк, для которых необходимо выполнить 20 запросов API от удаленного API (одна из причин, по которой я кеширую это).
  2. Проверить, не кэширован ли пользователь уже в redis
  3. Проверить, для указанного пользователя Steam существует ключ истечения срока действия (даже если он не существует).
  4. Если кеш существует и был извлечен менее чем за 15 минут go, отобразить результат из кэша Redis.
  5. Если кеша не существует, мы запрашиваем удаленный API.
  6. Если запрос был успешным, кешируем данные в Redis и возвращаем ответ.

По какой-то причине это получает захваченный сам по себе и через некоторое время работы Redis использует так много процессора и оперативной памяти, что это безумие, и я подумал, что справляюсь с этим должным образом.

Я также очищаю ВСЕ кеш один раз в день, используя скрипт оболочки и crontab.

redis-cli KEYS "steam_user*" | xargs redis-cli DEL

Почему он продолжает использовать больше ЦП и ОЗУ (даже если посетителей буквально нет, и я боюсь думать, что произойдет, если будет много посетителей), и как могу я работать вокруг этой проблемы, чтобы исправить это?

1 Ответ

2 голосов
/ 20 февраля 2020

Процесс, который использует все ваши ресурсы - это / tmp / kdevtmpfsi. Быстрый поиск в Google показал, что это майнинг вредоносных программ. Это означает, что ни в Redis, ни в вашей программе нет какой-то ошибки. Этот комментарий к Github объясняет, как от него избавиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...