TCP เปิดการเชื่อมต่อใหม่สำหรับทุกแพ็กเก็ตที่ส่งหรือไม่


15

นี่อาจเป็นคำถามที่งี่เง่า แต่ฉันและเพื่อนไม่กี่คนกำลังพูดถึงข้อ จำกัด ที่อาจเกิดขึ้นของ TCP เรามีแอปพลิเคชั่นที่จะคอยฟังลูกค้า (คิดถึงเกตเวย์) และกำหนดเส้นทางข้อมูลลูกค้าที่เชื่อมต่อทั้งหมดผ่านผู้เผยแพร่คาฟคาที่เชื่อมต่อไปยังหัวข้อเดียว

หนึ่งในเพื่อนของฉันกำลังบอกว่า TCP จะเป็นปัญหาสำหรับเกตเวย์นี้เนื่องจากกำลังจะสร้างการเชื่อมต่อใหม่สำหรับทุกข้อความที่ส่ง (ไม่ใช่ kafka แต่โปรโตคอลการขนส่งพื้นฐานนั้นเป็นปัญหา) ซึ่งต้องมีพอร์ตใหม่ทุกครั้ง ในอัตราที่เราจะส่งข้อความลูกค้าเหล่านี้ (กิกะไบต์), kafka จะหมดพอร์ตที่จะอ่านจาก ??

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

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

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


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

13
TCP ไม่สามารถเปิดการเชื่อมต่อใหม่สำหรับแต่ละแพ็คเก็ตได้เนื่องจากมันต้องการแพ็คเก็ตหลายตัวเพื่อเปิดการเชื่อมต่อใหม่ และไม่สามารถเปิดการเชื่อมต่อใหม่สำหรับแต่ละข้อความได้เนื่องจาก TCP ไม่มีแนวคิดของข้อความ เพื่อนของคุณสับสนมาก สิ่งที่สำคัญที่สุดที่จะเข้าใจเกี่ยวกับ TCP ซึ่งเป็นแนวคิดพื้นฐานที่สุดคือ TCP เป็นโปรโตคอลสตรีมไบต์
David Schwartz

1
อาร์กิวเมนต์เพื่อนของคุณไม่จำเป็นต้องผิด - ถ้าคุณไม่ใช้พอร์ตซ้ำผ่านแอพพลิเคชั่นระดับคงที่หรือมีลูกค้ามากเกินไประบบของคุณอาจหมดพอร์ตชั่วคราว มีวิธีแก้ไขปัญหาดังกล่าว: ใช้SO_REUSEADDRเพื่อปิดซ็อกเก็ตเร็วขึ้นเพิ่มช่วงของพอร์ตชั่วคราว ฯลฯ นอกจากนี้TCP_FASTOPENและสามารถใช้สลับระดับ OS หลายอย่างเพื่อแก้ไขข้อ จำกัด อื่น ๆ ที่รู้จักกันดีของ TCP ไม่ว่าจะด้วยวิธีใดจะไม่มีประเด็นในการพูดคุยข้อ จำกัด ของ TCP เมื่อคุณไม่มีภาระงานที่จะทดสอบ
user1643723

คำตอบ:


22

หนึ่งในเพื่อนของฉันกำลังบอกว่า TCP จะเป็นปัญหาสำหรับเกตเวย์นี้เนื่องจากกำลังจะสร้างการเชื่อมต่อใหม่สำหรับทุกข้อความที่ส่ง (ไม่ใช่ kafka แต่โปรโตคอลการขนส่งพื้นฐานนั้นเป็นปัญหา) ซึ่งต้องมีพอร์ตใหม่ทุกครั้ง ในอัตราที่เราจะส่งข้อความลูกค้าเหล่านี้ (กิกะไบต์), kafka จะหมดพอร์ตที่จะอ่านจาก ??

เพื่อนของคุณสับสนอย่างรุนแรง TCP เป็นโปรโตคอลแบบสตรีม มันไม่มีความคิดของข้อความ แน่นอนว่ามันใช้แพ็กเก็ตที่เลเยอร์ IP แต่สำหรับแอปพลิเคชันนี่คือรายละเอียดการใช้งาน TCP แทรกขอบเขตแพ็คเก็ตที่มันทำให้ความรู้สึกที่จะทำเช่นนั้นและไม่จำเป็นต้องมีครั้งเดียวต่อwrite()send()หรือ ในทำนองเดียวกันก็รวมแพ็กเก็ตต่อเนื่องกันหากคุณได้รับมากกว่าหนึ่งระหว่างการโทรไปหรือread()recv()

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

(ในทางปฏิบัติโปรโตคอลส่วนใหญ่ที่สร้างขึ้นบน TCP มีสิ่งที่คล้ายกับข้อความเช่นคำขอ HTTP และการตอบสนอง แต่ TCP ไม่ทราบหรือสนใจเกี่ยวกับโครงสร้างของสิ่งต่าง ๆ )

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


9

ความเข้าใจของฉันคือเมื่อคุณสร้างการเชื่อมต่อ TCP การเชื่อมต่อนั้นจะยังคงเปิดอยู่จนกว่าจะหมดเวลาโดยแอปพลิเคชันหรือบังคับให้ปิดโดยเซิร์ฟเวอร์หรือไคลเอนต์

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

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

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

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


2
แม้ว่าใน TCP จะมีพันธมิตรรายหนึ่งที่เริ่มต้นการเชื่อมต่อ (มักเรียกว่า "ลูกค้า") และอีกคนหนึ่ง (มักเรียกว่า "เซิร์ฟเวอร์") แน่นอนหลังจากสร้างการเชื่อมต่อแล้วความแตกต่างนี้ไม่สำคัญอีกต่อไป
Paŭlo Ebermann

2
@ PaŭloEbermannไม่มีอะไรใน TCP RFC เกี่ยวกับไคลเอนต์หรือเซิร์ฟเวอร์ แนวคิดไคลเอนต์ / เซิร์ฟเวอร์เป็นแนวคิดแอปพลิเคชัน สิ่งที่อยู่ในหัวข้อที่นี่คือโปรโตคอลที่หรือต่ำกว่า OSI layer-4 และไม่มีไคลเอนต์หรือเซิร์ฟเวอร์ในโปรโตคอลเหล่านั้น ในความเป็นจริงสิ่งที่คุณอาจถือว่าเป็นไคลเอนต์ (อันที่เปิดการเชื่อมต่อ TCP) ในความเป็นจริงอาจเป็นแอพพลิเคชันเซิร์ฟเวอร์ เรามีเซิร์ฟเวอร์ที่เริ่มต้นการเชื่อมต่อ TCP กับลูกค้าเพื่อทำสิ่งต่าง ๆ เช่นการตรวจสอบความปลอดภัยและการปรับปรุง
Ron Maupin

7

ไม่ TCP ไม่จำเป็นต้องเปิดการเชื่อมต่อใหม่สำหรับทุกแพ็คเก็ตที่ส่ง

คุณสามารถส่งหลาย ๆ แพ็กเก็ตโดยใช้การเชื่อมต่อ HTTP แบบถาวรโดยที่:

... การเชื่อมต่อ TCP เดียวเพื่อส่งและรับการร้องขอ / ตอบกลับ HTTP หลายรายการ [ถูกใช้] ตรงข้ามกับการเปิดการเชื่อมต่อใหม่สำหรับทุกคู่คำขอ / ตอบกลับเดียว

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

การเชื่อมต่อที่หลากหลาย vs การเชื่อมต่อแบบต่อเนื่อง

ที่มา: https://www.vcloudnine.de/how-to-dramatically-improve-website-load-times/


7
คำตอบนี้ดูเหมือนจะทำให้เกิดความสับสนในเลเยอร์ การร้องขอ / ตอบกลับของ HTTP นั้นแทบจะไม่เป็นเพียงแพ็กเก็ตเดียว
Barmar

2
ไม่ต้องพูดถึงทุก ๆ "open" คือลูกศร 3 อัน (syn, synack, ack) และทุก ๆ "close" คืออีก 4 (fin, ack 2x เซิร์ฟเวอร์และไคลเอนต์) ดังนั้นหากจะมีการเชื่อมต่อต่อแพ็คเก็ตจริง จะเพิ่มขึ้นอย่างรวดเร็ว
htmlcoderexe

5

คุณตีความว่า TCP ทำงานอย่างไร

สำหรับสิ่งที่เพื่อนของคุณพูดฉันเห็นความเป็นไปได้สองอย่างที่นี่:

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

  2. เพื่อนของคุณผิด


5

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

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

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

ในที่สุดตามที่คนอื่น ๆ ได้กล่าวถึง TCP เป็นกระแสข้อมูล ไม่มีกรอบใด ๆ เพียงเพราะเพียร์หนึ่งเขียนข้อมูลด้วยวิธีใดวิธีหนึ่ง (เช่น 1 1024 byte write call ตามด้วย 2 256 byte write calls) ที่ไม่รับประกันว่าเพียร์อื่นจะอ่านมันในกลุ่มขนาดเดียวกัน (เช่นมันอาจได้รับทั้งหมด 1536 ไบต์ ในการอ่านครั้งเดียว) ดังนั้นหากคุณกำลังส่ง "ข้อความ" หลาย ๆ ตัวบนซ็อกเก็ต TCP แบบดิบคุณจะต้องจัดทำโพรโทคอลการกำหนดเฟรมภาพของคุณเองเพื่อแยกแยะข้อความที่แตกต่างกัน แม้ว่าจะมีวิธีที่ง่ายในการทำเช่นนี้ แต่โดยทั่วไปก็ไม่ควรทำเพราะมีโปรโตคอลจำนวนมากที่สร้างขึ้นบน TCP เพื่อแก้ปัญหานี้ สำหรับการสนทนาเพิ่มเติมโปรดดูที่: https://blog.stephencleary.com/2009/04/message-framing.html


2

ฉันคิดว่าเพื่อนของคุณกำลังพูดถึง HTTP ไม่ใช่ TCP

HTTP เดิมเป็นโปรโตคอลไร้สัญชาติ: การร้องขอ HTTP แต่ละครั้งจะใช้การเชื่อมต่อ TCP แยกต่างหาก นี่คือเหตุผลที่เราต้องการคุกกี้ (หรือสิ่งที่คล้ายกัน) เพื่อใช้งาน


0

คุณได้กล่าวถึง "การเชื่อมต่อเดียวและต้องการพอร์ตใหม่ทุกครั้ง" และฉันจะตีความว่าคุณมีลูกค้าจำนวนมากที่ใช้เทคนิค PAT ในสภาพแวดล้อมเครือข่ายเดียวกันเพื่อเชื่อมต่อกับเซิร์ฟเวอร์ภายนอกองค์กรของคุณ PAT จะมีขีด จำกัด 65535 (ขีด จำกัด เซสชัน TCP บนที่อยู่ IPv4) ถ้าเป็นจริงคุณมีขีด จำกัด

TCP เปิดการเชื่อมต่อใหม่สำหรับทุกแพ็กเก็ตที่ส่งหรือไม่ ไม่มันไม่นานเท่าที่เซสชัน TCP นั้นถูกต้อง และ ...


0

ผมชอบหน้าวิกิพีเดียที่ดีใน TCP มันแสดงให้เห็นอย่างชัดเจนว่าเกิดอะไรขึ้นกับหมายเลขพอร์ต โดยบังเอิญยังมีบทที่เป็นประโยชน์เกี่ยวกับการใช้ ressource:

การใช้ทรัพยากร

การใช้งานส่วนใหญ่จัดสรรรายการในตารางที่จับคู่เซสชันกับกระบวนการของระบบปฏิบัติการที่กำลังทำงานอยู่ เนื่องจากแพ็กเก็ต TCP ไม่รวมตัวระบุเซสชันปลายทางทั้งสองจึงระบุเซสชันโดยใช้ที่อยู่และพอร์ตของไคลเอ็นต์ เมื่อใดก็ตามที่ได้รับแพ็คเก็ตการใช้งาน TCP จะต้องทำการค้นหาในตารางนี้เพื่อค้นหากระบวนการปลายทาง แต่ละรายการในตารางเรียกว่า Transmission Control Block หรือ TCB มันมีข้อมูลเกี่ยวกับจุดปลาย (IP และพอร์ต) สถานะของการเชื่อมต่อการเรียกใช้ข้อมูลเกี่ยวกับแพ็คเก็ตที่มีการแลกเปลี่ยนและบัฟเฟอร์สำหรับการส่งและรับข้อมูล

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

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

ดังนั้น TCP จะสามารถใช้งานพอร์ตไม่ได้หากลูกค้าเปิดการเชื่อมต่อ TCP จำนวนมากพร้อมกันโดยไม่ต้องปิด ปัญหาเกิดขึ้นเฉพาะฝั่งไคลเอ็นต์และไม่สำคัญว่าการเชื่อมต่อนั้นจะมีที่อยู่ IP ของเซิร์ฟเวอร์เดียวกันหรือต่างกันหรือพอร์ตเซิร์ฟเวอร์

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

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

หากคุณมีลูกค้าเพียงไม่กี่รายเท่านั้นน้อยกว่า 65k-ish และ / หรือคุณเชื่อมต่อกับเบราว์เซอร์ Kafka ของคุณเพียงครั้งเดียว

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