简介
我正在运行一个多线程 tcp 服务器,它使用一个固定的线程池和一个无界的 Runnable 队列。客户端将可运行对象分派(dispatch)到池中。
在我的压力测试场景中,600 个客户端尝试登录到服务器并立即向所有其他客户端广播消息同时并且反复无休止并且没有 sleep (现在客户端只是丢弃传入的消息)。使用为堆内存保留 1GB 的四核 - 以及用于年轻代和老年代的并行 GC - 服务器在 20 分钟后因 OOM 异常而崩溃。监控垃圾收集器发现老年代正在缓慢增加,而 full GC 只释放了一小部分内存。完整堆的快照显示老年代几乎完全被 Runnables(及其传出引用)占据。
似乎工作线程完成 Runnable 的速度比客户端能够排队等待执行的速度快(对于服务器的每个传入“事件”,服务器将创建 599 个 Runnable,因为有 600 - 1客户 - 假设他们当时都已登录)。
问题
有人可以帮我想出一个策略来处理不堪重负的线程池 worker 吗?
还有
- 如果我绑定(bind)队列,我应该实现什么策略来处理被拒绝的执行?
- 如果我增加堆的大小,那不是只会延长 OOM 异常吗?
- 可以进行计算以衡量在 Runnable 的聚合中完成的工作量。或许这个衡量标准可以作为锁定机制的基础来协调客户的调度工作?
- 当服务器因工作不堪重负时,客户会有什么 react ?
最佳答案
不要使用无界队列。我不能告诉你界限应该是多少;你的负载测试应该给你这个问题的答案。无论如何,使边界可配置:至少动态可配置,更好地适应某些负载测量。
您没有告诉我们客户端如何提交他们的请求,但是如果涉及 HTTP,那么已经有一个过载情况的状态代码:503 Service Unavailable .
关于java - 线程池工作线程被 Runnables 淹没导致 JVM 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8057377/