2017-01-10 9 views
0

Используя Node, Express, MongoDB и Mongoose, я пытаюсь передать потенциально большое количество объектов (100K +) клиенту.Сервер узла останавливает прием соединений после потоковой передачи большого ответа

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

Мысли о том, что может произойти? Мысли о лучшем способе отладки?

Вот мой код:

res.writeHead(200, { 'Content-Type': 'application/json' }); 
res.write('{"meta":{"code":200},"objects":['); 

Object 
    .find({ foo: 'bar' }) 
    .sort({ createdAt: -1 }) 
    .lean() 
    .cursor() 
    .on('error', function (err) { 
    console.error(err); 
    res.end(); 
    }) 
    .on('data', function (object) { 
    if (!first) 
     res.write(','); 
    else 
     first = false; 

    res.write(JSON.stringify(object)); 
    }) 
    .on('close', function() { 
    res.end(']}'); 
    }); 

Edit:

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

Error: write after end 
    at ServerResponse.write (_http_outgoing.js:443:15) 
    at QueryCursor.<anonymous> (<redacted>/server/models/object.js:431:11) 
    at emitOne (events.js:96:13) 
    at QueryCursor.emit (events.js:188:7) 
    at QueryCursor.Readable.read (_stream_readable.js:381:10) 
    at flow (_stream_readable.js:761:34) 
    at emitReadable_ (_stream_readable.js:433:3) 
    at wrapped (<redacted>/node_modules/newrelic/lib/transaction/tracer/index.js:183:28) 
    at _combinedTickCallback (internal/process/next_tick.js:71:11) 
    at process._tickDomainCallback [as _tickCallback] (internal/process/next_tick.js:122:9) 

Edit 2:

Я никогда полностью не докопался до этого, но я подозреваю, что сервер удушья пытается JSON сериализации огромного количества записей. Я закончил с другим решением, сделав несколько запросов с постраничным доступом от клиента, а не сразу загружая записи. Смотри ниже.

+2

Здесь потенциально много чего происходит. У вас есть какой-то способ узнать, где он может застрять? Небольшое количество записей, связанных с различными шагами, может помочь определить, где проблема. – tadman

+0

Да, я посыпал некоторые каротажи. Отчасти проблема заключается в том, что запрос успешно завершается. Это просто последующие запросы, которые не работают, и я не знаю, почему. Это похоже на то, что сервер даже не принимает соединение. – nickpatrick

+0

Если вы застряли в главном цикле событий по какой-то причине, это поведение, которое вы увидите, все приложение перестает принимать соединения или создает выходные данные. Возможно, у вас есть действительно сумасшедшая самореферентная структура данных, с которой не может справиться стриптизатор JSON, хотя он должен предупредить вас, если это так. – tadman

ответ

0

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