การออกแบบการตัดสินค้าจากคลัง - ส่งเซ็กเมนต์เล็กข้อมูลทาง TCP ที่มี Winsock

การแปลบทความ การแปลบทความ
หมายเลขบทความ (Article ID): 214397
ขยายทั้งหมด | ยุบทั้งหมด

เนื้อหาบนหน้านี้

สรุป

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

ข้อมูลเพิ่มเติม

background:

เมื่อมีการกองซ้อน Microsoft TCP ได้รับแพคเก็ตข้อมูล ตัวจับเวลาหน่วง 200 ms ไปออก เมื่อ ACK ถูกส่ง จนตัวจับเวลาหน่วงเวลาถูกตั้งค่าใหม่ และจะเริ่มต้นล่าช้า 200 ms อื่นเมื่อมีรับแพคเก็ตข้อมูลถัดไป เมื่อต้องการเพิ่มประสิทธิภาพในอินเทอร์เน็ตและอินทราเน็ตโปรแกรมประยุกต์ กองซ้อน Microsoft TCP ใช้เงื่อนไขต่อไปนี้เพื่อตัดสินใจได้ว่า เมื่อส่ง ACK หนึ่งในแพ็กเก็ตข้อมูลที่ได้รับ:
  • หากได้รับแพคเก็ตที่สองของข้อมูลก่อนที่หมดอายุของตัวจับเวลาหน่วงเวลา ACK ถูกส่งไป
  • ถ้าไม่มีข้อมูลที่จะส่งไปในทิศทางเดียวกันเป็น ACK นั้นก่อนที่ได้รับแพคเก็ตข้อมูลที่สอง และตัวจับเวลาหน่วงเวลาหมดอายุ ACK อยู่ piggybacked กับเซ็กเมนต์ข้อมูล และส่งทันที
  • เมื่อตัวจับเวลาหน่วงเวลาหมดอายุ ACK ที่ถูกส่งไป
เพื่อหลีกเลี่ยงการมีแพคเก็ตข้อมูลขนาดเล็กที่ congest เครือข่าย กองซ้อน Microsoft TCP ทำให้อัลกอริทึมการ Nagle โดยค่าเริ่มต้น ซึ่ง coalesces บัฟเฟอร์ข้อมูลขนาดเล็กที่จากหลายสายโทรส่งและความล่าช้าในการส่งออกจนกว่าส่งข้อ ACK สำหรับแพคเก็ตข้อมูลก่อนหน้านี้ได้รับจากโฮสต์ระยะไกล ต่อไปนี้เป็นข้อยกเว้นอัลกอริทึม Nagle สอง:
  • ถ้ามีการกองซ้อน coalesced บัฟเฟอร์ข้อมูลขนาดใหญ่กว่าค่าสูงสุดส่งต่อหน่วย (MTU), แพคเก็ตที่ขนาดเต็มส่งทันทีโดยไม่ได้กำลังรอการ ACK จากโฮสต์ระยะไกล บนเครือข่ายอีเทอร์เน็ตแบบ MTU สำหรับ TCP/IP เป็นไบต์ 1460
  • มีใช้ตัวเลือกการซ็อกเก็ต TCP_NODELAY เพื่อปิดการใช้อัลกอริทึมการ Nagle เพื่อที่แพคเก็ตข้อมูลขนาดเล็กมีการจัดส่งไปยังโฮสต์ระยะไกลโดยไม่มีการหน่วงเวลา
เพื่อปรับประสิทธิภาพการทำงานในชั้นแอพลิเคชัน Winsock สำเนาข้อมูลบัฟเฟอร์จากแอพลิเคชันส่งการเรียกการบัฟเฟอร์การเคอร์เนล Winsock จากนั้น กองซ้อนใช้ heuristics ของตนเอง (เช่นอัลกอริทึม Nagle) เพื่อตรวจสอบที่แท้จริงแล้ว ใส่แพคเก็ตบนสาย คุณสามารถเปลี่ยนยอดเงินของบัฟเฟอร์เคอร์เนล Winsock ที่ปันส่วนไปยังซ็อกเก็ตที่ใช้ตัวเลือก SO_SNDBUF (เป็นกิโล 8 โดยค่าเริ่มต้น) If necessary, Winsock can buffer significantly more than the SO_SNDBUF buffer size. In most cases, the send completion in the application only indicates the data buffer in an application send call is copied to the Winsock kernel buffer and does not indicate that the data has hit the network medium. The only exception is when you disable the Winsock buffering by setting SO_SNDBUF to 0.

Winsock uses the following rules to indicate a send completion to the application (depending on how the send is invoked, the completion notification could be the function returning from a blocking call, signaling an event or calling a notification function, and so forth):
  • If the socket is still within SO_SNDBUF quota, Winsock copies the data from the application send and indicates the send completion to the application.
  • If the socket is beyond SO_SNDBUF quota and there is only one previously buffered send still in the stack kernel buffer, Winsock copies the data from the application send and indicates the send completion to the application.
  • If the socket is beyond SO_SNDBUF quota and there is more than one previously buffered send in the stack kernel buffer, Winsock copies the data from the application send. Winsock does not indicate the send completion to the application until the stack completes enough sends to put the socket back within SO_SNDBUF quota or only one outstanding send condition.

Case Study 1

Overview:

A Winsock TCP client needs to send 10000 records to a Winsock TCP server to store in a database. The size of the records varies from 20 bytes to 100 bytes long. To simplify the application logic, the design is as follows:
  • The client does blocking send only. The server does blocking recv only.
  • The client socket sets the SO_SNDBUF to 0 so that each record goes out in a single data segment.
  • The server calls recv in a loop. The buffer posted in recv is 200 bytes so that each record can be received in one recv call.

Performance:

During testing, the developer finds the client could only send five records per second to the server. The total 10000 records, maximum at 976K bytes of data (10000 * 100 / 1024), takes more than half an hour to send to the server.

Analysis:

Because the client does not set the TCP_NODELAY option, the Nagle algorithm forces the TCP stack to wait for an ACK before it can send another packet on the wire. However, the client has disabled the Winsock buffering by setting the SO_SNDBUF option to 0. Therefore, the 10000 send calls have to be sent and ACK'ed individually. Each ACK is delayed 200-ms because the following occurs on the server's TCP stack:
  • When the server gets a packet, its 200-ms delay timer goes off.
  • The server does not need to send anything back, so the ACK cannot be piggybacked.
  • The client will not send another packet unless the previous packet is acknowledged.
  • The delay timer on the server expires and the ACK is sent back.

How to Improve:

There are two problems with this design. First, there is the delay timer issue. The client needs to be able to send two packets to the server within 200-ms. Because the client uses the Nagle algorithm by default, it should just use the default Winsock buffering and not set SO_SNDBUF to 0. Once the TCP stack has coalesced a buffer larger than the Maximum Transmission Unit (MTU), a full-sized packet is sent immediately without waiting for the ACK from the remote host.

Secondly, this design calls one send for each record of such small size. Sending this small of a size is not very efficient. In this case, the developer might want to pad each record to 100 bytes and send 80 records at a time from one client send call. To let the server know how many records will be sent in total, the client might want to start off the communication with a fix-sized header containing the number of records to follow.

Case Study 2

Overview:

A Winsock TCP client application opens two connections with a Winsock TCP server application providing stock quotes service. The first connection is used as a command channel to send the stock symbol to the server. The second connection is used as a data channel to receive the stock quote. After the two connections have been established, the client sends a stock symbol to the server through the command channel and waits for the stock quote to come back through the data channel. It sends the next stock symbol request to the server only after the first stock quote has been received. The client and the server do not set the SO_SNDBUF and TCP_NODELAY option.

Performance:

During testing, the developer finds the client could only get five quotes per second.

Analysis:

This design only allows one outstanding stock quote request at a time. The first stock symbol is sent to the server through the command channel (connection) and a response is immediately sent back from the server to the client over the data channel (connection). Then, the client immediately sends the second stock symbol request and the send returns immediately as the request buffer in the send call is copied to the Winsock kernel buffer. However, the client TCP stack cannot send the request from its kernel buffer immediately because the first send over the command channel is not acknowledged yet. After the 200-ms delay timer at the server command channel expires, the ACK for the first symbol request comes back to the client. Then, the second quote request is successfully sent to the server after being delayed for 200-ms. The quote for the second stock symbol comes back immediately through the data channel because, at this time, the delay timer at the client data channel has expired. An ACK for the previous quote response is received by the server. (Remember that the client could not send a second stock quote request for 200-ms, thus giving time for the delay timer on the client to expire and send an ACK to the server.) As a result, the client gets the second quote response and can issue another quote request, which is subject to the same cycle.

How to Improve:

The two connection (channel) design is unnecessary here. If you use only one connection for the stock quote request and response, the ACK for the quote request can be piggybacked on the quote response and come back immediately. To further improve the performance, the client could "multiplex" multiple stock quote requests into one send call to the server and the server could also "multiplex" multiple quote responses into one send call to the client. If the two unidirectional channel design is really necessary for some reason, both sides should set the TCP_NODELAY option so that the small packets can be sent immediately without having to wait for an ACK for the previous packet.

Recommendations:

While these two case studies are fabricated, they help to illustrate some worst case scenarios. When you design an application that involves extensive small data segment sends and recvs, you should consider the following guidelines:
  • ถ้าข้อมูลมีเซ็กเมนต์ไม่เวลาสำคัญ แอพลิเคชันควร coalesce เหล่านั้นลงในบล็อกข้อมูลที่มีขนาดใหญ่เพื่อส่งต่อไปยังการเรียกส่ง เนื่องจากบัฟเฟอร์การส่งมักจะถูกคัดลอกไปบัฟเฟอร์ของเคอร์เนล Winsock บัฟเฟอร์ที่ไม่ควรเกินไป มีสักเล็กน้อยกว่า 8 K คือมักจะมีผลบังคับใช้ ตราบเท่าที่เคอร์เนล Winsock ได้บล็อกขนาดใหญ่กว่า MTU มันจะส่งออกจากแพคเก็ตขนาดเต็มหลายและแพคเก็ตที่สุดท้ายกับสิ่งที่เหลือ จะไม่มีกดส่งด้าน ยกเว้นแพคเก็ตล่าสุด โดยตัวจับเวลาการหน่วงเวลา 200 ms แพคเก็ตล่าสุด เกิดขึ้นเป็น กลุ่มการลำดับเลข odd ข้อมูล ว่ายังคงกับอัลกอริทึมการยอมรับล่าช้า ถ้ามีการกองซ้อนสิ้นส่งได้บล็อกอื่นมีขนาดใหญ่กว่า MTU คุณสามารถข้ามอัลกอริทึมการ Nagle ยังคง
  • ถ้าเป็นไปได้ หลีกเลี่ยงการเชื่อมต่อซ็อกเก็ตกับกระแสข้อมูล unidirectional การสื่อสารผ่านซ็อกเก็ต unidirectional คือ มากกว่า impacted โดย Nagle ง่าย และ algorithms ยอมรับที่ถูกหน่วงเวลา ถ้ามีการสื่อสารตามการร้องขอและการไหลของการตอบสนอง คุณควรใช้ซ็อกเก็ตเดียวการส่งและ recvs เพื่อให้สามารถถูก piggybacked ACK นั้นในการตอบสนอง
  • ถ้าเซ็กเมนต์ข้อมูลขนาดเล็กทั้งหมดที่มีการส่งออกในทันที กำหนดตัวเลือกการ TCP_NODELAY ในท้ายที่ส่ง
  • นอกจากว่าคุณต้องการรับประกันการส่งแพคเก็ตไปบนสายเมื่อมีระบุการดำเนินการเสร็จสมบูรณ์ส่ง โดย Winsock คุณควรกำหนด SO_SNDBUF ที่เป็นศูนย์ไม่ บัฟเฟอร์การ 8 K เริ่มต้นได้ถูกกำหนด heuristically การทำงานดีสำหรับสถานการณ์ส่วนใหญ่ใน fact และคุณไม่ควรเปลี่ยนแปลงได้เว้นแต่ว่าคุณได้ทดสอบให้คุณตั้งค่าใหม่ของบัฟเฟอร์ Winsock ให้ประสิทธิภาพการทำงานได้ดีกว่าค่าเริ่มต้น นอกจากนี้ เซ็ต SO_SNDBUF กับศูนย์ได้ mostly beneficial สำหรับโปรแกรมประยุกต์จำนวนมากการถ่ายโอนข้อมูล แม้แต่ สำหรับการประสิทธิภาพสูงสุด คุณควรใช้ร่วมกับสองครั้งที่การกำหนดบัฟเฟอร์ (มากกว่าหนึ่งคงค้างส่งทุกเวลาที่กำหนด) แล้ว overlapped I/O
  • ถ้าการส่งข้อมูลที่ไม่มีการให้มีการ ใช้ UDP

ข้อมูลอ้างอิง

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการยอมรับที่ถูกหน่วงเวลาและอัลกอริทึมการ Nagle โปรดดูที่ตัวเลือกต่อไปนี้:

Braden, R. [1989], RFC 1122 ข้อกำหนดของงานวิศวกรรมอินเทอร์เน็ตของอินเทอร์เน็ตโฮสต์--เยอร์การสื่อสาร บังคับ

คุณสมบัติ

หมายเลขบทความ (Article ID): 214397 - รีวิวครั้งสุดท้าย: 8 มกราคม 2554 - Revision: 2.0
Keywords: 
kbdswnet2003swept kbapi kbinfo kbip kbnetwork kbwinsock kbmt KB214397 KbMtth
แปลโดยคอมพิวเตอร์
ข้อมูลสำคัญ: บทความนี้แปลโดยซอฟต์แวร์การแปลด้วยคอมพิวเตอร์ของ Microsoft แทนที่จะเป็นนักแปลที่เป็นบุคคล Microsoft มีบทความที่แปลโดยนักแปลและบทความที่แปลด้วยคอมพิวเตอร์ เพื่อให้คุณสามารถเข้าถึงบทความทั้งหมดในฐานความรู้ของเรา ในภาษาของคุณเอง อย่างไรก็ตาม บทความที่แปลด้วยคอมพิวเตอร์นั้นอาจมีข้อบกพร่อง โดยอาจมีข้อผิดพลาดในคำศัพท์ รูปแบบการใช้ภาษาและไวยากรณ์ เช่นเดียวกับกรณีที่ชาวต่างชาติพูดผิดเมื่อพูดภาษาของคุณ Microsoft ไม่มีส่วนรับผิดชอบต่อความคลาดเคลื่อน ความผิดพลาดหรือความเสียหายที่เกิดจากการแปลเนื้อหาผิดพลาด หรือการใช้บทแปลของลูกค้า และ Microsoft มีการปรับปรุงซอฟต์แวร์การแปลด้วยคอมพิวเตอร์อยู่เป็นประจำ
ต่อไปนี้เป็นฉบับภาษาอังกฤษของบทความนี้:214397

ให้ข้อเสนอแนะ

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com