คนงานที่ไม่ปิดกั้น VS หลายคนที่ปิดกั้น


9

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

คนงานที่ขวางกั้นหลายคนเก่งเพราะ:

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

ผู้ปฏิบัติงานที่ไม่บล็อกคนเดียวนั้นดีเพราะ:

  • ใช้หน่วยความจำน้อยลง
  • ลูกค้าที่ขี้เกียจน้อยกว่า (ซึ่งเชื่อมต่อกับเซิร์ฟเวอร์และส่งส่วนหัวอย่างช้าๆหรือไม่ส่งเลย)

อย่างที่คุณอาจจะเห็นว่าในความคิดของฉันคนงานหลายหัวข้อดูเหมือนโซลูชันที่ดีขึ้นโดยรวม ปัญหาเดียวของมันคือการโจมตีเซิร์ฟเวอร์นั้นง่ายกว่า

แก้ไข (การวิจัยเพิ่มเติม): ทรัพยากรบางอย่างที่ฉันพบบนเว็บ ( พันเธรดและการบล็อก I / O - วิธีเก่าในการเขียนเซิร์ฟเวอร์ Java คือใหม่อีกครั้ง (และดีกว่า)โดย Paul Tyma) คำแนะนำที่ว่าวิธีการบล็อกโดยทั่วไปดีกว่า ฉันยังไม่รู้จริงๆว่าจะจัดการกับการเชื่อมต่อปลอมได้อย่างไร

PS ไม่แนะนำให้ใช้ไลบรารีหรือแอปพลิเคชันสำหรับงาน ฉันสนใจที่จะรู้ว่ามันใช้งานได้จริงหรืออาจทำงานได้ดีกว่าทำงาน

PSS ฉันแบ่งลอจิกออกเป็นหลายส่วนและอันนี้จัดการได้เฉพาะการยอมรับส่วนหัว HTTP ไม่ประมวลผลพวกเขา


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

คำตอบ:


4

ไม่มีกระสุนเงิน

ในทางปฏิบัติมันขึ้นอยู่กับ ...

tl; dr - วิธีแก้ง่ายใช้ nginx ...

การปิดกั้น:

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

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

AFAIK โดยทั่วไปใช้วิธีการแบบหลายกระบวนการในเซิร์ฟเวอร์ HTTP ที่บล็อกเนื่องจากเป็นวิธีที่ปลอดภัยกว่า / ง่ายกว่าในการจัดการ / กู้คืนหน่วยความจำในลักษณะที่ปลอดภัย การรวบรวมขยะกลายเป็นปัญหาที่ไม่ใช่เมื่อการกู้คืนหน่วยความจำนั้นง่ายพอ ๆ กับการหยุดกระบวนการ สำหรับกระบวนการที่ใช้เวลานาน (เช่น daemon) คุณลักษณะนั้นมีความสำคัญเป็นพิเศษ

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

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

non-blocking:

การไม่บล็อกจะเป็นสิ่งที่เหมือนกับ Node.js หรือ nginx สิ่งเหล่านี้เป็นที่รู้จักโดยเฉพาะอย่างยิ่งสำหรับการปรับการเชื่อมต่อจำนวนมากขึ้นต่อโหนดภายใต้โหลดที่ใช้ IO มาก โดยทั่วไปแล้วเมื่อมีคนเข้ามาถึงขีด จำกัด สูงสุดของสิ่งที่เซิร์ฟเวอร์ที่ใช้เธรด / กระบวนการสามารถจัดการพวกเขาเริ่มสำรวจตัวเลือกอื่น สิ่งนี้เรียกว่าปัญหา C10K (เช่นความสามารถในการจัดการ 10,000 การเชื่อมต่อพร้อมกัน)

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

แม้ว่ามันอาจจะไม่สามารถใช้ได้กับโปรโตคอลเครือข่ายจำนวนมาก แต่ HTTPs ที่ไร้สัญชาตินั้นทำงานได้ดีเป็นพิเศษสำหรับสถาปัตยกรรมที่ไม่มีการบล็อก โดยการใช้การรวมกันของ reverse-proxy และเซิร์ฟเวอร์ HTTP ที่ไม่มีการบล็อกหลายตัวเป็นไปได้ที่จะระบุและกำหนดเส้นทางรอบ ๆ โหนดที่มีโหลดจำนวนมาก

แม้แต่บนเซิร์ฟเวอร์ที่มีเพียงหนึ่งโหนดก็เป็นเรื่องปกติมากสำหรับการตั้งค่าเพื่อรวมเซิร์ฟเวอร์หนึ่งตัวต่อโปรเซสเซอร์หลักเพื่อเพิ่มปริมาณงานสูงสุด

ทั้งสอง:

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

ในกรณีของคุณ:

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

ผมขอแนะนำให้ตรวจสอบจากเอกสารสำหรับNginx ในตัวพร็อกซี่กลับ

นอกเหนือ:

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

พบว่าเมื่อสลับระหว่างไคลเอนต์รหัสสำหรับการบันทึกและการคืนค่า / สถานะเป็นเรื่องยาก

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

ดูเหมือนว่าพวกเขาจะเข้าใจแอสซิงก์ได้ไม่ดีนักและส่งผลให้มีสมมติฐานที่ไม่ดีมากมาย

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