Java 线程池工作人员因可运行程序崩溃JVM而不知所措

Java 线程池工作人员因可运行程序崩溃JVM而不知所措,java,multithreading,memory-management,garbage-collection,Java,Multithreading,Memory Management,Garbage Collection,简介 我正在运行一个多线程tcp服务器,它使用一个固定线程池和一个无限可运行队列。客户端将可运行程序分派到池中 在我的压力测试场景中,600个客户机尝试登录到服务器,并立即向其他客户机同时重复广播消息,无休止且不睡觉(现在客户机只是丢弃传入的消息)。使用一个为堆内存保留1GB的四核,以及一个为年轻人和老年人保留的并行GC,服务器在20分钟后崩溃,出现OOM异常。对垃圾收集器的监视表明,永久生成正在缓慢增加,而完整的GC只释放一小部分内存。完整堆的快照显示,旧一代几乎完全被可运行程序(及其传出引用

简介

我正在运行一个多线程tcp服务器,它使用一个固定线程池和一个无限可运行队列。客户端将可运行程序分派到池中

在我的压力测试场景中,600个客户机尝试登录到服务器,并立即向其他客户机同时重复广播消息,无休止且不睡觉(现在客户机只是丢弃传入的消息)。使用一个为堆内存保留1GB的四核,以及一个为年轻人和老年人保留的并行GC,服务器在20分钟后崩溃,出现OOM异常。对垃圾收集器的监视表明,永久生成正在缓慢增加,而完整的GC只释放一小部分内存。完整堆的快照显示,旧一代几乎完全被可运行程序(及其传出引用)占用

工作线程完成可运行程序的速度似乎无法超过客户端将其排队等待执行的速度(对于服务器的每个传入“事件”,服务器将创建599个可运行程序,因为有600-1个客户端-假设它们当时都已登录)

问题

有没有人能帮我构思一个策略,如何处理被淹没的线程池工作人员

同时

  • 如果我绑定了队列,我应该实现什么策略来处理被拒绝的执行
  • 如果我增加堆的大小,那不是只会延长OOM异常吗
  • 可以进行计算以测量在可运行项聚合中完成的工作量。也许这个度量可以用作锁定机制的基础,以协调客户机的调度工作
  • 当服务器被工作压得喘不过气来时,客户端会有什么反应

您必须以某种方式限制传入的请求,执行该操作的机制应取决于您正在尝试执行的工作。其他任何事情都只会在足够的负载下导致OOM,从而为DOS攻击(甚至是无意的攻击)打开大门

基本上,您有4种选择:

  • 让客户端等待,直到您准备好接受他们的请求
  • 主动拒绝客户端请求,直到您准备好接受新请求
  • 当服务器未准备好接收请求时,允许客户端在尝试访问服务器时超时
  • 上述两种或三种策略的混合
  • 正确的策略取决于你的真实客户在各种情况下的反应——他们最好是无限期地(有效地)等待,还是尽快知道他们的工作不会完成,除非他们稍后再试

    无论采用哪种方式,都需要能够计算当前排队的任务数,并根据队列中的项目数添加延迟、完全阻塞或返回错误条件

    可以使用BlockingQueue实现来实现简单的阻塞策略。然而,这并没有提供特别细粒度的控制

    或者,您可以使用信号量来控制将任务添加到队列的许可证,如果您希望应用温和的限制,那么这具有提供tryAcquire(长超时,TimeUnit)方法的优势


    无论采用哪种方式,都不要让为客户机服务的线程无限增长,否则,您只会因为不同的原因而得到OOM

    您必须以某种方式限制传入的请求,执行该操作的机制应取决于您正在尝试执行的工作。其他任何事情都只会在足够的负载下导致OOM,从而为DOS攻击(甚至是无意的攻击)打开大门

    基本上,您有4种选择:

  • 让客户端等待,直到您准备好接受他们的请求
  • 主动拒绝客户端请求,直到您准备好接受新请求
  • 当服务器未准备好接收请求时,允许客户端在尝试访问服务器时超时
  • 上述两种或三种策略的混合
  • 正确的策略取决于你的真实客户在各种情况下的反应——他们最好是无限期地(有效地)等待,还是尽快知道他们的工作不会完成,除非他们稍后再试

    无论采用哪种方式,都需要能够计算当前排队的任务数,并根据队列中的项目数添加延迟、完全阻塞或返回错误条件

    可以使用BlockingQueue实现来实现简单的阻塞策略。然而,这并没有提供特别细粒度的控制

    或者,您可以使用信号量来控制将任务添加到队列的许可证,如果您希望应用温和的限制,那么这具有提供tryAcquire(长超时,TimeUnit)方法的优势


    无论采用哪种方式,都不要让为客户机服务的线程无限增长,否则,您只会因为不同的原因而得到OOM

    听起来好像你在做负载测试。我会确定你认为什么是“可接受的重载”。您期望单个客户端产生的最大流量是多少?然后加倍。或者是三倍。或者以类似的方式缩放。使用此阈值限制或拒绝使用如此多带宽的客户端


    这有很多好处。首先,它提供了确定服务器负载(每台服务器的用户数)所需的分析类型。其次,它为您提供了抵御DDOS攻击的第一道防线

    听起来好像你在做负载测试。我会确定你认为什么是“可接受的重载”。您期望单个客户端产生的最大流量是多少?然后加倍。或者是三倍。或者以类似的方式缩放。使用这个thr