อะไรคือการไม่ปิดกั้นหรือ I / O ไม่ตรงกันใน Node.js?


136

ในบริบทของเอ็นจิ้นฝั่งเซิร์ฟเวอร์ Javascript สิ่งที่ไม่บล็อก I / O หรืออะซิงโครนัส I / O คืออะไร ฉันเห็นนี้ถูกกล่าวถึงว่าเป็นข้อได้เปรียบกว่าการใช้งานด้านเซิร์ฟเวอร์ Java


3
การคิดถึงแท็กสคริปต์ในสภาพแวดล้อมของเบราว์เซอร์จะช่วยให้เข้าใจแนวคิดนี้ได้ดี Zakas มีบทความที่ยอดเยี่ยมเกี่ยวกับเรื่องนี้ - ส่วนแรก ๆ ควรเพียงพอที่จะอธิบายแนวคิดของการบล็อก: nczonline.net/blog/2010/08/10/what-is-a-non-blocking-script
netpoetica

คำตอบ:


317

ซิงโครนัส vs อะซิงโครนัส

การประมวลผลแบบซิงโครนัสมักจะหมายถึงการเรียกใช้โค้ดตามลำดับ การประมวลผลแบบอะซิงโครนัสหมายถึงการเรียกใช้ที่ไม่ได้ทำงานตามลำดับที่ปรากฏในรหัส ในตัวอย่างต่อไปนี้การดำเนินการแบบซิงโครนัสทำให้การแจ้งเตือนเริ่มทำงานตามลำดับ ในการดำเนินการ async ในขณะที่alert(2)ดูเหมือนจะดำเนินการที่สองก็ไม่ได้

ซิงโครนัส: 1,2,3

alert(1);
alert(2);
alert(3);

แบบอะซิงโครนัส: 1,3,2

alert(1);
setTimeout(() => alert(2), 0);
alert(3);

การบล็อก vs การไม่บล็อก

การบล็อกหมายถึงการดำเนินการที่บล็อกการดำเนินการเพิ่มเติมจนกว่าการดำเนินการนั้นจะเสร็จสิ้น การไม่บล็อกหมายถึงโค้ดที่ไม่ได้บล็อกการทำงาน ในตัวอย่างที่กำหนดlocalStorageคือการดำเนินการปิดกั้นตามที่จะหยุดการดำเนินการเพื่ออ่าน ในทางกลับกันfetchเป็นการดำเนินการที่ไม่มีการปิดกั้นเนื่องจากไม่ได้ขัดขวางalert(3)การทำงาน

// Blocking: 1,... 2
alert(1);
var value = localStorage.getItem('foo');
alert(2);

// Non-blocking: 1, 3,... 2
alert(1);
fetch('example.com').then(() => alert(2));
alert(3);

ข้อดี

ข้อดีอย่างหนึ่งของการดำเนินการแบบอะซิงโครนัสที่ไม่ปิดกั้นคือคุณสามารถเพิ่มการใช้งาน CPU สูงสุดเช่นเดียวกับหน่วยความจำ

ซิงโครนัสตัวอย่างการบล็อก

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

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

ตัวอย่างแบบอะซิงโครนัสและไม่มีการบล็อก

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

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


5
ผมไม่แน่ใจว่าผมเข้าใจวรรค 2 ของคุณภายใต้การปิดกั้นใน PHP คุณกำลังบอกว่า "ในขณะที่ PHP มักจะบล็อกบน IO มันไม่ได้เพราะระบบปฏิบัติการเธรดการดำเนินงาน IO โดยอัตโนมัติ"? หรือคุณกำลังบอกว่านี่ไม่ใช่ปัญหาใน PHP เพราะ PHP สร้างเธรดใหม่สำหรับแต่ละคำขอโดยอัตโนมัติดังนั้นคำขอที่ถูกบล็อกหนึ่งคำขอจะไม่หยุดทั้งสภาพแวดล้อมของ PHP? (ฉันคาดเดาหลัง .. )
dcow

6
มันหลัง
โจเซฟ

2
รอสักครู่ถ้ามันหมายถึงอันหลังข้อดีที่ไม่ใช่การบล็อก I / O PHP (เช่น reactPHP หรืออย่างอื่น) เหนือการบล็อก ยังคงสับสน
Sunu Pinasthika Fajar

5
@CharlieParker ใช่ การดำเนินการ async ทำงานขนานกับรหัสของคุณ แต่การโทรกลับที่ "กลับมา" กับผลลัพธ์ของการดำเนินการแบบ async นั้นจะถูกจัดคิวเพื่อประมวลผลในรหัสหลักเมื่อรหัสหลักไม่ว่าง
โจเซฟ

2
@CharlieParker ต่อไปนี้เป็นบทความที่เกี่ยวข้องกับ internals ของกลไก async
โจเซฟ

7
var startTime = new Date().getTime();
var getEndTime = () => {
    var tempEndTime = new Date().getTime();
    var second = (tempEndTime - startTime)/1000
    return `took ${second} sec...to finish\n`
}

console.log('1: start App', getEndTime())
setTimeout(()=>{
    console.log('2: setTimeout', getEndTime())
}, 1000)
console.log('3: End App', getEndTime())

// console -> Process Order:  1 -> 3 -> 2

ตัวอย่างรหัส

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