未来和延迟:如何优先考虑某些期货的执行优先于其他期货

时间:2015-09-09 10:03:04

标签: scala concurrency executorservice

我有一个Akka / Spray.io REST服务器,在收到用户请求后,将为该用户执行三项操作:

  1. 将用户数据上传到远程存储。
  2. 更新数据库中的用户统计信息
  3. 响应用户指示操作是否失败或成功
  4. 由于它们本质上是所有阻塞操作,因此它们被包装在scala.concurrent.Future中以进行异步执行。

    我面临的问题是,在负载很重的情况下,服务器的响应延迟非常高(5秒)。经过调查,问题是由于只要该用户的计算完成,就不会执行包含特定用户响应的Future实例。相反,我经常发现它们排在其他任务之后。

    这基本上是优先级问题。理想情况下,服务器继续执行异步操作,但是当用户响应可用时,它应优先于其他任务。想象一下,我们可以对服务器说,"嘿,我知道你会有很多来自其他用户的待处理请求,但是既然你已经为这个特定用户更新了数据库并上传了数据,为什么不呢?在继续为其他客户提供服务之前首先回复用户"

    我尝试过设置两个ExecutionContext实例responseEC,一个用于发送用户响应的专用ExecutionContext和用于其他(阻塞)任务的generalBlockingEC。我期望JVM将以高度公平的方式在两个EC实例之间交替执行,并且看到我的响应以更及时的方式发送。

    不幸的是,出于某种原因,JVM偏向于在generalBlockingEC中花费更多时间,而不是以公平的方式在responseECgeneralBlockingEC之间交替工作。

    我是否以错误的方式接近问题?是否有更好的方法来优先执行某些Future个实例而不是其他实例(例如,可能在Actor的帮助下)?

1 个答案:

答案 0 :(得分:3)

首先,我将在这里回答为什么没有一种机制来优先考虑某些线程池而不是其他线程池:How to configure ThreadPool priority in Playframework具体来说:

  

目前无法配置线程优先级,因为这样   设置对许多平台大多没有影响,因此   有资格作为安慰剂。如果您启动并主动使用更多线程   比你有CPU核心,然后由此产生的竞争将是昂贵的   而且会浪费资源,所以你最好小心翼翼   您的线程池大小为CPU绑定部分的可用内核。

我认为你已经通过创建两个执行上下文开始了正确的行。我建议您确保每个执行上下文都有自己的Threadpool,并确保两者之间的线程总数不超过或不超过硬件上的内核数。

如果你想支持一个执行上下文而不是另一个,你可以尝试给它一个更大比例的线程。