Play 2.2 动作未与 Web 服务响应处理程序并行处理

Posted

技术标签:

【中文标题】Play 2.2 动作未与 Web 服务响应处理程序并行处理【英文标题】:Play 2.2 action not processed in parallel with web service response handler 【发布时间】:2013-11-28 15:17:44 【问题描述】:
public class Application extends Controller 

    @BodyParser.Of(BodyParser.Json.class)
    public static Result action1() 
        WS.url(WS_URL).get().map(new Function<WS.Response, Result>() 
            public Result apply(WS.Response response) 
                try 
                    Thread.sleep(10000);
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
                return null;
            
        );
        return ok();
    

    @BodyParser.Of(BodyParser.Json.class)
    public static Result action2() 
        return ok();
    

客户端首先调用action1(),然后调用action2()。但是,Play 似乎在这 10 秒后处理了第二个请求。我认为来自 Web 服务的响应由 Play 在单独的线程中处理,但似乎并非如此。在这种情况下,如果我想休眠或在超时后执行一些代码,而不中断服务器处理其他请求,我该怎么办?

编辑:当客户端调用 action2() 之前来自 WS 的响应到达时,就会发生这种情况。

【问题讨论】:

您确定客户端在调用操作 2 之前不等待操作 1 完成吗?可以显示客户端代码吗? 不,它不会等待。实际上,服务器在向 WS 发送请求后立即从 action1 返回,但似乎来自 WS 的响应是由处理动作的同一线程处理的。我忘了说 WS 的响应是在客户端调用 action2 之前到达的。 【参考方案1】:

默认情况下Play分配的线程数与你拥有的CPU核心数相同(虽然注意有多个线程池),所以如果你想做sleep之类的阻塞操作,请配置它以分配更多线程在处理程序中。

【讨论】:

确实,我找到的解决方案是使用 Akka 系统在单独的线程中进行每个 WS 调用。【参考方案2】:

不太确定您要实现什么,但下面的代码将在 WS 调用返回和返回 ok 结果之间插入 10 秒延迟:

public static F.Promise<SimpleResult> action1() 
    return WS.url(WS_URL).get().flatMap(new Function<WS.Response, F.Promise<WS.Response>>() 
        public F.Promise<WS.Response> apply(WS.Response response) 
           return F.Promise.timeout(response, 100000);
        
    ).map(new Function<WS.Response, SimpleResult>() 
        public SimpleResult apply(WS.Response response) 
           return ok();
        
    ;

要了解 Play 的线程池,请阅读以下内容:

http://www.playframework.com/documentation/2.2.x/ThreadPools

要了解 Play 如何使用 Promise,请阅读以下内容:

http://www.playframework.com/documentation/2.2.x/JavaAsync

【讨论】:

当用户点击我网站上的一个按钮时,服务器会完成多个 WS 调用,这些调用返回的响应用于更新对象列表。同时,客户端会定期发送 AJAX 请求以检查列表中的任何对象是否已更新。问题是 AJAX 请求是在 所有 WS 调用返回之后提供的,而不是像我预期的那样并行。我找到的解决方案是使用 Akka 系统在单独的线程中进行每个 WS 调用。 您是否在 WS API 返回的承诺上调用 get()?如果你是,那么基本上你把你的应用程序变成了一个同步阻塞应用程序,你看到的行为是预期的。永远不要在承诺上打电话给get() 不,我不打电话给get()

以上是关于Play 2.2 动作未与 Web 服务响应处理程序并行处理的主要内容,如果未能解决你的问题,请参考以下文章

上传到 Google Play 时,android apk 未与 zip 对齐

Http响应处理

微服务工程中,基础组件应用

响应码

asp.net 中的模拟未与 com 对象共享

JQuery DataTable 标头未与 ScrollY 和服务器端处理对齐