3

我有一个提供 REST API 的 Grails 4 应用程序。其中一个端点有时会失败,但会出现以下异常:

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$10.exceptionCaught(DefaultHttpClient.java:1917)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:297)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:276)
    at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:268)
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireExceptionCaught(CombinedChannelDuplexHandler.java:426)
    at io.netty.channel.ChannelHandlerAdapter.exceptionCaught(ChannelHandlerAdapter.java:92)
    at io.netty.channel.CombinedChannelDuplexHandler$1.fireExceptionCaught(CombinedChannelDuplexHandler.java:147)
    at io.netty.channel.ChannelInboundHandlerAdapter.exceptionCaught(ChannelInboundHandlerAdapter.java:143)
    at io.netty.channel.CombinedChannelDuplexHandler.exceptionCaught(CombinedChannelDuplexHandler.java:233)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:297)
    at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:276)
    at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:268)
    at io.netty.handler.timeout.ReadTimeoutHandler.readTimedOut(ReadTimeoutHandler.java:98)
    at io.netty.handler.timeout.ReadTimeoutHandler.channelIdle(ReadTimeoutHandler.java:90)
    at io.netty.handler.timeout.IdleStateHandler$ReaderIdleTimeoutTask.run(IdleStateHandler.java:505)
    at io.netty.handler.timeout.IdleStateHandler$AbstractIdleTask.run(IdleStateHandler.java:477)
    at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38)
    at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:127)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:405)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:906)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:834)

端点使用 micronaut http 客户端调用其他系统。远程系统需要很长时间才能响应,导致 ReadTimeOutException。

这是调用远程服务的代码:

class RemoteTaskService implements GrailsConfigurationAware {

    String taskStepperUrl

    // initializes fields from configuration
    void setConfiguration(Config config) {
        taskStepperUrl = config.getProperty('services.stepper')
    }

    private BlockingHttpClient getTaskClient() {
        HttpClient.create(taskStepperUrl.toURL()).toBlocking()
    }

    List<Map> loadTasksByProject(long projectId) {
        try {
            retrieveRemoteList("/api/tasks?projectId=${projectId}")
        } catch(HttpClientResponseException e) {
            log.error("Loading tasks of project failed with status: ${e.status.code}: ${e.message}")
            throw new NotFoundException("No tasks found for project ${projectId}")
        }
    }

    private List<Map> retrieveRemoteList(String path) {
        HttpRequest request = HttpRequest.GET(path)
        HttpResponse<List> response = taskClient.exchange(request, List) as HttpResponse<List>
        response.body()
    }
}

我尝试在我的 application.yml 中使用以下配置解决它:

micronaut:
    server:
        read-timeout: 30

micronaut.http.client.read-timeout: 30

...没有成功。尽管我进行了配置,但在调用端点后 10 秒左右仍会发生超时。

如何更改 http rest 客户端的读取超时持续时间?

4

3 回答 3

8

micronaut.http.client.read-timeout需要一个持续时间,因此您应该为该值添加一个测量单位,30s例如30m30h

于 2021-04-01T20:00:01.043 回答
3

似乎配置值没有注入到手动创建的 http 客户端中。

一种解决方案是在创建时配置 HttpClient,设置 readTimeout 持续时间:

private BlockingHttpClient getTaskClient() {
    HttpClientConfiguration configuration = new DefaultHttpClientConfiguration()
    configuration.readTimeout = Duration.ofSeconds(30)
    new DefaultHttpClient(taskStepperUrl.toURL(), configuration).toBlocking()
}
于 2020-02-11T08:53:55.117 回答
0

就我而言,我正在从客户端流式传输文件

  @Get(value = "${service-path}", processes = APPLICATION_OCTET_STREAM)
  Flowable<byte[]> fullImportStream();

所以当我得到这个时,我的第一个冲动就是增加read-timeout价值。但是,对于流式传输场景,适用的属性read-idle-timeout如文档https://docs.micronaut.io/latest/guide/configurationreference.html#io.micronaut.http.client.DefaultHttpClientConfiguration中所述

于 2021-08-13T08:18:25.553 回答