Redis публиковать утечки памяти? - PullRequest
0 голосов
/ 27 декабря 2018

Я знаю, что таких вопросов уже много, но я не нашел такой, который соответствовал бы моей реализации.Я использую redis в окружении Node.js, и кажется, что redis.publish теряет память.Я ожидаю, что это будет что-то вроде «противодавления», как показано здесь: Node redis издатель, потребляющий слишком много памяти

Но, насколько я понимаю: Node должен снять такое давление всинхронный контекст, иначе цикл событий узла не будет вызван, и GC также не будет вызван.

Моя программа выглядит так:

const websocketApi = new WebsocketApi()
const currentState = {}

websocketApi.connect()
websocketApi.on('open', () => {
  channels.map((channel) => websocketApi.subscribeChannel(channel))
})

websocketApi.on('message', (message) => {
  const ob = JSON.parse(message)

  if (currentState[ob.id]) {
    currentState[ob.id] = update(currentState[ob.id], ob.data)
  } else {
    currentState[ob.id] = ob.data
  }

  const payload = {
    channel: ob.id,
    info: currentState[ob.id],
    timestamp: Date.now(),
    type: 'newData'
  }
  // when i remove this part, the memory is stable
  redisClient.publish(payload.channel, JSON.stringify(payload))
})
// to reconnect in case of error
websocketApi.on('close', () =>
  websocketApi.connect())

Кажется, чтосообщения расположены слишком близко друг к другу, поэтому у него нет времени, чтобы освободить строки, удерживаемые в redis.publish.

Есть ли у вас какие-либо представления о том, что не так в этом коде?

РЕДАКТИРОВАТЬ: более конкретно, что я могу наблюдать, когда я делаю дамп памяти моего приложения:

  • Память заполнена строкой, которые являются моими полезными нагрузками Stringified JSON, и "кусками"сообщения, которые отправляются через сам Redis.Их ссылка хранится внутри клиента redis в переменных, называемых чанком.Некоторые строковые данные по-прежнему освобождаются, но я создаю их намного быстрее.

  • Когда я не публикую сообщения через Redis, переменная "currentState" будет расти до тех пор, пока не произойдет точкарасти больше.Очевидно, это сильно влияет на оперативную память, но это ожидаемо.В остальном все в порядке, и приложение стабильно около 400 МБ, и оно взрывается, когда издатель Redis (PM2 перезапускает его, потому что он достигает максимальной емкости ОЗУ)

  • Мне кажется, что я спрашиваю Redisопубликовать больше, чем он может обработать, и Redis не имеет времени, чтобы закончить публиковать сообщения.Он по-прежнему содержит весь контекст, поэтому ничего не выпускает.Мне может понадобиться какая-то «очередь», чтобы позволить redis освободить некоторый контекст и завершить публикацию сообщений.Это действительно возможность, или я схожу с ума?

По сути, каждый цикл в моей программе "независим".Можно ли иметь столько клиентов Redis, сколько у меня есть петли?это лучшая идея?(ИМХО, узел однопоточный, поэтому это не поможет, но может помочь V8 лучше отслеживать ссылки на память и освобождать память)

1 Ответ

0 голосов
/ 27 декабря 2018

Клиент redis буферизует команды, если клиент не подключен либо потому, что он еще не подключен, либо его подключение не установлено, либо не удается подключиться.

Убедитесь, что вы можете подключиться к серверу Redis.Убедитесь, что ваша программа подключена к серверу.Я бы предложил добавить прослушиватель к redisClient.on('connect'), если он не передан, клиент никогда не подключался.

Если вы подключены, клиент не должен буферизовать, но чтобы проблема появилась раньше, отключите автономную очередь,передать параметр enable_offline_queue: false в createClient, это приведет к попыткам отправки команд, если не подключен сбой.

Вы должны подключить прослушиватель ошибок к redisClient: redisClient.on('error', console.error.bind(console)).Это может привести к сообщению о том, почему клиент выполняет буферизацию.

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