When sending a http request over http2 with jetty client, JettyClientHttpRequest uses org.eclipse.jetty.client.OutputStreamRequestContent to provide the body content. Unfortunately, OutputStreamRequestContent generates some data frame overhead, since it sends all data frames that contains actual data without the END_STREAM flag set - and then when the OutputStreamRequestContent is closed, sends a final empty data frame with the END_STREAM flag set. The more efficient way would be to set the END_STREAM flag in the last data frame that actually contained data ofc.
In cases where the body is relatively small and fit in a single data frame, the effect is that the client sends twice as many data frames as necessary (the first frame with the data, and then the "unnecessary" frame with the END_STREAM flag).
Furthermore, if the bodies are really small, and the server is Tomcat - there is a high risk that the client will trigger Tomcat's "overhead protection", which will make Tomcat close the connection. In my microservice setup using spring-boot with tomcat on the server side and spring-boot with jetty-based RestClient on the client side I'm running into issues similar to https://stackoverflow.com/questions/60049290/closenowexception-this-stream-is-not-writeable and https://stackoverflow.com/questions/61413934/http2-err-connection-closed-too-much-overhead due to this.
To some extent this is a limitation in the Jetty client, but I still believe spring-web can mitigate it to some extent. At least in my case (and I think it is the most common) I have the request executed via a InterceptingClientHttpRequest, which is buffering the body in a byte array. The body is then fed via org.springframework.http.StreamingHttpOutputMessage#setBody(byte[]) to JettyClientHttpRequest which then send it to OutputStreamRequestContent via Body#writeTo. However, since we in practice already have the body in a byte array in this case, we could just as well use e.g. a org.eclipse.jetty.client.BytesRequestContent and thereby avoid the unnecessary data frame. Though, a way to access the byte array from the JettyClientHttpRequest is needed (maybe just a "ByteArrayBody" class implementing StreamingHttpOutputMessage.Body and exposing the byte array?). Or an alternative ClientHttpRequestFactory that creates non-streaming requests for jetty client?
When sending a http request over http2 with jetty client,
JettyClientHttpRequestusesorg.eclipse.jetty.client.OutputStreamRequestContentto provide the body content. Unfortunately,OutputStreamRequestContentgenerates some data frame overhead, since it sends all data frames that contains actual data without the END_STREAM flag set - and then when theOutputStreamRequestContentis closed, sends a final empty data frame with the END_STREAM flag set. The more efficient way would be to set the END_STREAM flag in the last data frame that actually contained data ofc.In cases where the body is relatively small and fit in a single data frame, the effect is that the client sends twice as many data frames as necessary (the first frame with the data, and then the "unnecessary" frame with the END_STREAM flag).
Furthermore, if the bodies are really small, and the server is Tomcat - there is a high risk that the client will trigger Tomcat's "overhead protection", which will make Tomcat close the connection. In my microservice setup using spring-boot with tomcat on the server side and spring-boot with jetty-based RestClient on the client side I'm running into issues similar to https://stackoverflow.com/questions/60049290/closenowexception-this-stream-is-not-writeable and https://stackoverflow.com/questions/61413934/http2-err-connection-closed-too-much-overhead due to this.
To some extent this is a limitation in the Jetty client, but I still believe spring-web can mitigate it to some extent. At least in my case (and I think it is the most common) I have the request executed via a
InterceptingClientHttpRequest, which is buffering the body in a byte array. The body is then fed viaorg.springframework.http.StreamingHttpOutputMessage#setBody(byte[])toJettyClientHttpRequestwhich then send it toOutputStreamRequestContentviaBody#writeTo. However, since we in practice already have the body in a byte array in this case, we could just as well use e.g. aorg.eclipse.jetty.client.BytesRequestContentand thereby avoid the unnecessary data frame. Though, a way to access the byte array from theJettyClientHttpRequestis needed (maybe just a "ByteArrayBody" class implementingStreamingHttpOutputMessage.Bodyand exposing the byte array?). Or an alternativeClientHttpRequestFactorythat creates non-streaming requests for jetty client?