วิธีการทำงานของแบบจำลองการไม่บล็อก IO แบบเธรดเดี่ยวใน Node.js


325

ฉันไม่ใช่โปรแกรมเมอร์ของ Node แต่ฉันสนใจที่การทำงานของIO แบบเธรดเดียวที่ไม่บล็อก หลังจากที่ฉันอ่านบทความการทำความเข้าใจ - the-node-js-event-loopฉันสับสนจริง ๆ มันเป็นตัวอย่างสำหรับแบบจำลอง:

c.query(
   'SELECT SLEEP(20);',
   function (err, results, fields) {
     if (err) {
       throw err;
     }
     res.writeHead(200, {'Content-Type': 'text/html'});
     res.end('<html><head><title>Hello</title></head><body><h1>Return from async DB query</h1></body></html>');
     c.end();
    }
);

Que:เมื่อมีสองคำร้องขอ A (มาก่อน) และ B เนื่องจากมีเพียงเธรดเดียวโปรแกรมฝั่งเซิร์ฟเวอร์จะจัดการคำร้องขอ A ประการแรก: การทำแบบสอบถาม SQL คือคำสั่ง asleep ที่รอ I / O รออยู่ และโปรแกรมติดค้างอยู่ที่การI/Oรอคอยและไม่สามารถรันโค้ดที่แสดงหน้าเว็บด้านหลังได้ โปรแกรมจะสลับเพื่อขอ B ในระหว่างรอหรือไม่ ในความเห็นของฉันเนื่องจากรูปแบบเธรดเดียวไม่มีวิธีสลับหนึ่งคำขอจากอีกแบบ แต่ชื่อของโค้ดตัวอย่างที่บอกว่าทุกอย่างที่วิ่งขนานยกเว้นรหัสของคุณ

(PS ฉันไม่แน่ใจว่าฉันเข้าใจรหัสผิดหรือไม่ตั้งแต่ฉันไม่เคยใช้ Node) วิธีที่โหนดสลับ A เป็น B ระหว่างที่รออยู่ และคุณสามารถอธิบายแบบจำลองเธรดเดียวที่ไม่บล็อก IOของโหนดด้วยวิธีง่ายๆได้หรือไม่? ฉันจะขอบคุณถ้าคุณสามารถช่วยฉัน :)

คำตอบ:


374

Node.js สร้างขึ้นบนlibuvซึ่งเป็นไลบรารีข้ามแพลตฟอร์มที่เป็นนามธรรม apis / syscalls สำหรับอินพุต / เอาต์พุตแบบอะซิงโครนัส (ไม่ปิดกั้น) ที่จัดเตรียมโดยระบบปฏิบัติการที่รองรับ (Unix, OS X และ Windows อย่างน้อย)

Asynchronous IO

ในรูปแบบการเขียนโปรแกรมการดำเนินการนี้เปิด / อ่าน / เขียนบนอุปกรณ์และทรัพยากร (ซ็อกเก็ตระบบไฟล์ ฯลฯ ) ที่จัดการโดยระบบไฟล์จะไม่บล็อกเธรดการโทร (เช่นเดียวกับในรูปแบบซิงโครนัสทั่วไป) และเพียงแค่ทำเครื่องหมาย กระบวนการ (ในโครงสร้างข้อมูลระดับเคอร์เนล / OS) ที่จะได้รับแจ้งเมื่อมีข้อมูลหรือเหตุการณ์ใหม่ ในกรณีของแอพที่คล้ายกับเว็บเซิร์ฟเวอร์กระบวนการนั้นจะต้องรับผิดชอบในการพิจารณาว่าคำขอ / บริบทใดที่เหตุการณ์แจ้งเตือนเป็นของและดำเนินการตามคำขอจากที่นั่น โปรดทราบว่านี่จะหมายความว่าคุณจะอยู่ในกรอบสแต็กที่แตกต่างจากเฟรมที่มาจากการร้องขอไปยังระบบปฏิบัติการเนื่องจากหลังต้องส่งไปยังโปรแกรมเลือกจ่ายงานของกระบวนการเพื่อให้กระบวนการเธรดเดี่ยวจัดการกับเหตุการณ์ใหม่

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

โมเดลของโหนด (รูปแบบการส่งต่อและห่วงเหตุการณ์)

โหนดแก้ปัญหาการใช้ประโยชน์จากคุณสมบัติของภาษาจาวาสคริปต์เพื่อทำให้รูปแบบนี้ดูซิงโครนัสมากขึ้นโดยการชักจูงโปรแกรมเมอร์ให้ใช้รูปแบบการเขียนโปรแกรมบางอย่าง ทุกฟังก์ชั่นที่ร้องขอ IO มีลายเซ็นที่ต้องการfunction (... parameters ..., callback)และจำเป็นต้องได้รับการติดต่อกลับที่จะถูกเรียกใช้เมื่อการดำเนินการที่ร้องขอเสร็จสมบูรณ์ (โปรดทราบว่าเวลาส่วนใหญ่ที่ใช้ในการรอให้ระบบปฏิบัติการส่งสัญญาณความสมบูรณ์ - เวลาที่ ใช้เวลาทำงานอื่น ๆ ) การสนับสนุนของ Javascript สำหรับการปิดช่วยให้คุณใช้ตัวแปรที่คุณกำหนดไว้ในฟังก์ชั่นด้านนอก (การโทร) ภายในเนื้อความของการเรียกกลับ - ซึ่งจะช่วยให้สถานะระหว่างฟังก์ชั่นต่างๆที่จะถูกเรียกใช้โดยโหนดรันไทม์อิสระ ดูเพิ่มเติมต่อเนื่องสไตล์ผ่าน

นอกจากนี้หลังจากการเรียกฟังก์ชั่นการดำเนินการวางไข่ IO ฟังก์ชั่นการโทรมักจะreturnควบคุมไปยังโหนดของห่วงเหตุการณ์ การวนซ้ำนี้จะเรียกใช้การเรียกกลับหรือฟังก์ชันถัดไปที่กำหนดไว้สำหรับการดำเนินการ (ส่วนใหญ่เนื่องจากเหตุการณ์ที่เกี่ยวข้องได้รับแจ้งจากระบบปฏิบัติการ) - ช่วยให้การประมวลผลพร้อมกันของการร้องขอหลายรายการพร้อมกัน

คุณสามารถนึกถึงเหตุการณ์วนรอบของโหนดที่ค่อนข้างคล้ายกับตัวแจกจ่ายของเคอร์เนล : เคอร์เนลจะกำหนดเวลาสำหรับการดำเนินการเธรดที่ถูกบล็อกเมื่อ IO ที่ค้างอยู่เสร็จสมบูรณ์ในขณะที่โหนดจะกำหนดเวลาการเรียกกลับเมื่อเหตุการณ์ที่เกี่ยวข้องเกิดขึ้น

พร้อมกันสูงไม่มีการขนาน

เป็นคำพูดสุดท้ายวลี "ทุกอย่างทำงานในแบบขนานยกเว้นรหัสของคุณ" ทำหน้าที่ได้ดีในการจับจุดที่โหนดอนุญาตให้โค้ดของคุณจัดการคำร้องขอจากซ็อกเก็ตเปิดหลายแสนด้วยหัวข้อเดียวพร้อมกันโดยการมัลติเพล็กซ์และเรียงลำดับ js ทั้งหมดของคุณ ตรรกะในการดำเนินการสตรีมเดียว (แม้ว่าการพูดว่า "ทุกอย่างทำงานในแบบขนาน" อาจไม่ถูกต้องที่นี่ - ดูการทำงานพร้อมกันกับการขนาน - ความแตกต่างคืออะไร ) นี้ทำงานสวยดีสำหรับเซิร์ฟเวอร์ webapp เป็นส่วนใหญ่ของเวลาที่ใช้จริงในการรอคอยสำหรับเครือข่ายหรือดิสก์ (ฐานข้อมูล / ซ็อกเก็ต) และตรรกะไม่ได้จริงๆ CPU เข้ม - นั่นคือจะพูดว่า: งานนี้ดีสำหรับงาน IO-ที่ถูกผูกไว้


45
คำถามติดตามผล I / O เกิดขึ้นจริงอย่างไร? โหนดกำลังส่งคำขอไปยังระบบและขอให้แจ้งเตือนเมื่อเสร็จสิ้น ดังนั้นระบบที่รันเธรดที่กำลังทำ I / O หรือระบบกำลังดำเนินการ I / O แบบอะซิงโครนัสที่ระดับฮาร์ดแวร์โดยใช้อินเตอร์รัปต์หรือไม่ บางสิ่งบางอย่างต้องรอให้ I / O เสร็จสิ้นและนั่นจะปิดกั้นจนกว่าจะเสร็จสิ้นและใช้ทรัพยากรจำนวนหนึ่ง
ฟิลิป

6
เพิ่งสังเกตเห็นว่าความคิดเห็นติดตามผลนี้ตอบโดย @ user568109 ด้านล่างฉันหวังว่าจะมีวิธีรวมคำตอบทั้งสองนี้
lfalin

4
ฉันหวังว่าคุณจะสามารถเขียนคำตอบสองครั้งได้นานดังนั้นฉันจะเข้าใจดีขึ้นสองเท่า
Rafael Eyng

โหนดได้รับการสนับสนุนในหลาย ๆ ที่สำหรับการบันทึก เมื่อฉันออกแบบเฟิร์มแวร์สำหรับเราเตอร์ MIPS32 Node.JS สามารถทำงานกับ OpenWRT ได้
Qix - MONICA ถูกยกเลิก

คะแนนเหนือ apache ได้อย่างไร? Apache ยังสามารถจัดการการเชื่อมต่อพร้อมกันด้วยเธรดแยกต่างหาก
Suhail Gupta

210

เพื่อให้มุมมองให้ฉันเปรียบเทียบ node.js กับ apache

Apache เป็นเซิร์ฟเวอร์ HTTP แบบมัลติเธรดสำหรับแต่ละคำขอทุกครั้งที่เซิร์ฟเวอร์ได้รับจะสร้างเธรดแยกต่างหากซึ่งจัดการคำขอนั้น

Node.js ในอีกด้านหนึ่งเป็นเหตุการณ์ขับเคลื่อนการจัดการคำขอทั้งหมดแบบอะซิงโครนัสจากเธรดเดี่ยว

เมื่อได้รับ A และ B บน apache สองเธรดจะถูกสร้างขึ้นเพื่อจัดการกับคำร้องขอ แต่ละการจัดการแบบสอบถามแยกต่างหากแต่ละคนรอผลลัพธ์แบบสอบถามก่อนแสดงหน้า หน้านี้จะให้บริการจนกว่าแบบสอบถามจะเสร็จสิ้น การดึงแบบสอบถามกำลังบล็อกเนื่องจากเซิร์ฟเวอร์ไม่สามารถดำเนินการเธรดที่เหลือจนกว่าจะได้รับผลลัพธ์

ในโหนด c.query ได้รับการจัดการแบบอะซิงโครนัสซึ่งหมายความว่าในขณะที่ c.query ดึงผลลัพธ์สำหรับ A มันจะกระโดดเพื่อจัดการ c.query สำหรับ B และเมื่อผลลัพธ์มาถึงสำหรับ A มาถึงมันจะส่งผลลัพธ์กลับไปที่โทรกลับซึ่งส่ง คำตอบ Node.js รู้ว่าจะดำเนินการติดต่อกลับเมื่อดึงข้อมูลเสร็จสิ้น

ในความเห็นของฉันเนื่องจากเป็นรูปแบบเธรดเดียวจึงไม่มีวิธีเปลี่ยนจากคำขอหนึ่งไปเป็นคำขออื่น

จริงๆแล้วเซิร์ฟเวอร์โหนดทำสิ่งนั้นให้คุณตลอดเวลา ในการสร้างสวิตช์ (พฤติกรรมแบบอะซิงโครนัส) ฟังก์ชันส่วนใหญ่ที่คุณจะใช้จะมีการเรียกกลับ

แก้ไข

แบบสอบถาม SQL นำมาจากห้องสมุดmysql มันใช้สไตล์การโทรกลับเช่นเดียวกับอีซีแอเหตุการณ์เพื่อคิวคิว SQL ไม่ดำเนินการแบบอะซิงโครนัสซึ่งทำโดยเธรดlibuvภายในที่ให้นามธรรมของ I / O ที่ไม่บล็อก ขั้นตอนต่อไปนี้เกิดขึ้นในการทำแบบสอบถาม:

  1. เปิดการเชื่อมต่อกับ db สามารถทำการเชื่อมต่อแบบอะซิงโครนัสได้
  2. เมื่อเชื่อมต่อฐานข้อมูลแล้วแบบสอบถามจะถูกส่งไปยังเซิร์ฟเวอร์ แบบสอบถามสามารถจัดคิว
  3. วนรอบเหตุการณ์หลักจะได้รับแจ้งการเสร็จสิ้นด้วยการโทรกลับหรือเหตุการณ์
  4. หลักวนรอบดำเนินการติดต่อกลับ / eventhandler ของคุณ

คำขอขาเข้าไปยังเซิร์ฟเวอร์ http ได้รับการจัดการในลักษณะเดียวกัน สถาปัตยกรรมเธรดภายในเป็นดังนี้:

วนรอบเหตุการณ์ node.js

เธรด C ++ คือ libuv ที่ทำแบบอะซิงโครนัส I / O (ดิสก์หรือเครือข่าย) เหตุการณ์หลักวนรอบยังคงดำเนินการหลังจากการจัดส่งการร้องขอไปยังกลุ่มเธรด สามารถรับคำขอเพิ่มเติมได้เนื่องจากไม่ต้องรอหรือนอนหลับ การสืบค้น SQL / การร้องขอ HTTP / ระบบไฟล์อ่านทั้งหมดเกิดขึ้นด้วยวิธีนี้


16
ไดอะแกรมมีประโยชน์มาก
Anmol Saraf

14
รอดังนั้นในไดอะแกรมของคุณคุณมี "internal C ++ threadpool" ซึ่งหมายความว่าการดำเนินการบล็อก IO ทั้งหมดจะวางไข่เธรดใช่มั้ย ดังนั้นหากแอป Node ของฉันใช้งาน IO บางอย่างสำหรับทุกคำขอมีความแตกต่างระหว่างโมเดลโหนดและโมเดล Apache หรือไม่? ฉันไม่ได้รับส่วนนี้ขอโทษ
gav.newalkar

21
@ gav.newalkar พวกเขาไม่วางไข่เธรดคำขอถูกจัดคิว เธรดในเธรดพูลประมวลผล เธรดไม่ได้เป็นแบบไดนามิกและตามคำขอเช่นเดียวกับใน Apache พวกเขามักจะได้รับการแก้ไขและแตกต่างจากระบบไปยังระบบ
user568109

10
@ user568109 แต่ Apache ก็ใช้เธรดพูลด้วยเช่นกัน ( httpd.apache.org/docs/2.4/mod/worker.html ) ดังนั้นในที่สุดความแตกต่างระหว่างการติดตั้งกับ node.js แตกต่างจากที่มี Apache อยู่ด้านหน้าเฉพาะในที่ตั้ง threadpool อยู่ใช่ไหม?
กริช

13
แผนภาพนั้นควรอยู่ในหน้าแรกของเอกสารอย่างเป็นทางการ
bouvierr

52

Node.js ใช้libuvเบื้องหลัง libuv มีเธรดพูล (ขนาด 4 ตามค่าเริ่มต้น) ดังนั้น Node.js ใช้เธรดเพื่อให้เกิดความพร้อมกัน

อย่างไรก็ตาม , รหัสของคุณทำงานบนเส้นเดียว (เช่นทุกฟังก์ชั่นการเรียกกลับ Node.js จะถูกเรียกว่าในหัวข้อเดียวกันที่เรียกว่าวงด้ายหรือเหตุการณ์วง) เมื่อมีคนพูดว่า "Node.js ทำงานบนเธรดเดียว" พวกเขากำลังพูดว่า "การเรียกกลับของ Node.js ทำงานบนเธรดเดี่ยว"


1
คำตอบสั้น ๆ แต่ชัดเจน (y)
Sudhanshu Gaur

1
คำตอบที่ดีฉันจะเพิ่มว่า I / O เกิดขึ้นนอกเหตุการณ์ห่วงหลักนี้ห่วงวนด้ายขอด้าย
Ionut Popa

นั่นคือคำตอบสิ่งที่ฉันค้นหาจาก 2 ชั่วโมงว่าการทำงานพร้อมกันในการจัดการแอพพลิเคชั่นแบบเธรดเดียวได้อย่างไร
Muhammad Ramzan

ใช่ยากที่จะได้คำตอบ 'ระดับถัดไป' สิ่งนี้อธิบายว่าที่จริงแล้ว IO ทำอะไรได้บ้าง (ในกลุ่มเธรดอื่น)
Oliver Shaw

9

Node.js ขึ้นอยู่กับโมเดลการโปรแกรมมิงวนเหตุการณ์ วนรอบเหตุการณ์จะทำงานในเธรดเดี่ยวและรอเหตุการณ์ซ้ำ ๆ จากนั้นเรียกใช้ตัวจัดการเหตุการณ์ใด ๆ ที่สมัครรับข้อมูลเหตุการณ์เหล่านั้น เหตุการณ์สามารถเป็นตัวอย่าง

  • การจับเวลารอเสร็จสมบูรณ์
  • อันถัดไปของข้อมูลพร้อมที่จะถูกเขียนลงไฟล์นี้
  • มีคำขอ HTTP ใหม่ที่สดใหม่มาถึงแล้ว

ทั้งหมดนี้ทำงานในเธรดเดียวและไม่มีการเรียกใช้โค้ด JavaScript แบบขนาน ตราบใดที่ตัวจัดการเหตุการณ์เหล่านี้มีขนาดเล็กและยังรอเหตุการณ์เพิ่มเติมที่ตัวเองทุกอย่างทำงานได้ดี สิ่งนี้อนุญาตให้จัดการหลายคำร้องขอพร้อมกันโดยกระบวนการ Node.js เดียว

(มีความมหัศจรรย์เล็กน้อยภายใต้ประทุนซึ่งเป็นที่มาของเหตุการณ์บางอย่างเกี่ยวข้องกับเธรดผู้ปฏิบัติงานระดับต่ำที่ทำงานพร้อมกัน)

ในกรณี SQL นี้มีจำนวนมากของสิ่งที่ (เหตุการณ์) ที่เกิดขึ้นระหว่างการทำแบบสอบถามฐานข้อมูลและได้รับผลของมันในการติดต่อกลับ ในช่วงเวลานั้นวงเหตุการณ์จะปั๊มชีวิตลงในแอปพลิเคชันและจะขออีกเหตุการณ์หนึ่งครั้งละครั้ง ดังนั้นจึงมีการแสดงคำขอหลายรายการพร้อมกัน

มุมมองเหตุการณ์ระดับสูงของลูปเหตุการณ์

ตามที่: "ห่วงเหตุการณ์จาก 10,000 - แนวคิดหลักที่อยู่เบื้องหลัง Node.js"


5

ฟังก์ชัน c.query () มีสองอาร์กิวเมนต์

c.query("Fetch Data", "Post-Processing of Data")

การดำเนินการ "ดึงข้อมูล" ในกรณีนี้คือ DB-Query ตอนนี้ Node.js อาจถูกจัดการโดยการวางไข่จากเธรดผู้ปฏิบัติงานและให้ภารกิจนี้ในการดำเนินการ DB-Query (จำ Node.js สามารถสร้างเธรดภายใน) สิ่งนี้ทำให้ฟังก์ชั่นส่งคืนทันทีโดยไม่ล่าช้า

อาร์กิวเมนต์ที่สอง "การประมวลผลข้อมูล" เป็นฟังก์ชันการโทรกลับกรอบงานโหนดจะลงทะเบียนการโทรกลับนี้และถูกเรียกใช้โดยลูปเหตุการณ์

ดังนั้นคำสั่งc.query (paramenter1, parameter2)จะกลับมาทันทีเปิดใช้งานโหนดเพื่อตอบสนองคำขออื่น

PS: ฉันเพิ่งเริ่มเข้าใจโหนดจริง ๆ แล้วฉันต้องการที่จะเขียนสิ่งนี้เป็นความคิดเห็นต่อ@Philip แต่เนื่องจากไม่มีคะแนนชื่อเสียงเพียงพอจึงเขียนเป็นคำตอบ


3

หากคุณอ่านเพิ่มเติมอีกเล็กน้อย - "แน่นอนในส่วนหลังมีเธรดและกระบวนการสำหรับการเข้าถึงฐานข้อมูลและการดำเนินการตามกระบวนการอย่างไรก็ตามสิ่งเหล่านี้จะไม่เปิดเผยรหัสของคุณอย่างชัดเจนดังนั้นคุณจึงไม่ต้องกังวลเกี่ยวกับสิ่งอื่นนอกจากรู้ การโต้ตอบของ I / O เช่นกับฐานข้อมูลหรือกระบวนการอื่น ๆ จะไม่ตรงกันจากมุมมองของแต่ละคำขอเนื่องจากผลลัพธ์จากเธรดเหล่านั้นจะถูกส่งคืนผ่านลูปเหตุการณ์ไปยังโค้ดของคุณ "

เกี่ยวกับ - "ทุกอย่างทำงานในแบบขนานยกเว้นรหัสของคุณ" - รหัสของคุณจะถูกดำเนินการแบบซิงโครนัสเมื่อใดก็ตามที่คุณเรียกใช้การดำเนินการแบบอะซิงโครนัสเช่นการรอ IO เหตุการณ์ห่วงจะจัดการทุกอย่าง มันไม่ใช่สิ่งที่คุณต้องคิด

ในตัวอย่างของคุณ: มีสองคำขอ A (มาก่อน) และ B. คุณดำเนินการตามคำขอ A, รหัสของคุณจะยังคงทำงานแบบซิงโครนัสและดำเนินการตามคำขอ B วงวนเหตุการณ์จะจัดการคำขอเมื่อเสร็จสิ้นแล้วจะเรียกการเรียกกลับ ผลลัพธ์เดียวกันจะไปขอ B.


3
"แน่นอนบนแบ็กเอนด์มีเธรดและกระบวนการสำหรับการเข้าถึงฐานข้อมูลและการประมวลผลกระบวนการอย่างไรก็ตามสิ่งเหล่านี้ไม่ได้เปิดเผยรหัสของคุณอย่างชัดเจน" - ถ้าฉันใช้จากวลีนี้แล้วฉันไม่เห็นความแตกต่างระหว่างโหนดใด ๆ ทำหรือกรอบ multithreaded ใด ๆ - สมมติว่า Spring Framework ของ Java - ทำ มีหลายเธรด แต่คุณไม่ได้ควบคุมการสร้าง
Rafael Eyng

@RafaelEyng ฉันคิดว่าสำหรับการจัดการชุดของคำขอหลาย ๆ โหนดจะมีหัวข้อเดียวสำหรับที่ ฉันไม่แน่ใจว่าการเรียกกลับแต่ละครั้งจะถูกวางไว้บนอินสแตนซ์ใหม่ของเธรดนอกเหนือจากกระบวนการอื่น ๆ เช่นการเข้าถึงฐานข้อมูล แต่อย่างน้อยเราก็รู้ว่าโหนดไม่อินสแตนซ์เธรดทุกครั้งที่ได้รับการร้องขอซึ่งจะต้องรอ โทรกลับ)
Cerberus เย็น

1

เอาล่ะสิ่งที่มากที่สุดควรมีความชัดเจนเพื่อให้ห่างไกล ... ส่วนที่ยุ่งยากเป็นของ SQL : ถ้ามันไม่ได้อยู่ในความเป็นจริงทำงานในหัวข้ออื่นหรือกระบวนการในมันครบถ้วนของ SQL-การดำเนินการจะต้องมีการแบ่งออกเป็นแต่ละขั้นตอน (โดย ตัวประมวลผล SQL ที่สร้างขึ้นสำหรับการประมวลผลแบบอะซิงโครนัส!) ซึ่งตัวที่ไม่บล็อกจะถูกดำเนินการและตัวบล็อก (เช่นสลีป) สามารถถ่ายโอนจริงไปยังเคอร์เนล (เป็นสัญญาณเตือนการขัดจังหวะ / เหตุการณ์) และใส่รายการเหตุการณ์สำหรับ ห่วงหลัก

นั่นหมายความว่าเช่นการตีความของ SQL ฯลฯ จะทำทันที แต่ในระหว่างการรอ (เก็บเป็นเหตุการณ์ที่จะมาในอนาคตโดยเคอร์เนลใน kqueue, epoll, ... โครงสร้างร่วมกับการดำเนินงาน IO อื่น ๆ ) ลูปหลักสามารถทำสิ่งอื่น ๆ ได้และในที่สุดก็ตรวจสอบว่ามีบางสิ่งเกิดขึ้นจาก IO และรออยู่

ดังนั้นในการใช้ถ้อยคำใหม่อีกครั้ง: โปรแกรมไม่เคย (อนุญาตให้ติด) ติดขัดการโทรขณะหลับจะไม่ถูกดำเนินการ หน้าที่ของพวกเขาทำโดยเคอร์เนล (เขียนอะไรสักอย่างรอสิ่งที่จะมาผ่านเครือข่ายรอเวลาผ่านไป) หรือเธรดหรือกระบวนการอื่น - กระบวนการโหนดตรวจสอบว่าอย่างน้อยหนึ่งในหน้าที่เหล่านั้นจะเสร็จสิ้นโดยเคอร์เนลในการเรียกบล็อกไปยังระบบปฏิบัติการเพียงครั้งเดียวในแต่ละเหตุการณ์วงรอบ ถึงจุดนั้นเมื่อทุกอย่างที่ไม่มีการปิดกั้นเสร็จสิ้น

ชัดเจน? :-)

ฉันไม่รู้โหนด แต่ c.query มาจากไหน?


kqueue epoll ใช้สำหรับการแจ้งเตือน I / O แบบอะซิงโครนัสที่ปรับขนาดได้ในเคอร์เนล linux โหนดมี libuv สำหรับสิ่งนั้น โหนดอยู่บน userland ทั้งหมด ไม่ได้ขึ้นอยู่กับเคอร์เนลที่ใช้
user568109

1
@ user568109, libuv เป็นคนกลางของโหนด เฟรมเวิร์กแบบอะซิงโครนัสใด ๆ ขึ้นอยู่กับหรือไม่สนับสนุนโดยตรงกับการสนับสนุน I / O แบบอะซิงโครนัสในเคอร์เนล ดังนั้น?
Robert Siemer

ขอโทษสำหรับความสับสน. การทำงานของซ็อกเก็ตต้องการการปิดกั้น I / O จากเคอร์เนล ดูแลการจัดการแบบอะซิงโครนัส แต่ไฟล์ I / O แบบอะซิงโครนัสนั้นถูกจัดการโดย libuv เอง คำตอบของคุณไม่ได้บอกว่า จะถือว่าทั้งสองเหมือนกันถูกจัดการโดยเคอร์เนล
user568109
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.