Play框架:当请求超出可用线程时会发生什么

资料使用者

我在线程池服务阻止请求中有一个线程。

  def sync = Action {
    import Contexts.blockingPool
    Future { 
        Thread.sleep(100)
    } 
    Ok("Done")
  }

在Contexts.blockingPool中配置为:

custom-pool {
    fork-join-executor {
            parallelism-min = 1
            parallelism-max = 1
    }
}

从理论上讲,如果上述请求同时接收到100个请求,则预期的行为应该是:1个请求应该休眠(100),其余99个请求应该被拒绝(或排队直到超时?)。但是,我观察到创建了额外的工作线程来处理其余的请求。我还观察到,当池中的线程数小于接收到的请求时,延迟随着(变得慢于服务请求)而增加。

如果收到大于配置的线程池大小的请求,预期的行为是什么?

多诺万·穆勒(Donovan Muller)

您的检验结构不正确,无法检验您的假设。如果您在文档中仔细阅读本节,将会看到Play具有一些线程池/执行上下文。关于您的问题,最重要的一个是默认线程池以及它与您的操作所服务的HTTP请求之间的关系。

正如文档所描述的,默认情况下,默认线程池是所有应用程序代码运行的地方。即,所有动作代码,包括所有动作代码Future(未明确定义其自己的执行上下文),都将在此执行上下文/线程池中运行。因此,使用您的示例:

def sync = Action {

  // *** import Contexts.blockingPool
  // *** Future { 
  // *** Thread.sleep(100)
  // ***} 

  Ok("Done")
}

您操作中所有注释的代码// ***将在默认线程池中运行即当请求路由到您的操作时:

  1. Future一起Thread.sleep将分派到您的自定义执行上下文
  2. 然后不用等待它Future完成(因为它在自己的线程池[ Context.blockingPool]中运行,因此不会阻塞默认线程池上的任何线程)
  3. 您的Ok("Done")陈述被评估,客户收到回复
  4. 大约 收到响应后100毫秒,您便Future完成了

因此,为了解释您的观察,当您发送100个并发请求时,Play会很乐意接受这些请求,路由到您的控制器操作(在默认线程池上执行),分派给您Future,然后响应客户端。

默认池的默认大小为

play {
  akka {
    ...
    actor {
      default-dispatcher = {
        fork-join-executor {
          parallelism-factor = 1.0
          parallelism-max = 24
        }
      }
    }
  }
}

每个内核最多使用24个线程。每个线程最多使用24个线程。考虑到您的操作几乎没有(不包括Future),您将能够不费力地处理每秒1000个请求。Future会通过但积压工作更长的时间花费,因为你是在自定义池阻塞线程只有(blockingPool)。

如果您使用我的操作略有调整的版本,您将在日志输出中看到确认以上说明的内容:

object Threading {

  def sync = Action {
    val defaultThreadPool = Thread.currentThread().getName;

    import Contexts.blockingPool
    Future {
      val blockingPool = Thread.currentThread().getName;
      Logger.debug(s"""\t>>> Done on thread: $blockingPool""")
      Thread.sleep(100)
    }

    Logger.debug(s"""Done on thread: $defaultThreadPool""")
    Results.Ok
  }
}

object Contexts {
  implicit val blockingPool: ExecutionContext = Akka.system.dispatchers.lookup("blocking-pool-context")
}

您的所有请求都将被快速处理,然后再Future一个一个地完成。

因此,总而言之,如果您真的想测试Play如何仅用一个线程处理请求来处理许多并发请求,则可以使用以下配置:

play {
  akka {
    akka.loggers = ["akka.event.Logging$DefaultLogger", "akka.event.slf4j.Slf4jLogger"]
    loglevel = WARNING
    actor {
      default-dispatcher = {
        fork-join-executor {
          parallelism-min = 1
          parallelism-max = 1
        }
      }
    }
  }
}

您可能还想向操作中添加一个Thread.sleep(这样可以降低默认线程池中的寂寞线程的速度)

    ...
    Thread.sleep(100)
    Logger.debug(s"""<<< Done on thread: $defaultThreadPool""")
    Results.Ok
}

现在,您将拥有1个用于请求的线程和1个用于您Future线程如果您以高并发连接数运行此程序,您会注意到客户端在Play一步一步地处理请求时阻塞。您期望看到的是...

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

VHDL中的整数超出范围时会发生什么?

来自分类Dev

QFuture超出范围时会发生什么?

来自分类Dev

Microsoft SQL Server连接超出带宽时会发生什么?

来自分类Dev

关于实体框架,运行时会发生什么

来自分类Dev

多线程程序创建新进程时会发生什么?

来自分类Dev

多线程程序创建新进程时会发生什么?

来自分类Dev

在浏览器中请求URL时会发生什么?

来自分类Dev

暂停时会发生什么?

来自分类Dev

在 Swift 中,当两个线程获取并设置非线程安全属性时会发生什么?

来自分类Dev

当Java中的集合超出容量限制时会发生什么?

来自分类Dev

c++ 当unique_ptr 的别名超出范围时会发生什么?

来自分类Dev

多线程:为什么生成器不是线程安全的?在线程之间共享时会发生什么?

来自分类Dev

当两个线程同时调用相同的静态方法时会发生什么?

来自分类Dev

当您使用Task.Run太多而导致线程池耗尽时会发生什么?

来自分类Dev

当两个线程尝试修改/访问并发HashMap中的相同密钥时会发生什么?

来自分类Dev

当线程尝试同时调用静态和非静态同步方法时会发生什么?

来自分类Dev

当线程进入Java中的同步块/方法时会发生什么情况

来自分类Dev

当两个并发线程尝试从CopyOnWriteArrayList中删除元素时会发生什么?爪哇

来自分类Dev

当几个线程试图调用相同的同步方法时会发生什么?

来自分类Dev

当原始类超出范围时,线程会发生什么情况

来自分类Dev

未指定dbCreate时会发生什么?

来自分类Dev

升级Ubuntu时会发生什么?

来自分类Dev

单击提交按钮时会发生什么

来自分类Dev

循环结束时会发生什么?

来自分类Dev

合成子类的变量时会发生什么?

来自分类Dev

达到墓碑限制时会发生什么

来自分类Dev

VRAM已满时会发生什么?

来自分类Dev

当指针太大时会发生什么?

来自分类Dev

断言检查失败时会发生什么?

Related 相关文章

  1. 1

    VHDL中的整数超出范围时会发生什么?

  2. 2

    QFuture超出范围时会发生什么?

  3. 3

    Microsoft SQL Server连接超出带宽时会发生什么?

  4. 4

    关于实体框架,运行时会发生什么

  5. 5

    多线程程序创建新进程时会发生什么?

  6. 6

    多线程程序创建新进程时会发生什么?

  7. 7

    在浏览器中请求URL时会发生什么?

  8. 8

    暂停时会发生什么?

  9. 9

    在 Swift 中,当两个线程获取并设置非线程安全属性时会发生什么?

  10. 10

    当Java中的集合超出容量限制时会发生什么?

  11. 11

    c++ 当unique_ptr 的别名超出范围时会发生什么?

  12. 12

    多线程:为什么生成器不是线程安全的?在线程之间共享时会发生什么?

  13. 13

    当两个线程同时调用相同的静态方法时会发生什么?

  14. 14

    当您使用Task.Run太多而导致线程池耗尽时会发生什么?

  15. 15

    当两个线程尝试修改/访问并发HashMap中的相同密钥时会发生什么?

  16. 16

    当线程尝试同时调用静态和非静态同步方法时会发生什么?

  17. 17

    当线程进入Java中的同步块/方法时会发生什么情况

  18. 18

    当两个并发线程尝试从CopyOnWriteArrayList中删除元素时会发生什么?爪哇

  19. 19

    当几个线程试图调用相同的同步方法时会发生什么?

  20. 20

    当原始类超出范围时,线程会发生什么情况

  21. 21

    未指定dbCreate时会发生什么?

  22. 22

    升级Ubuntu时会发生什么?

  23. 23

    单击提交按钮时会发生什么

  24. 24

    循环结束时会发生什么?

  25. 25

    合成子类的变量时会发生什么?

  26. 26

    达到墓碑限制时会发生什么

  27. 27

    VRAM已满时会发生什么?

  28. 28

    当指针太大时会发生什么?

  29. 29

    断言检查失败时会发生什么?

热门标签

归档