У нас есть большой файл размером около 6 ГБ, который распакован до размера 64 ГБ (образ ОС), который нам нужно загрузить с помощью http.Мы используем либо библиотеку запросов узла, либо axios.Файл загружается и распаковывается (передается по каналу) на лету, используя следующий код:
const downloadUsingHttp = (downloadUrl, destinationPath) => {enter code here
return new Promise((resolve, reject) => {
const unpackedPathWriteStream = fs.createWriteStream(destinationPath);
let totalDownloadSize = 64023257088;
let downloadedSize = 0;
let lastProgressSent = 0;
axios({
method: 'get',
url: downloadUrl,
responseType: 'stream',
auth: {
username: 'user',
password: 'pass'
},
withCredentials: true
}).then(function (response) {
response.data
.on('data', chunk => {
if (totalDownloadSize === 0) {
return;
}
downloadedSize += chunk.length;
const progress = Math.floor((downloadedSize / totalDownloadSize) * 100);
if (progress % 5 !== 0) {
return;
}
if (lastProgressSent === progress) {
return;
}
lastProgressSent = progress;
console.log('Copy progress ', progress + ' %')
})
.pipe(zlib.createUnzip())
.pipe(unpackedPathWriteStream)
}).catch((err) => {
console.log(err.message)
});
unpackedPathWriteStream
.on('error', err => {
console.log(err);
reject(err);
}).on('end', () => {
resolve();
})
})
};
downloadUsingHttp(
'https://example.com/storage/file.raw.gz',
'/data/downloaded-and-unziped.raw'
);
На компьютере, на котором запущен этот код, имеется 2 ГБ ОЗУ.Когда этот код запускается, возникает проблема, связанная с тем, что машине не хватает оперативной памяти, при прогрессе около 15% и сбое приложения узла.Иногда даже вся машина перестает отвечать на запросы и требует перезагрузки.
Таким образом, похоже, что обработка обратного давления , реализованная через .pipe () для потоков, в этом случае не работает.Например, если не загружать файл через http (с помощью библиотеки запросов или axios), но делать это с читаемыми и записываемыми потоками, выполнять те же операции копирования и распаковки на лету с использованием метода pipe и не происходит исчерпание памяти.
Также важно упомянуть, что эта проблема возникает только при выполнении загрузки по http в локальной сети (локальная среда разработки).
Любая помощь будет оценена.
Обновление
Мы пытались дросселировать поток до 100 КБ / с, и, похоже, он работает в условиях, когда не было увеличенного использования памяти RAM.При изменении на 1 МБ / с использование увеличивается и в конечном итоге приложение тормозит.Мы использовали библиотеку stream-throttle
, чтобы попробовать это.