ffang commented on PR #3640:
URL: https://github.com/apache/cxf/pull/3640#issuecomment-6451495974

   > Hi @ffang , I tested this solution against my camel reproducer and it 
LGTM... all my attempts were good 💯 .
   > 
   > Just out of curiosity, given your knowledge of the codebase, I wonder why 
this particular problem showed up mainly in local test with wiremock ... and 
it's occurring in production only to a very minor extent. My assumption of a 
networks difference could be the cause for the race condition to happens more 
frequently only in localhost... as I mentioned in the Jira ticket? I am a very 
curious person :) . I tried debug further, but the game wasn't worth the candle 
and didn't have much time.
   > 
   > Thank, Valentino Porta
   
   Hi @vp340,
   
   Thanks for testing the fix against your Camel reproducer, and for confirming 
it works. That's very helpful.
   
   I think your network theory is right in spirit. It's a race between two 
threads, so anything that changes their relative timing changes how often it 
shows up.
   
   With chunking disabled, CXF buffers the request and gives the `HttpClient` a 
publisher that reports the buffered size. For an asynchronous call, two things 
happen in parallel:
   
   - **The caller thread** writes the body into the buffer and closes the 
stream. Closing hands the response handling to the work queue without waiting, 
then drops the buffer (`pout = null` and `publisher.close()`).
   - **The `HttpClient` thread** gets a connection (a new one or a pooled one), 
asks for the content length, writes the request headers, and only then 
subscribes to the body.
   
   In the old code, the body was sent only if the `HttpClient` finished all of 
that before the caller dropped the buffer. If it was too late, it got either 
`0/206` ("Too few bytes returned by the publisher") or a chunked request with 
no body. Which thread wins depends on:
   
   - whether the connection is new or reused, and the latency to open it;
   - how long the headers take to write;
   - how much of the body was already buffered when the send started;
   - JIT warm-up;
   - thread scheduling and load on the machine.
   
   That fits what you saw. The first call is slow on the caller side (cold 
JVM), so the `HttpClient` wins. Against a local WireMock everything after that 
is warm and fast, so the caller wins every time. With a remote server or a 
production network, the timing varies, so the outcome varies too. I haven't 
measured exactly why your production setup lands at 0.01%, but I wouldn't read 
too much into the exact numbers.
   
   With this PR the publisher keeps its own reference to the buffered body, so 
the order of the two threads no longer matters. Once it's in, you shouldn't 
need `cxf-rt-transports-http-hc` or `AllowChunking=true` as a workaround.
   
   Thanks,
   Freeman


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to