เพื่อนที่ใช้ nodejs ทุกคนรู้ว่าโหนดเป็นเธรดเดี่ยวซึ่งหมายความว่าเมื่อทำงานบนซีพียู 8 คอร์คุณสามารถใช้พลังการคำนวณของคอร์เดียวเท่านั้น
เธรดเดี่ยวเป็นคำวิจารณ์ของโหนดเสมอ แต่ด้วยการแนะนำของคลัสเตอร์ในเวอร์ชัน 0.6 สถานการณ์นี้เปลี่ยนไป นักพัฒนาสามารถพึ่งพาคลัสเตอร์เพื่อขยายเซิร์ฟเวอร์โหนดไปยังเซิร์ฟเวอร์แบบมัลติเธรดได้อย่างง่ายดาย
คลัสเตอร์คืออะไร
คลัสเตอร์เป็นไลบรารีมัลติเธรดที่จัดทำโดยโหนด ผู้ใช้สามารถใช้เพื่อสร้างหลายเธรด เธรดแบ่งปันพอร์ตการฟัง เมื่อมีคำขอภายนอกไปยังพอร์ตนี้คลัสเตอร์จะส่งต่อคำขอไปยังเธรดแบบสุ่ม เนื่องจากแต่ละเธรดโหนดจะครอบครองหน่วยความจำหลายสิบเมกะไบต์จึงเป็นไปไม่ได้ที่จะสร้างเธรดสำหรับแต่ละคำขอเช่น PHP โดยทั่วไปจำนวนเธรดที่สร้างขึ้นจะไม่เกินจำนวนคอร์ CPU มากที่สุด
การคัดลอกรหัสมีดังนี้:
var cluster = ต้องการ ('คลัสเตอร์');
var http = ต้องการ ('http');
var numcpus = ต้องการ ('os'). cpus (). ความยาว;
if (Cluster.ismaster) {
// คนงานส้อม
สำหรับ (var i = 0; i <numcpus; i ++) {
cluster.fork ();
-
Cluster.on ('Exit', function (คนงาน, รหัส, สัญญาณ) {
console.log ('Worker' + Worker.process.pid + 'Die');
-
} อื่น {
// คนงานสามารถแบ่งปันการเชื่อมต่อ TCP ใด ๆ
// ในกรณีนี้เป็นเซิร์ฟเวอร์ HTTP
http.createserver (ฟังก์ชั่น (req, res) {
Res.writehead (200);
Res.end ("Hello World/N");
}). ฟัง (8000);
-
ดังที่แสดงในรหัสข้างต้น Cluster.ismaster จะถูกตั้งค่าเป็น TRUE เมื่อโปรแกรมกำลังทำงาน หลังจากโทรหา cluster.fork () โปรแกรมจะสร้างเธรดและเรียกใช้อีกครั้ง ในเวลานี้ Cluster.ismaster จะถูกตั้งค่าเป็นเท็จ เราใช้ตัวแปรนี้เป็นหลักเพื่อตรวจสอบว่าเธรดปัจจุบันเป็นของเธรดลูกหรือไม่
นอกจากนี้ยังสามารถสังเกตได้ว่าหลังจากสร้างเธรดเด็กแต่ละตัวมันจะฟังพอร์ต 8000 โดยไม่ก่อให้เกิดความขัดแย้ง นี่คือฟังก์ชั่นของพอร์ตที่ใช้ร่วมกันของคลัสเตอร์
การสื่อสารระหว่างเธรด
เมื่อเธรดถูกสร้างขึ้นพวกเขาจะไม่แชร์หน่วยความจำหรือข้อมูลซึ่งกันและกัน การแลกเปลี่ยนข้อมูลทั้งหมดสามารถประมวลผลได้ในเธรดหลักผ่าน Worker.Send และ Worker.on ('ข้อความ', Handler) รายการต่อไปนี้แสดงตัวอย่างของระบบออกอากาศ
การคัดลอกรหัสมีดังนี้:
var cluster = ต้องการ ('คลัสเตอร์');
var http = ต้องการ ('http');
var numcpus = ต้องการ ('os'). cpus (). ความยาว;
if (Cluster.ismaster) {
var workers = [];
// สร้างคนงานใหม่
ฟังก์ชั่น newworker () {
var worker = cluster.fork ();
// ฟังข้อมูล หากประเภทออกอากาศจะถูกกำหนดว่าเป็นการออกอากาศ
Worker.on ('ข้อความ', ฟังก์ชั่น (msg) {
if (msg.type == 'ออกอากาศ') {
เหตุการณ์ var = msg.event;
// ส่งการออกอากาศนี้ไปยังคนงานทั้งหมด
Workers.foreach (ฟังก์ชั่น (คนงาน) {
Worker.Send (เหตุการณ์);
-
-
-
คนงานกลับ;
-
สำหรับ (var i = 0; i <numcpus; i ++) {
Workers.push (Newworker ());
-
Cluster.on ('ออนไลน์', ฟังก์ชั่น (คนงาน) {
console.log ('คนงาน %d เป็นออนไลน์', worker.id);
-
} อื่น {
var worker = cluster.worker;
// การออกอากาศคือการส่งข้อความที่มีการออกอากาศประเภทเหตุการณ์คือเนื้อหาออกอากาศ
Worker.broadcast = function (เหตุการณ์) {
Worker.Send ({
ประเภท: 'ออกอากาศ',
กิจกรรม: เหตุการณ์
-
-
// นี่เป็นไปไม่ได้ที่จะฟังข้อมูลที่ส่งคืนโดยใช้คนงานที่นี่
process.on ('ข้อความ', ฟังก์ชั่น (เหตุการณ์) {
console.log ('คนงาน:'+worker.id+'เหตุการณ์กู้คืนจาก'+event.workerid);
-
// ส่งออกอากาศ
Worker.broadcast ({
ข้อความ: 'ออนไลน์',
WorkerId: คนงาน
-
-
ปัญหาที่ต้องระวัง
นอกจากนี้ยังกล่าวถึงข้างต้นว่าไม่สามารถใช้ข้อมูลระหว่างเธรดและการแลกเปลี่ยนข้อมูลทั้งหมดสามารถแลกเปลี่ยนผ่านการสื่อสารระหว่างเธรดเท่านั้น ยิ่งไปกว่านั้นข้อมูลที่แลกเปลี่ยนนั้นสามารถส่งต่อได้ดังนั้นฟังก์ชั่นตัวบ่งชี้ไฟล์และ HttPresponse ไม่สามารถส่งผ่านได้
หากคุณใช้คลัสเตอร์คุณต้องพิจารณาปัญหาการแลกเปลี่ยนข้อมูลเมื่อออกแบบโปรแกรม วิธีการของฉันเองคือการจัดเก็บข้อมูลทั้งหมดที่คล้ายกับเซสชันใน Redis และแต่ละเธรดจะทำงานที่เก็บและการถอนและข้อมูลทั้งหมดไม่ได้อยู่ในหน่วยความจำโหนด
จุดสุดท้ายในปัจจุบันคลัสเตอร์ถูกทำเครื่องหมายอย่างเป็นทางการว่าเป็นการทดลองโดยโหนดและ API อาจเปลี่ยนแปลงในอนาคต