加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

(Scala)中的异步请求播放“挂起”

发布时间:2020-12-16 09:06:15 所属栏目:安全 来源:网络整理
导读:我编写了一个应用程序( Scala)Play,当我在本地计算机上运行它时,它的工作方式与我预期的完全一样.我正在处理的方法(可能有其他人遇到此问题,我没有进行过广泛检查)是一个由POST请求触发的方法.它返回一个Async对象,因为该方法完成的评估返回一个Future. 但是
我编写了一个应用程序( Scala)Play,当我在本地计算机上运行它时,它的工作方式与我预期的完全一样.我正在处理的方法(可能有其他人遇到此问题,我没有进行过广泛检查)是一个由POST请求触发的方法.它返回一个Async对象,因为该方法完成的评估返回一个Future.

但是当我部署它时,这种方法的表现完全不同.我一整天都在追逐这个问题,但是我已经到了无法解释发生了什么的地步.

该方法看起来像这样:

def add = Action(parse.json) { request =>
    Async {
      val req = request.body.asOpt[TaskRequest] map { r =>
        val job = createJob(r)
        submitJob(job,r)
        job map { ij =>
          allowOrigin(Created(ij).withHeaders("Location" -> routes.Jobs.read(ij._id.stringify).url));
        }
      }
      req.get
    }
  }

总的来说,这非常简单. createJob方法返回Future [Job]. submitJob调用是一种“即发即忘”调用来触发一些背景内容(我不想等待).然后,我在创建作业时处理作业结果以生成Result对象.

所有这些都像我在本地机器上描述的那样工作.但是当我部署它时,真的很奇怪. submitJob调用会触发长时间运行的计算.正如我所说,我对等待它没兴趣,这就是为什么我甚至不使用它返回任何地方的Future.

但这是奇怪的部分…在我的开发机器上,我的POST请求(直接调用add)的响应在作业创建后立即返回.但是在部署机器上,我只在submitJob任务完成后得到响应!换句话说,我把这个req看作是一个看似与submitJob调用完全无关的Future(它肯定不依赖于它的结果),但是在部署环境中,Async块在submitJob完成之前不会返回(即使req几乎立即实现).

到底发生了什么事?我把println语句全部放在代码中.它肯定会立即通过req.get调用.但是整个(HTTP)响应肯定会等到submitJob完成. Async以某种方式了解submitJob调用吗?如果是这样,为什么它在两台不同的机器上表现不同?

有任何想法吗?

解决方法

好的,我明白了.哦,这是多么痛苦.问题是我的“一劳永逸”任务是一项长期任务.但是部署机器上的线程池大小最终小于我的开发机器.结果,这个长时间运行的任务在线程池中丢失并堵塞了它.因此,AsyncResult的处理可能会被长时间运行的计算所取代(它实际上阻止了长时间运行计算的结果,但底线是它被阻止).

在阅读了Heather Miller对Scala 2.10期货的一个非常好的解释之后,我注意到了阻塞构造,可用于临时扩展线程池的大小以用于单个未来.我用阻塞调用包装了我的阻塞代码,这就完成了.据推测,这会分配一个额外的临时工来处理我的阻塞调用,结果,AsyncResult的内容得到及时处理.

(注意,包装submitJob调用是没用的,因为它本身没有阻塞.我必须做的是进入submitJob调用并找到实际阻塞的位置并将其包装.)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读