micronaut-core: Regression: HTTP client read timeout since 1.3.1

I just noticed that since 1.3.1 HTTP clients always cause read timeouts, at least when talking with a micronaut server (haven’t tried other cases). When using 1.3.0 or earlier the code behaves as expected. Maybe caused by #2763? That seems to be the main change to HttpClient in 1.3.1. Client timeout setting has no effect on this problem.

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. Checkout example server and client (see links at the end)
  2. run server with gradlew run
  3. run client with gradlew run -> will cause read timeout exception although server received call and replied
  4. change Micronaut version to 1.3.0 or lower in client gradle.properties -> client behaves as expected

Expected Behaviour

Client should receive result from server.

Actual Behaviour

read timeout exception:

Caused by: io.micronaut.http.client.exceptions.ReadTimeoutException: Read Timeout
        at io.micronaut.http.client.exceptions.ReadTimeoutException.<clinit>(ReadTimeoutException.java:26)
        at io.micronaut.http.client.DefaultHttpClient.lambda$null$29(DefaultHttpClient.java:1091)
        at io.reactivex.internal.operators.flowable.FlowableOnErrorNext$OnErrorNextSubscriber.onError(FlowableOnErrorNext.java:103)
        at io.reactivex.internal.operators.flowable.FlowableTimeoutTimed$TimeoutSubscriber.onTimeout(FlowableTimeoutTimed.java:139)
        at io.reactivex.internal.operators.flowable.FlowableTimeoutTimed$TimeoutTask.run(FlowableTimeoutTimed.java:170)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

Environment Information

  • Operating System: Windows 10
  • Micronaut Version: >= 1.3.1
  • JDK Version: 8

Example Application

https://github.com/esocode/micronaut-http-server-test https://github.com/esocode/micronaut-http-client-test

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 1
  • Comments: 24 (16 by maintainers)

Most upvoted comments

@volnei you are performing blocking operations on the netty event loop which is the default for Micronaut 2.0 (see the upgrading section on changes to the threading model https://docs.micronaut.io/latest/guide/index.html#upgrading)

Your problem can be fixed with the following change ( or even better just don’t block):

---
 .../main/java/gateway/WorkerController.java   |  3 ++
diff --git a/gateway/src/main/java/gateway/WorkerController.java b/gateway/src/main/java/gateway/WorkerController.java
index d5cc164..b578643 100644
--- a/gateway/src/main/java/gateway/WorkerController.java
+++ b/gateway/src/main/java/gateway/WorkerController.java
@@ -2,12 +2,15 @@ package gateway;
 
 import io.micronaut.http.annotation.*;
 import io.micronaut.http.HttpResponse;
+import io.micronaut.scheduling.TaskExecutors;
+import io.micronaut.scheduling.annotation.ExecuteOn;
 
 import java.util.Map;
 
 import javax.inject.Inject;
 
 @Controller("/worker")
+@ExecuteOn(TaskExecutors.IO)
 public class WorkerController {
-- 

I also use Micronaut 2.0.0 and have the same issue when I call my client for second time…

I ask because I believe your problem is different

@volnei do you have an example that reproduces the issue?

This can be worked around in 1.3.3 by using event listeners instead. Example:

@Singleton
public class Application {

    @Inject
    private ServiceClient service;

    public static void main(final String[] args) {
        Micronaut.run(Application.class);
    }

    @EventListener
    void runApp(StartupEvent startupEvent) throws MalformedURLException {
        System.out.println(
            "*********************************************************");
        System.out.println(
            "ID of 'Test': " + service.getIdForName("Test").blockingGet());
    }
}