You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by "Steffen Heil (Mailinglisten)" <li...@steffen-heil.de> on 2015/08/25 14:15:14 UTC

Asynchronous writes (Servlet and WebSocket)

Hi


I am investigating, how I can archive asynchronous writes with tomcat.

For servlets I came up with code like this:
	final AsyncContext context = request.startAsync();
	final ServletInputStream input = request.getInputStream();
	final ServletOutputStream output = response.getOutputStream();
	ChannelProcessor processor = new ChannelProcessor( channel, input, output );
	context.addListener( processor );
	input.setReadListener( processor );
	output.setWriteListener( processor );

While ChannelProcessor is my class that implements (beside others) WriteListener, so I get notified, when the ServletOutputStream is ready to send more data.
However, looking at the code, I suspect that "output.write( byte[] buffer )" will still block, if the amount of data in buffer is larger than the maximum size of the OutputBuffer used by that connection:

Call stack:
  CoyoteOutputStream.write   (is ServletOutputStream.write)
  OutputBuffer.write
  ByteChunk.append
  ByteChunk.flushBuffer
  OutputBuffer.realWriteBytes
... from here on I am not sure.


For WebSockets there is
	session.getAsyncRemote().sendBinary( buffer, handkler );

But that calls ServletOutputStream.write (maybe from another thread)


So, are these really asynchronous?
Is a call to ServletOutputStream.write always guaranteed to return without blocking?`
Where is that implemented?


Regards,
  Steffen


Re: AW: Asynchronous writes (Servlet and WebSocket)

Posted by Mark Thomas <ma...@homeinbox.net>.
On 26 August 2015 08:30:38 BST, "Steffen Heil (Mailinglisten)" <li...@steffen-heil.de> wrote:

>> No. It is too invasive to back port to the stable 8.0.x and it also
>requires removing support for BIO and comet which we don't want to
>> do in 8.0.x.
>
>Will this be rather a 8.1.x (mid term) or 9.0.x (long term) change?

It will be in 9.0.x. It is TBD if there will be a 8.1.x branch. We don't often do it. The possibility has been raised but no plans to do it at the moment.

>Is the code in trunk considered stable?

Yes, excluding the HTTP/2 which a) is still in development and b) I know I can easily crash.

Cheers,

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


AW: AW: Asynchronous writes (Servlet and WebSocket)

Posted by "Steffen Heil (Mailinglisten)" <li...@steffen-heil.de>.
Hi


> The equivalent code for NIO is in
> org.apache.coyote.http11.InternalNioOutputBuffer

Thanks for the reference. I took a short look at it.
As soon as I have a little time left, I will analyze it in more depth, as I am very interested in NIO...
For now the assertion that write are indeed asynchronous is enough for me.


> No. It is too invasive to back port to the stable 8.0.x and it also requires removing support for BIO and comet which we don't want to
> do in 8.0.x.

Will this be rather a 8.1.x (mid term) or 9.0.x (long term) change?
Is the code in trunk considered stable?


> 8.0.x releases are on a roughly monthly cycle. The most recent (8.0.26) was announced today.

Thanks for the hint, I missed that one.


Regards,
  Steffen


Re: AW: Asynchronous writes (Servlet and WebSocket)

Posted by Mark Thomas <ma...@apache.org>.
On 25/08/2015 17:02, Steffen Heil (Mailinglisten) wrote:

>>> Where is that implemented?
>> The detail varies between versions due to the refactoring that has gone on over time in the connectors but in trunk that is all handled
>> by SocketWrapperBase.writeNonBlocking()
> 
> I am using 8.0.24. There I did not find such a class.

The equivalent code for NIO is in
org.apache.coyote.http11.InternalNioOutputBuffer

Similar code exists in the other implementations for the other connectors.

>> Generally, the trunk code should be easier to follow because of the refactoring.
> 
> Will these refactorings be in the next release?

No. It is too invasive to back port to the stable 8.0.x and it also
requires removing support for BIO and comet which we don't want to do in
8.0.x.

> When is it due?

8.0.x releases are on a roughly monthly cycle. The most recent (8.0.26)
was announced today.

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


AW: Asynchronous writes (Servlet and WebSocket)

Posted by "Steffen Heil (Mailinglisten)" <li...@steffen-heil.de>.
Hi


Thanks for assuring me, that it really is asynchronous. That was a blocker for us.


> archive? I'm guessing you mean achieve.

Yes, I did. Sorry, not a native English speaker...


> No, it will buffer it all in the SocketWrapper. You won't get another notification until the buffered data has been written.

Ok.


> Yes, assuming you are not using the BIO connector (where it always blocks regardless).

NIO only.


> > Where is that implemented?
> The detail varies between versions due to the refactoring that has gone on over time in the connectors but in trunk that is all handled
> by SocketWrapperBase.writeNonBlocking()

I am using 8.0.24. There I did not find such a class.


> Generally, the trunk code should be easier to follow because of the refactoring.

Will these refactorings be in the next release? When is it due?


Best regards,
  Steffen


Re: Asynchronous writes (Servlet and WebSocket)

Posted by Mark Thomas <ma...@apache.org>.
On 25/08/2015 13:15, Steffen Heil (Mailinglisten) wrote:
> Hi
> 
> I am investigating, how I can archive asynchronous writes with tomcat.

archive? I'm guessing you mean achieve.

> For servlets I came up with code like this:
> 	final AsyncContext context = request.startAsync();
> 	final ServletInputStream input = request.getInputStream();
> 	final ServletOutputStream output = response.getOutputStream();
> 	ChannelProcessor processor = new ChannelProcessor( channel, input, output );
> 	context.addListener( processor );
> 	input.setReadListener( processor );
> 	output.setWriteListener( processor );
> 
> While ChannelProcessor is my class that implements (beside others) WriteListener, so I get notified, when the ServletOutputStream is ready to send more data.
> However, looking at the code, I suspect that "output.write( byte[] buffer )" will still block, if the amount of data in buffer is larger than the maximum size of the OutputBuffer used by that connection:

No, it will buffer it all in the SocketWrapper. You won't get another
notification until the buffered data has been written.

> For WebSockets there is
> 	session.getAsyncRemote().sendBinary( buffer, handkler );
> 
> But that calls ServletOutputStream.write (maybe from another thread)

Same as above.

> So, are these really asynchronous?

Yes.

> Is a call to ServletOutputStream.write always guaranteed to return without blocking?`

Yes, assuming you are not using the BIO connector (where it always
blocks regardless).

> Where is that implemented?

The detail varies between versions due to the refactoring that has gone
on over time in the connectors but in trunk that is all handled by
SocketWrapperBase.writeNonBlocking()

Generally, the trunk code should be easier to follow because of the
refactoring.

HTH,

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org