Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Jetty 9.2.13 DefaultServlet static file download error ; HP Nonstop (Tandem) Operating system

Hi,

On Tue, Dec 15, 2015 at 12:04 PM, Sakthivel.P <p.stivel@xxxxxxxxx> wrote:
>
> Dear Simone& Joakim,
>
> I would like to explain the issue in more detail. There are two issues;
>
> 1.DefaultServlet does not respect the outputBufferSize (32k) when using NIO
>
> When serving static files, Jetty tries to send the whole file in one message to TCPIP. This causes a problem on HP NonStop as the maximum size can be only 52K. Normal application responses are broken into 32K  pieces.

The outputBufferSize is the size of the buffer where application
content is copied to.
This is an important optimization for applications that write very
small chunks of data: we don't issue a TCP write() for every
application write.
Instead, we copy the application write data into the output buffer.
When the buffer is full (and in other conditions as well) we issue the
TCP write of the buffer.
This is a huge optimization that every server does.

When writing files, we don't need to copy any data from the file
system into the output buffer.
We typically have a direct buffer pointing to the file, and we just
ask the JVM to write that, whatever size the file is.
All JVMs can do that, apart Non-Stop, which has this 52 KiB limit.

> By commenting out code where the buffer is writing through GatheringByteChannel in public boolean flush(ByteBuffer... buffers) method in org.eclipse.jetty.io.ChannelEndPoint.Java class the defaultServlet also successfully served large files properly.
>
> @Override
>     public boolean flush(ByteBuffer... buffers) throws IOException
>     {
>         int flushed=0;
>         try
>         {
>             if (buffers.length==1)
>                 flushed=_channel.write(buffers[0]);
>             //else if (buffers.length>1 && _channel instanceof GatheringByteChannel) //commented this line
>              //   flushed= (int)((GatheringByteChannel)_channel).write(buffers,0,buffers.length); // and this line
>             else
>             {
>                 for (ByteBuffer b : buffers)
>                 {
>                     if (b.hasRemaining())
>                     {
>                         int l=_channel.write(b);
>                         if (l>0)
>                             flushed+=l;
>                         if (b.hasRemaining())
>                             break;
>                     }
>                 }
>             }
>             ...
>         }
>         ...
>     }
>
> I do not know why the code the way it is. This never happened on Jetty using BIO. It shows up with NIO on Jetty 8 and Jetty 9. This must be a bug; why should outbuffersize not be followed ?

See above.
Commenting out that code will have huge performance impacts on all other JVMs.

Jetty currently does not have a configuration option for
DefaultServlet to force usage of the output buffer.
One trick that you can use is to wrap the ServletOutputStream.
Jetty does not perform optimized writes if it finds that the
ServletOutputStream has been wrapped by the application.

> 2.Woff and Woff2 files are not being downloaded by defaultServlet (only on the NonStop)
>
> Before the above change, AwesomeFont woff, woof2 and ttf files could not come down as they are larger than 52K.
> After the above change all files of all sorts larger than 52K successfully come, including awesomefont ttf file.
> However, woff and woff2 files do not. For some reason, the browsers disconnect the connection. Jetty sees a remote disconnect error.

This is an unrelated error, and will need more investigation on the
browser side on why it closes the connection.

-- 
Simone Bordet
----
http://cometd.org
http://webtide.com
Developer advice, training, services and support
from the Jetty & CometD experts.


Back to the top