특정 Azure 계정의 모든 blob 컨테이너에있는 모든 blob을 다운로드하는 백업 스크립트를 작성하고 있습니다.노드 js azure SDK getBlobToStream은 많은 양의 메모리를 사용합니다.
스크립트는 async.js를 사용하여 너무 많은 스레드 만 동시에 실행되어 서버에 과부하가 걸리지 않도록합니다. 이 스크립트를 실행하면 잘 작동하지만 큰 파일에 도달하면 메모리가 부족합니다. 나는 디스크가 쓸 수있는 것보다 빠르게 다운로드가 실행되는 것을 추측하고 있으며, 결국 메모리상의 버퍼를 가득 채우며 메모리를 완전히 소모하지만 정확한 원인을 디버깅하는 것은 지금까지 불가능했습니다.
다음과 같이 많은 메모리가 호출 사용 나타나는 특정 기능 :
blobService.getBlobToStream(
containerName,
blob.name,
fs.createWriteStream(fullPath),
function(error) {
if(error){ //Something went wrong, write it to the console but finish the queue item and continue.
console.log("Failed writing " + blob.name + " (" + error + ")");
callback();
}
else if(!error) { //Write the last modified date and finish the queue item silently
fs.writeFile(fullPath + ".date", blobLastModified, function(err)
{ if(err) console.log("Couldn't write .date file: " + err); });
callback();
}
});
심지어 하나의 700메가바이트 다운로드 쉽게 내 옆에 1GB 메모리를 채울 것입니다.
이 문제가 발생합니까? Azure SDK가 모든 것을 버퍼링하고 부엌 싱크대를 마술처럼 막는 매개 변수가 누락 되었습니까?
전체 코드 : 당신이 가능하게 스트림 대신 전체 BLOB 데이터에 데이터의 덩어리를 읽을 할 수
#!/usr/bin/env node
//Requires
var azure = require('azure');
var fs = require('fs');
var mkdirp = require('mkdirp');
var path = require('path');
var async = require('async');
var maxconcurrency = 1; //Max amount of simultaneous running threads of getBlobsAndSaveThem() running through async.js.
var blobService = azure.createBlobService();
backupPrefix='/backups/azurebackup/' //Always end with a '/'!!
//Main flow of the script is near the bottom of the file.
var containerProcessingQueue = async.queue(
function getBlobsAndSaveThem(containerName) {
console.log(containerName); //DEBUG
blobService.listBlobs(containerName,
function(error, blobs) {
if(!error){
var blobProcessingQueue =
async.queue(function(index,callback) {
var blob = blobs[index];
console.log(blob); //DEBUG
var fullPath = backupPrefix + containerName + '/' + blob.name;
var blobLastModified = new Date(blob.properties['last-modified']);
//Only create if the directoy doesn't exist, since mkdirp fails if the directory exists.
if(!fs.existsSync(path.dirname(fullPath))){ //And do it sync, because otherwise it'll check 99999 times if the directory exists simultaneously, doesn't find it, then fails to create it 99998 times.
mkdirp.sync(path.dirname(fullPath), function(err) { console.log('Failed to create directory ' + path.dirname(fullPath) + " ("+ err + ")"); });
}
if(fs.existsSync(fullPath + ".date")){
if(blobLastModified == fs.readFileSync(fullPath + ".date").toString()) {
callback();
return; //If the file is unmodified, return. No this won't exit the program, because it's called within a function definition (async.queue(function ...))
}
}
blobService.getBlobToStream(
containerName,
blob.name,
fs.createWriteStream(fullPath),
function(error) {
if(error){ //Something went wrong, write it to the console but finish the queue item and continue.
console.log("Failed writing " + blob.name + " (" + error + ")");
callback();
}
else if(!error) { //Write the last modified date and finish the queue item silently
fs.writeFile(fullPath + ".date", blobLastModified, function(err)
{ if(err) console.log("Couldn't write .date file: " + err); });
callback();
}
});
},maxconcurrency);
for(var blobindex in blobs){
blobProcessingQueue.push(blobindex);
} //Push new items to the queue for processing
}
else {
console.log("An error occurred listing the blobs: " + error);
}
});
},1);
blobService.listContainers(function(err, result){
for(var i=0;i<result.length;i++) {
containerProcessingQueue.push(result[i].name);
}
});
마침내이 작업을 시도했습니다. 그리고 그것은 작동합니다! 메모리 사용량은 30 ~ 40MB 정도로 훨씬 낮아 보인다. 실제로 모든 것을 메모리에 넣으려고 시도한 것 같다. 이 예제 코드를 가져 주셔서 감사합니다! 그것은 꽤 많이 일했습니다 :) –