mongoose / mongodb DoS-атака на экземпляр nodeJS [закрыто]

У нас есть экземпляр nodeJS внутри AWS VPC, который делает запрос экземпляру mongodb, работающему в другой зоне доступности.

Экземпляр узла получает много запросов . Этот запрос используется для получения большого количества информации из экземпляра mongodb. После первого запроса эта запись кешируется в течение определенного периода времени.

Вчера что-то произошло с объемом возвращаемых данных. С таким кодом, как:

 console.log('before retrieve');
 Model.find({}).exec(function() {
   console.log('after retrieve');
 });

If 10 раз ударил бы «до получения», а затем просто остановился бы, DoS-ing сам. Я удалил некоторые данные, которые он извлекал, в качестве временного исправления.

На стороне mongoDB я иногда видел:

 SocketException handling request, closing client connection: 9001 socket exception [SEND_ERROR]

Как я могу этого избежать?

0
задан 13 April 2014 в 00:15
1 ответ

Проблема, которую вы описываете, имеет гораздо меньшее отношение к mongoose, mongodb и node, а скорее является проявлением проблемы, обычно называемой «паническое бегство в тайнике» или «собачья куча». 1279] Как следует из названия, кеш-память возникает, когда целая куча вещей пытается обновить кеш одновременно. В вашем случае это происходит по истечении срока действия кеша или во время начальной загрузки данных в кеш. Внезапно приходит множество запросов и накладывает большую нагрузку на чтение вашей базы данных, что 1) приводит к медленному обновлению кеша и 2) вызывает еще большее количество запросов, которые складываются в ожидании кеша. Это в основном приводит к тому поведению, которое вы видели, когда все просто падает

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

Один из методов, который я использовал в прошлом, заключается в использовании двух ключей кэша с истекающим сроком действия, один ключ используется только для указания того, когда следует обновить кеш, а другой содержит фактические данные.

Для иллюстрации, предположим, есть объект foo , который я хочу кэшировать и срок действия которого истекает каждый час. Я могу создать еще один ключ foo_refresh , срок действия которого истекает за 1 минуту до ключа foo .

Когда истекает срок действия ключа foo_refresh , один рабочий / запрос немедленно заменяет foo_refresh ключ и игнорирует кеш и вместо этого извлекает данные из базы данных, обновление ключа foo по завершении (также сбрасывает время истечения срока действия). Используя подобный механизм, мы получаем своего рода «блокировку» при обновлении кеша, что означает, что не более одного рабочего будет когда-либо выполнять дорогостоящее чтение.

Предполагая, что обновление кеша занимает менее 1 минуты, ] foo никогда не истекает, вместо этого он обновляется по истечении срока действия ключа foo_refresh .

Надеюсь, это поможет!

3
ответ дан 4 December 2019 в 12:32

Теги

Похожие вопросы