【问题标题】:Should I override the default ExecutionContext?我应该覆盖默认的 ExecutionContext 吗?
【发布时间】:2013-05-30 10:56:11
【问题描述】:

在 Scala 中使用期货时,默认行为是使用默认的 Implicits.global 执行上下文。似乎这默认为每个处理器提供一个线程。在更传统的线程化 Web 应用程序中,当 future 执行诸如等待数据库之类的任务(与某些 cpu 绑定任务相反)时,这似乎是一个糟糕的默认值。

我希望覆盖默认上下文在生产中是相当标准的,但我找不到关于这样做的文档很少,似乎它可能并不常见。我错过了什么吗?

【问题讨论】:

    标签: scala concurrency


    【解决方案1】:

    与其将其视为覆盖默认执行上下文,不如问“我应该为不同的事情使用多个执行上下文吗?”如果这是问题,那么我的答案是肯定的。在我工作的地方,我们使用 Akka。在我们的应用程序中,我们使用默认的 Akka 执行上下文来实现非阻塞功能。然后,由于目前没有好的非阻塞 jdbc 驱动程序,我们所有的阻塞 SQL 调用都使用单独的执行上下文,其中每个连接方法都有一个线程。保持主执行上下文(分叉连接池)不受阻塞会显着提高我们的吞吐量。

    我认为在您的系统中为不同类型的工作使用多个不同的执行上下文是完全可以的。这对我们来说效果很好。

    【讨论】:

    • +1 提到重要的决定因素是您是否在期货中使用阻塞(或长时间运行)代码。如果不这样做,使用单独的执行上下文实际上会适得其反。
    • 如果你想要一个你可以控制的自定义执行器,但又想坚持默认的并行度和其他参数,似乎ExecutionContext.fromExecutor(new scala.concurrent.forkjoin.ForkJoinPool)(不带参数)似乎可以解决问题;在具有 8 个内核(包括超线程)的 i7 上创建一个 8 个池,与 ForkJoinPool.commonPool 包含的内容相匹配。
    • @cmbaxter 您是否将您的 JDBC 调用包装在期货中的 blocking {} 中?如果有单独的ExecutionContext,有必要吗?
    • @IvanYurchenko,我愿意,但我实际上并不是 100% 确定这是必要的。在我使用 Akka 的模型中,我为包装连接的池中的每个参与者使用 PinnedDispatcher。鉴于每个连接基本上都有自己的专用线程,我不确定在这种情况下是否有必要。我需要在某个时候对其进行分析,看看它是否有帮助、伤害或无所作为。现在,对于其他情况,使用blocking{} 可能是一个好主意,所以我想这取决于情况。
    • @cmbaxter,你介意分享一下你用来实现每个连接一个线程的 Akka 配置吗?
    【解决方案2】:

    “正确”的答案是,您需要使用 ExecutionContext 的方法在其签名中需要 ExecutionContext,因此您可以从“外部”提供 ExecutionContext(s) 以控制更高级别的执行。

    【讨论】:

      【解决方案3】:

      是的,在您的应用程序中创建和使用其他执行上下文绝对是一个好主意。

      执行上下文将模块化您的并发模型并隔离应用程序的不同部分,因此如果您的应用程序的某个部分出现问题,其他部分将受到的影响较小。考虑您的示例,您将有一个不同的执行上下文用于特定于 DB 的操作,而另一个执行上下文用于处理 Web 请求。

      在 Jonas Boner 的 this presentation 中,这种模式被称为在您的应用程序中创建“隔板”以提高稳定性和容错能力。

      我必须承认,我对执行上下文使用本身的了解不多。但是,我确实看到在某些框架中应用了这个原则。例如,Play 将针对不同类型的作业使用不同的执行上下文,并鼓励您在必要时将任务拆分到不同的池中:Play Thread Pools

      Akka 中间件还建议将您的应用程序拆分为不同的上下文,以适应应用程序中的不同并发区域。他们使用Dispatcher 的概念,这是电池上的执行上下文。

      此外,scala 并发库中的大多数运算符都需要执行上下文。这是设计使您在模块化应用程序并发时所需的灵活性。

      【讨论】:

      • Scala 中默认的ExecutionContext 是最近的 ForkJoin 池。鉴于此,您所说的全局执行上下文“适用于小型、快速的工作,但它肯定不会扩展到更大的应用程序”是没有根据的。
      • 这并不是说默认的执行上下文本身就没有性能。我的意思是说,在大型应用程序中只使用一个执行上下文并不是最好的事情。尽管如此,我还是删除了该评论,因为它令人困惑。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 2020-07-12
      • 1970-01-01
      相关资源
      最近更新 更多