【问题标题】:Play Framework handle request timeoutPlay Framework 处理请求超时
【发布时间】:2017-09-03 10:38:00
【问题描述】:

如何在 play ws 客户端中处理超时异常?当我指定RequestTimeout 并处理流时,CompletionStage 成功完成,即使有异常。

请参阅下面的示例。

代码(取自here):

// Make the request, which should timeout
        CompletionStage<StreamedResponse> futureResponse = ws.url("https://download.docker.com/mac/stable/Docker.dmg")
                .setMethod("GET").setRequestTimeout(1000)
                .stream();

        CompletionStage<Long> bytesReturned = futureResponse.thenCompose(res -> {
            Source<ByteString, ?> responseBody = res.getBody();

            // Count the number of bytes returned
            Sink<ByteString, CompletionStage<Long>> bytesSum = Sink.fold(0L, (total, bytes) -> 
            { 
                long len = bytes.toArray().length;
                return total + len;
            });

            return responseBody.runWith(bytesSum, materializer);
        }).handle((res, err) -> {
            LOGGER.info("Res = {}, err = {}", res, err);
            return 200L;
        }).exceptionally(ex -> {
            LOGGER.error("See exception");
            return 100L;
        });
        try {
            bytesReturned.toCompletableFuture().get();
            LOGGER.info("Got response");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        LOGGER.error("Step completed");

我在日志中看到java.util.concurrent.TimeoutExceptiono.a.netty.timeout.TimeoutTimerTask 被抛出,但futureResponse 成功完成。有什么办法可以捕捉到这个错误?

我的问题是我试图通过控制器将该响应返回给用户,但由于并非所有数据都已传输,因此它只是挂起。

[debug] i.n.u.i.JavassistTypeParameterMatcherGenerator - Generated: io.netty.util.internal.__matchers__.org.asynchttpclient.HttpResponseBodyPartMatcher
[debug] o.a.netty.channel.DefaultChannelPool - Closed 0 connections out of 0 in 0 ms
[debug] o.a.netty.timeout.TimeoutTimerTask - Request timeout to download.docker.com/52.84.239.124:443 after 1000 ms for NettyResponseFuture{currentRetry=0,
    isDone=0,
    isCancelled=0,
    asyncHandler=play.api.libs.ws.ahc.Streamed$DefaultStreamedAsyncHandler@376665d1,
    nettyRequest=org.asynchttpclient.netty.request.NettyRequest@39a19d4d,
    future=java.util.concurrent.CompletableFuture@3d9e0ea1[Not completed],
    uri=https://download.docker.com/mac/stable/Docker.dmg,
    keepAlive=true,
    redirectCount=0,
    timeoutsHolder=org.asynchttpclient.netty.timeout.TimeoutsHolder@789c9776,
    inAuth=0,
    statusReceived=1,
    touch=1491606083196} after 1075 ms
[debug] o.a.netty.channel.ChannelManager - Closing Channel [id: 0x66ec6bbd, L:/10.155.124.116:52337 - R:download.docker.com/52.84.239.124:443] 
[debug] o.a.netty.request.NettyRequestSender - Aborting Future NettyResponseFuture{currentRetry=0,
    isDone=0,
    isCancelled=0,
    asyncHandler=play.api.libs.ws.ahc.Streamed$DefaultStreamedAsyncHandler@376665d1,
    nettyRequest=org.asynchttpclient.netty.request.NettyRequest@39a19d4d,
    future=java.util.concurrent.CompletableFuture@3d9e0ea1[Not completed],
    uri=https://download.docker.com/mac/stable/Docker.dmg,
    keepAlive=true,
    redirectCount=0,
    timeoutsHolder=org.asynchttpclient.netty.timeout.TimeoutsHolder@789c9776,
    inAuth=0,
    statusReceived=1,
    touch=1491606083196}

[debug] o.a.netty.request.NettyRequestSender - Request timeout to download.docker.com/52.84.239.124:443 after 1000 ms
java.util.concurrent.TimeoutException: Request timeout to download.docker.com/52.84.239.124:443 after 1000 ms
    at org.asynchttpclient.netty.timeout.TimeoutTimerTask.expire(TimeoutTimerTask.java:43)
    at org.asynchttpclient.netty.timeout.RequestTimeoutTimerTask.run(RequestTimeoutTimerTask.java:48)
    at io.netty.util.HashedWheelTimer$HashedWheelTimeout.expire(HashedWheelTimer.java:588)
    at io.netty.util.HashedWheelTimer$HashedWheelBucket.expireTimeouts(HashedWheelTimer.java:662)
    at io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:385)
    at java.lang.Thread.run(Thread.java:745)
[debug] o.a.netty.handler.HttpHandler - Channel Closed: [id: 0x66ec6bbd, L:/10.155.124.116:52337 ! R:download.docker.com/52.84.239.124:443] with attribute INSTANCE
[info] controllers.RedirectController - Res = 2556824, err = null
[info] controllers.RedirectController - Got response
[error] controllers.RedirectController - Step completed

【问题讨论】:

    标签: playframework netty playframework-2.4 playframework-2.5 asynchttpclient


    【解决方案1】:

    即使我在 Play 1.2 中也面临超时异常,因为 api 需要很长时间才能发回响应。我能够手动设置解决我的问题的超时。

    WSRequest request = WS.url(your_url).timeout("600s");
    

    【讨论】:

    • 我不记得细节,但这不起作用。我已经在那里设置了所有可能的超时,但是会在较低级别引发异常,我无法拦截它。我完成了直接调用的 Apache Async Http Client。有一种方法可以覆盖那里的异常处理程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 2011-07-11
    • 1970-01-01
    相关资源
    最近更新 更多