I understand that HTTP2 in Jetty is mostly at the Connector, Transport and Channel levels.
I'm trying to decide which combination would be the best to transport binary data between client and server:
Details:
I would like to send binary data to my client and I would like the connections to be non-blocking/async. The number of concurrent client requests can be high and the server could take a few seconds (some times) to respond to some requests.
Each response is small chunk of binary data. I would've liked it if I could send Netty's ByteBufs
directly as the response instead of copying to byte[]
or ByteBuffer
but that is not directly related to this particular question.
Method #4 is not my favorite because of the ProtoBuf wrapping (link) limitation (link).
Jetty references:
Disclaimer, I am the Jetty HTTP/2 maintainer.
Given that you have a large number of clients and that processing could take seconds, I would recommend to go with option 1 - async servlet and Jetty HTTP/2 client.
With "async servlet" you have 2 flavors: 1) async processing with blocking I/O, or 2) async processing + async I/O.
Servlet async processing is triggered by the use of HttpServletRequest.startAsync()
.
Servlet async I/O is triggered by using ReadListener
and WriteListener
respectively with the ServletInputStream
and ServletOutputStream
.
You definitely want async processing because you have a large number of clients and processing in the order of seconds - this will optimize the use of server threads.
Whether or not to use async I/O should probably be measured, since you have small binary responses. Blocking I/O is much much easier to code and debug, while async I/O is definitely more complicated to code and debug. Async I/O really shines when you have large contents and slow clients that may congest the TCP connection.
If you want to be fully async, go with async I/O. If you can tolerate a bit of blocking in exchange of simpler code, stay on blocking I/O. Worth repeating, in both cases - either async I/O or blocking I/O - you want to use async processing.
Regarding the issue of copying data, if you are willing to cast down to Jetty classes, you can avoid the copy by directly writing a ByteBuffer
to the ServletOutputStream
subclass, see this example.
Finally, with the Jetty client you can use the high-level HttpClient
with the HTTP/2 transport as detailed here. The benefit would be a high-level API that only deals with HTTP concepts, rather than using the low-level HTTP2Client
that deals with HTTP/2 frames, streams and such.
Report back what you end up choosing, and how it goes for you !