JDK-6968351 : httpserver clashes with delayed TCP ACKs for low Content-Length
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6u21,11,17,19
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_2008
  • CPU: x86
  • Submitted: 2010-07-12
  • Updated: 2024-04-23
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0_21"
Java(TM) SE Runtime Environment (build 1.6.0_21-b06)
Java HotSpot(TM) Client VM (build 17.0-b16, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Windows Server 2008 64bit Standard SP2
Windows Server 2003 64bit Standard SP2

EXTRA RELEVANT SYSTEM CONFIGURATION :
Standard TCP settings (esp. no registry entry for TcpAckFrequency)

A DESCRIPTION OF THE PROBLEM :
Httpserver slows down to about requests/minute when accessing URLs with small Contents-Length (<= 1000, typically, depending on headers).

This is due to the use of nio together with the fact that nttp server wites to the output channel twice, once to write the headers and once to write the response body. This clashes with the Windows TCP-Stack implementation and RFC1122.

On the TCP level, this can be seen as follows:

(1) Server writes out one TCP packet for the headers (with PSH).
(2) Client receives the packet but does not send ACK because it had received only ONE packet (RFC1122).
(3) Server applications writes to the channel, but OS does not send TCP packet for the response body, because there is no ACK and the internal write buffer still holds less than the MSS (typ. 1460 bytes), see RFC 1122, sect. 4.2.3.4.
(4) Over 100ms later, Client OS sends delayed ACK
(5) Server OS responds with response TCP packet (with PSH)

This can be ameliorated by setting TcpAckFrequency=1 on the client side, but this is not an option for a production environment.

FIX: Write the whole HTTP response message in one write to the channel.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Clear from description

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Performance should scale like the RTT of the network path.
ACTUAL -
Performance is dominated by delayed ACT timer, i.e 100-200ms per request.

REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER SUBMITTED WORKAROUND :
No workaround for httpserver. Setting TCP_NODELAY on the socket does not help, but this seems to be another general problem.

Comments
A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/18667 Date: 2024-04-06 23:35:48 +0000
18-04-2024

To prevent this issue, the HttpServer (Java process) can be started by passing the following system property: -Dsun.net.httpserver.nodelay=true This will cause the HttpServer code to set the TCP_NODELAY socket option on the socket accept()ed by the server from a client connection. Doing so prevents the delays in receiving the response content.
30-09-2022

This affects Linux too as noticed in https://bugs.openjdk.org/browse/JDK-8294610
30-09-2022