Java中的正常降级以避免内存不足错误

| 在突发大量内存的请求期间,哪些工具或最佳实践可用于在Java服务中正常降级服务?有问题的应用程序是多线程的。处理每个请求所需的工作量可能相差很大,并且不容易拆分和并行化。 我很担心编写与堆使用和GC有关的应用程序级代码,但是我们发现,通过处理多个密集请求,应用程序可能会陷入麻烦,这意味着内存不足错误或完整的GC。完整的GC通常无法找到任何可用内存。 长话短说:我正在考虑添加一些限制或排队功能来避免此类问题。 任何想法或建议表示赞赏。     
已邀请:
        如joeslice所说,通过一个简单的资源池实现限制。从最基本的角度来看,这是一个信号灯-您的工作线程在处理请求之前需要获得许可。由于您说自己有各种各样的任务,因此您可能希望许可证稍微复杂一些,例如获得与工作规模成比例的一定数量的许可证。 过去,我发现这并不总是有效。假设您的启发式功能已关闭,并且您的应用仍然抛出了OOM。重要的是要防止进程在不良状态下徘徊,因此请立即终止并重新启动进程。有几种方法可以通知OOM何时发生,例如看到Java内存不足,然后退出。     
        这是Netty作者的一个实现示例(链接)。他们基本上会跟踪内存使用情况,并根据该统计信息直接进行调节。 另一个更粗略的方法是使用固定线程池和有界队列来限制并发执行。一种常见的方法是,一旦此队列已满,就让ѭ0的调用者自己执行任务。这样,负载将(应该是)一直传播到客户端,直到新请求的创建变慢为止。因此,应用程序的行为。变得更加“优雅”。 实际上,我几乎只使用上述的“粗略”方式。效果很好。基本上,固定线程池和有界队列的组合+调用方运行拒绝策略。我将参数(队列大小,线程池大小)保持可配置,然后在完成设计之后,我将调整这些参数。有时,很明显可以在服务等之间共享线程池,因此在这种情况下,使用类“ 1”来获取固定在一个线程中的固定线程池/有界队列/调用方运行策略确实非常方便。     
        我想知道是否有一种方法可以预先确定给定工作将使用多少内存...。如果有某种方法可以确定特定的输入可能会产生爆炸性的内存大小,也许您可​​以尝试保持它不会与另一个高使用率作业同时运行。 如果您可以确定每个工作之间的相对大小(这是一个很大的假设),则可以使用计数信号量来允许(例如)运行100个单位的工作。一个典型的工作可能只算作一个单元(并且只获取一个许可),而较大的工作可能需要在运行前获取10或20个许可。 当然,如果您无法预先确定要使用的内存大小,则仍然可以探索进一步细分问题的方法,从而可以执行更多的小内存工作少数大工作。     
在应用程序服务器中,通常有工作线程池的设置。该池中的最大线程数大致定义了您将消耗多少内存。这是一个简单且重要的工作概念。 我不会称其为“优雅降级”。这是节流的。正常降级涉及降低服务级别(例如,提供给用户的详细信息的数量),以至少使每个当前用户都可以使用基本必需的功能。随着节流,额外的用户就走运了。 根据该定义进行的正常降级需要了解应用程序的性质,因此您必须使代码对此有所了解。 一种明显的方法是根据用户的需要将所有可能的操作分为几类。一等舱应始终处理。仅当服务器低于特定负载级别时,才应提供第二(第三,第四,...)类,否则将返回“暂时不可用”错误。     
        您正在使用J2EE吗?因为这是应用服务器完成负载平衡的工作,并且我敢肯定许多主流AppServer都支持它。您的应用程序不必关心它。     

要回复问题请先登录注册