[ โพสต์นี้เป็นข้อมูลล่าสุด ณ วันที่ 2012-09-02 (ใหม่กว่าด้านบน) ]
Node.js ปรับขนาดบนเครื่องมัลติคอร์อย่างแน่นอน
ใช่ Node.js เป็นหนึ่งเธรดต่อกระบวนการ นี่คือการตัดสินใจออกแบบโดยเจตนาและไม่จำเป็นต้องจัดการกับความหมายการล็อก หากคุณไม่เห็นด้วยกับสิ่งนี้คุณอาจยังไม่เข้าใจว่าการดีบักโค้ดแบบมัลติเธรดนั้นเป็นเรื่องยากเพียงใด สำหรับคำอธิบายลึกของรูปแบบกระบวนการ Node.js และทำไมมันทำงานด้วยวิธีนี้ (และทำไมมันจะไม่สนับสนุนหลายหัวข้อ) อ่านโพสต์อื่น ๆ ของฉัน
ดังนั้นฉันจะใช้ประโยชน์จากกล่อง 16 core ของฉันได้อย่างไร
สองทาง:
- สำหรับงานที่ต้องคำนวณหนัก ๆ ขนาดใหญ่เช่นการเข้ารหัสภาพ Node.js สามารถเปิดไฟกระบวนการเด็กหรือส่งข้อความไปยังกระบวนการผู้ปฏิบัติงานเพิ่มเติม ในการออกแบบนี้คุณจะต้องมีหนึ่งเธรดที่จัดการโฟลว์ของเหตุการณ์และกระบวนการ N ที่ทำงานหนักในการคำนวณและเคี้ยวซีพียูอีก 15 ตัว
- สำหรับการปรับปริมาณงานบนเว็บเซอร์วิซคุณควรรันเซิร์ฟเวอร์ Node.js หลายเครื่องในหนึ่งกล่องหนึ่งตัวต่อคอร์และแยกการรับส่งข้อมูลระหว่างคำขอ สิ่งนี้จะให้ CPU-affinity ที่ยอดเยี่ยมและจะขยายสเกลความเร็วเกือบเป็นเส้นตรงด้วยการนับคอร์
ปรับขนาดปริมาณงานบนเว็บเซอร์
ตั้งแต่ v6.0.X Node.js ได้รวมโมดูลคลัสเตอร์โดยตรงจากกล่องซึ่งทำให้ง่ายต่อการตั้งค่าตัวทำงานของโหนดหลายตัวที่สามารถฟังในพอร์ตเดียว หมายเหตุว่านี้ไม่ได้เช่นเดียวกับพี่ learnboost "คลัสเตอร์" โมดูลพร้อมใช้งานผ่านNPM
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
http.Server(function(req, res) { ... }).listen(8000);
}
คนงานจะแข่งขันเพื่อยอมรับการเชื่อมต่อใหม่และกระบวนการที่โหลดน้อยที่สุดมีแนวโน้มที่จะชนะมากที่สุด มันทำงานได้ค่อนข้างดีและสามารถเพิ่มปริมาณงานได้ค่อนข้างดีบนกล่องแบบมัลติคอร์
หากคุณมีภาระมากพอที่จะใส่ใจกับหลายคอร์แล้วคุณจะต้องทำสิ่งต่าง ๆ เพิ่มเติม:
เรียกใช้บริการ Node.js ของคุณหลังเว็บพร็อกซีเช่นNginxหรือApache - สิ่งที่สามารถทำการควบคุมปริมาณการเชื่อมต่อ (ยกเว้นกรณีที่คุณต้องการให้เงื่อนไขโอเวอร์โหลดนำกล่องลงมาอย่างสมบูรณ์) เขียน URL ใหม่ให้บริการเนื้อหาคงที่และพร็อกซีย่อยบริการอื่น ๆ
รีไซเคิลกระบวนการทำงานของคุณเป็นระยะ สำหรับกระบวนการที่ใช้เวลานานแม้กระทั่งหน่วยความจำขนาดเล็กก็จะรั่วไหลในที่สุด
ตั้งค่าการรวบรวม / การตรวจสอบบันทึก
ป.ล. : มีการพูดคุยกันระหว่างแอรอนกับคริสโตเฟอร์ในความคิดเห็นของโพสต์อื่น ความคิดเห็นบางประการเกี่ยวกับเรื่องนี้:
- โมเดลซ็อกเก็ตที่ใช้ร่วมกันนั้นสะดวกมากสำหรับการอนุญาตให้กระบวนการหลาย ๆ ฟังบนพอร์ตเดียวและแข่งขันเพื่อยอมรับการเชื่อมต่อใหม่ ตามแนวคิดคุณอาจนึกถึง Apache แบบ preforked ทำสิ่งนี้กับข้อแม้ที่สำคัญว่าแต่ละขั้นตอนจะยอมรับการเชื่อมต่อเพียงครั้งเดียวและจากนั้นก็ตาย การสูญเสียประสิทธิภาพสำหรับ Apache อยู่ในค่าใช้จ่ายของการฟอร์กกระบวนการใหม่และไม่มีอะไรเกี่ยวข้องกับการดำเนินการซ็อกเก็ต
- สำหรับ Node.js การมีพนักงาน N คนแข่งขันกันในซ็อกเก็ตเดียวเป็นโซลูชั่นที่เหมาะสมอย่างยิ่ง อีกทางเลือกหนึ่งคือการตั้งค่า Front-end แบบ on-box เช่น Nginx และมีทราฟฟิกพร็อกซีนั้นไปยังพนักงานแต่ละคน โซลูชันทั้งสองมีคุณลักษณะด้านประสิทธิภาพที่คล้ายคลึงกันมาก และเนื่องจากอย่างที่ฉันได้กล่าวไว้ข้างต้นคุณอาจต้องการใช้ Nginx (หรือทางเลือก) ที่บังหน้าบริการโหนดของคุณอย่างไรก็ตามตัวเลือกที่นี่อยู่ระหว่าง:
พอร์ตที่ใช้ร่วมกัน: nginx (port 80) --> Node_workers x N (sharing port 3000 w/ Cluster)
VS
พอร์ตส่วนบุคคล: nginx (port 80) --> {Node_worker (port 3000), Node_worker (port 3001), Node_worker (port 3002), Node_worker (port 3003) ...}
มีประโยชน์บางอย่างในการตั้งค่าพอร์ตแต่ละพอร์ต (อาจมีข้อต่อระหว่างกระบวนการน้อยกว่ามีการตัดสินใจในการทำโหลดบาลานซ์ที่ซับซ้อนมากขึ้นเป็นต้น) แต่ก็เป็นงานที่ต้องตั้งค่ามากขึ้นและโมดูลคลัสเตอร์ในตัวนั้นต่ำ - ทางเลือกที่ซับซ้อนที่เหมาะกับคนส่วนใหญ่