วิธีส่งวัตถุ json ที่มีขนาดใหญ่มากเป็นการตอบกลับ - node.js พร้อม express

ฉันได้รับข้อผิดพลาดนี้ FATAL ERROR: JS Allocation failed - process out of memory และได้ระบุแล้วว่าเป็นปัญหาที่ฉันส่งออบเจ็กต์ json ที่มีขนาดใหญ่มากไปที่ res.json (หรือ JSON.stringify) เพื่อให้บริบทแก่คุณ โดยพื้นฐานแล้วฉันจะส่งไฟล์กำหนดค่าประมาณ 30,000 ไฟล์ (ไฟล์กำหนดค่าแต่ละไฟล์มี ประมาณ 10,000 บรรทัด) เป็นวัตถุ json หนึ่งรายการ

คำถามของฉันคือมีวิธีส่งวัตถุ json ขนาดใหญ่เช่นนี้หรือมีวิธีที่ดีกว่าในการสตรีมมัน (เช่นใช้ socket.io หรือไม่)

ฉันใช้: โหนด v0.10.33, [email protected]

อัปเดต: โค้ดตัวอย่าง

var app = express();

app.route('/events')
.get(function(req, res, next) {
  var configdata = [{config:<10,000 lines of config>}, ... 10,000 configs]
  res.json(configdata); // The out of memory error comes here
})

person abarik    schedule 12.05.2015    source แหล่งที่มา
comment
คุณช่วยยกตัวอย่างโค้ดเล็กน้อยได้ไหม?   -  person Evan Hahn    schedule 13.05.2015
comment
ฉันได้เพิ่มโค้ดตัวอย่างโค้ดแล้ว   -  person abarik    schedule 13.05.2015
comment
แน่นอนว่าคำตอบคือไม่ต้องส่งไฟล์ปรับแต่งครั้งละ 30,000 ไฟล์ใช่ไหม นี่คือกลิ่นรหัส แม้แต่การดาวน์โหลด json 1 ครั้งที่มี 10,000 บรรทัดก็ยังเยอะมาก   -  person BenjaminPaul    schedule 13.05.2015
comment
ใช่ ฉันเห็นด้วย... มันเป็นการออกแบบโค้ดที่ไม่ดี ฉันได้แก้ไขด้วย socket.io เพื่อสตรีมไฟล์ปรับแต่งแทนที่จะส่งทั้งหมดในครั้งเดียว   -  person abarik    schedule 13.05.2015
comment
เนื่องจากฉันกำลังจัดเก็บไฟล์กำหนดค่าแต่ละไฟล์เป็นรายการ db ฉันจึงไม่สามารถสตรีมทีละบรรทัดได้ บวกกับการอ่านบทความนี้ ฉันเห็นว่า 10,000 บรรทัดในไฟล์ปรับแต่งเดียวสามารถอ่านทั้งหมดในคราวเดียวได้ josh.zeigler.us/technology/web-development/   -  person abarik    schedule 13.05.2015


คำตอบ (3)


หลังจากลองมาหลายครั้ง ในที่สุดฉันก็ตัดสินใจใช้ socket.io เพื่อส่งไฟล์ปรับแต่งแต่ละไฟล์ในแต่ละครั้ง แทนที่จะส่งไฟล์ปรับแต่งทั้งหมดในคราวเดียว วิธีนี้ช่วยแก้ปัญหาหน่วยความจำไม่เพียงพอซึ่งทำให้เซิร์ฟเวอร์ของฉันเสียหาย ขอบคุณสำหรับความช่วยเหลือทั้งหมดของคุณ

person abarik    schedule 13.05.2015

ลองใช้สตรีมครับ สิ่งที่คุณต้องการคือสตรีมที่อ่านได้ซึ่งสร้างข้อมูลตามความต้องการ ฉันจะเขียนโค้ดแบบง่ายที่นี่:

var Readable = require('stream').Readable;
var rs = Readable();

rs._read = function () {
    // assuming 10000 lines of config fits in memory
    rs.push({config:<10,000 lines of config>);
};

rs.pipe(res);
person Magomogo    schedule 14.05.2015

คุณสามารถลองเพิ่มโหนดหน่วยความจำได้ด้วย ธง --max_old_space_size บนบรรทัดคำสั่ง

อาจมีวิธีแก้ปัญหาที่หรูหรากว่านี้ ปฏิกิริยาแรกของฉันคือการแนะนำให้ใช้ res.json() กับวัตถุ Buffer แทนที่จะพยายามส่งวัตถุทั้งหมดทั้งหมดในช็อตเดียว แต่แล้วฉันก็รู้ว่าอะไรก็ตามที่แปลงเป็น JSON อาจจะต้องการใช้วัตถุทั้งหมดพร้อมกัน ดังนั้นคุณจะมีหน่วยความจำไม่เพียงพอแม้ว่าคุณจะเปลี่ยนไปใช้สตรีมก็ตาม หรืออย่างน้อยนั่นคือสิ่งที่ฉันคาดหวัง

person Trott    schedule 12.05.2015
comment
ฉันสามารถรวมไฟล์ปรับแต่งได้ครั้งละหนึ่งไฟล์อย่างแน่นอน และนั่นก็โอเค ปัญหาเกิดขึ้นเมื่อฉันลองสตริงไฟล์ปรับแต่ง 10,000 ไฟล์ (ไฟล์ปรับแต่งแต่ละไฟล์มี 10,000 ไลค์) คุณช่วยชี้ให้ฉันดูตัวอย่างการใช้วัตถุบัฟเฟอร์ได้ไหม ไม่อย่างนั้น ฉันคิดว่าฉันจะใช้วิธีสตรีมมิ่ง socket.io... - person abarik; 13.05.2015