-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Description
Version
5.0.5
Context
OS: Linux 6.17.0-6-generic #6-Ubuntu SMP PREEMPT_DYNAMIC Tue Oct 7 13:34:17 UTC 2025 x86_64 GNU/Linux (Kubuntu 25.10)
JVM: openjdk 21.0.9 2025-10-21
project link: https://github.com/kvr000/zbynek-java-exp/tree/master/http-exp/http-benchmark
In HttpClient streaming, Vertx seems to start pushing buffers prior to Future.onSuccess((HttpResponse) -> {}) is completed. As the stream handler is typically in that function, this results in loss of data:
In the github link, I provided benchmark, b3_VertxHttpClient is the randomly failing method - typically it misses about 2000 bytes - that indicates very close race condition.
In order to simulate bigger difference, I added sleep(1000) before registering onSuccess() callback and then it misses 1 GB.
Here is the additional snippet to the project:
@Benchmark
public void a0_VertxHttpClient(VertxHttpClientState state, Blackhole blackhole) throws Exception
{
MutableLong size = new MutableLong();
Future<HttpClientResponse> future = state.httpClient.request(HttpMethod.GET, "/big_16GB")
.compose(HttpClientRequest::send);
Thread.sleep(1000);
future.onSuccess((HttpClientResponse response) -> {
if (response.statusCode() != 200) {
Try.of(() -> { throw new IOException("Failed to retrieve file: status=" + response.statusCode()); }).get();
}
response.handler((buffer) -> size.add(buffer.length()));
});
future.await().end().await();
if (future.await().statusCode() != 200) {
throw new IllegalStateException("Unexpected status: " + future.await().statusCode());
}
if (size.longValue() != 16L*1024*1024*1024) {
throw new IllegalStateException("Unexpected size: " + size);
}
blackhole.consume(size.longValue());
}
Steps to reproduce
- Run the benchmark provided in the project.
- b3_VertxHttpClient will randomly fail with exception: java.io.IOException: Unexpected size: 17179865088
More reliable failure:
@Benchmark
public void a0_VertxHttpClient(VertxHttpClientState state, Blackhole blackhole) throws Exception
{
MutableLong size = new MutableLong();
Future<HttpClientResponse> future = state.httpClient.request(HttpMethod.GET, "/big_16GB")
.compose(HttpClientRequest::send);
Thread.sleep(1000);
future.onSuccess((HttpClientResponse response) -> {
if (response.statusCode() != 200) {
Try.of(() -> { throw new IOException("Failed to retrieve file: status=" + response.statusCode()); }).get();
}
response.handler((buffer) -> size.add(buffer.length()));
});
future.await().end().await();
if (future.await().statusCode() != 200) {
throw new IllegalStateException("Unexpected status: " + future.await().statusCode());
}
if (size.longValue() != 16L*1024*1024*1024) {
throw new IllegalStateException("Unexpected size: " + size);
}
blackhole.consume(size.longValue());
}
Do you have a reproducer?
https://github.com/kvr000/zbynek-java-exp/tree/master/http-exp/http-benchmark