我有一个大约有 400 个线程的 Play 框架应用程序。 200 是默认调度程序的一部分。 现在我有 2 个数据库源,每个数据库源有 9 个连接,线程池的最小大小为 20,最大大小为 200。所有数据库操作都在数据库执行上下文中执行。
正常负载下( <50 req/sec), the CPU usage is just fine. However, if we go up to 70 or 80 requests per second then utilization spikes and some APIS start becoming unresponsive.
我的推理是,一旦连接全部被占用,调度程序就会为所有新传入的请求创建一个任务队列。我假设由于调度程序不知道底层操作正在阻塞,因此它产生了与任务一样多的线程,并且所有这些线程都尝试调用 ebean 上的 getConnection(这是一个同步块)。那时,我希望投入大量资源来管理锁,为所有这些线程分配时间以检查是否有任何连接可用(时间切片)和上下文切换。
我走在正确的道路上吗?有没有办法证实这个理论并测量由此引起的CPU利用率?我读过有关 JMX 的信息,用于查看线程级 CPU 利用率,但我不确定它是如何工作的。最后,我看到的此设计的唯一改进是为两个数据库源提供单独的线程池,并将线程数与连接数相匹配。
我确实有一些线程转储快照,其中我可以看到一些线程被阻塞,而大多数线程正在等待。但是,尚不清楚等待是否意味着 .get() 或 .join() 阻塞操作,或者线程是否只是空闲(thread.sleep())
除非您使用某种非阻塞数据库驱动程序,否则您将创建太多线程,这些线程最终都会尝试并行运行,直到它们成为数据库的瓶颈。保持数据库线程池接近您的连接计数,如果您不阻塞调度程序线程,则每个 CPU 线程 1 个对于调度程序来说就足够了。我相信您可能会浪费资源和负载,而没有任何性能优势