Scala 未来和延迟:如何将某些未来的执行优先于其他未来

Scala 未来和延迟:如何将某些未来的执行优先于其他未来,scala,concurrency,executorservice,Scala,Concurrency,Executorservice,我有一个Akka/Spray.io REST服务器,在收到用户请求时,该服务器将为所述用户执行三个操作: 将用户数据上载到远程存储 更新数据库中的用户统计信息 响应用户指示操作是失败还是成功 由于它们本质上都是阻塞操作,因此它们被包装在scala.concurrent.Future中,用于异步执行 我面临的问题是,在重载情况下,服务器的响应延迟非常高(5秒)。经调查,问题是由于包含特定用户响应的Future实例没有在该用户的计算完成后立即执行。相反,我经常发现他们排在其他任务后面 这基本上是一个

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

  • 将用户数据上载到远程存储
  • 更新数据库中的用户统计信息
  • 响应用户指示操作是失败还是成功
  • 由于它们本质上都是阻塞操作,因此它们被包装在
    scala.concurrent.Future
    中,用于异步执行

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

    这基本上是一个优先级问题。理想情况下,服务器会继续执行异步操作,但当用户响应可用时,它应该优先于其他任务。想象一下,我们可以对服务器说,“嘿,我知道您将有许多来自其他用户的未决请求,但是既然您已经完成了对数据库的更新并上传了该特定用户的数据,为什么不在继续为其他客户机服务之前先响应该用户?”

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

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


    我是否以错误的方式处理问题?是否有更好的方法将某些
    未来的
    实例的执行优先于其他实例(例如,可能在Actor的帮助下)?

    首先,关于为什么没有一种机制将某些线程池优先于其他线程池的问题,我将在这里给出答案:具体来说:

    目前无法配置线程优先级,因为 设置在许多平台上基本上没有效果,因此 可作为安慰剂。如果启动并积极使用更多线程 如果你有CPU核,那么产生的竞争将是昂贵的 而且会浪费资源,所以你最好仔细装修 您的线程池大小与CPU绑定部件的可用内核相匹配

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


    如果您想让一个执行上下文优于另一个,可以尝试让它占线程总数的更大比例。

    为什么要并行运行所有这些内容?例如,如果一个失败,另一个成功,您仍然会向用户返回一个失败,但其缺点是在操作中浪费了一个线程,还请注意,即使您将它们包装在futures中,据我所知,它们仍在阻塞分配的线程。@EndeNeu当线程中遇到阻塞调用时,将执行上下文切换,以便另一个线程可以执行。上下文切换的成本很高,但如果正确调整(通过考虑可用CPU的数量和平均阻塞时间等因素),多线程多个阻塞调用的速度优势仍将超过上下文切换的成本Interest。那么,如果基本构建块几乎不能保证这些事情,那么应该如何在应用程序中争取相对一致的延迟配置文件呢?也许只有我一个人,但我觉得调整线程数是相当精细的,在一般的多台机器上不是一个非常健壮的解决方案?