6

我有一个服务可以在内存中暂存对其进行的所有调用,因为我们不想丢失数据,同时我们需要该服务因任何外部依赖(例如数据库)而失败。然后,这些分阶段的呼叫会定期在后台被拾取和处理。

如果出于某种原因,如果调用过多并且内存不足,我们需要警惕。

所以,简单地说,这个问题是:当由于资源不足导致添加到列表失败时,我需要捕获或监视什么异常来通知我?它会导致 VM 本身出现 OOM,还是也存在集合级别限制?

如果没有集合级别的限制,您会建议我如何监控服务的使用情况?目前,我们有堆使用和内存使用指标。这些够吗?此外,JVM 被配置为在出现 OOM 错误时终止(这是因为 VM 管理器随后会在终止时重新启动它正在管理的任何进程)。

4

3 回答 3

4

要抛出的异常是OutOfMemoryException. 一旦你的集合吃光了所有可用的堆空间,这个异常就可以在你的应用程序的任何部分抛出。

但是,如果您知道它可能会针对特定集合被抛出,最好的方法可能是防止这种情况发生,即限制此集合或使用缓存,以便按需驱逐和重新加载未使用的实体。对于轻量级缓存实现,我会推荐 Guava 的CacheBuilder

更新

由于每个人都建议基于 FS 的存储,这里是我的轻量级插入式建议:

  • CacheBuilder从 NoSQL DB 加载序列化数据
  • Kryo序列化器将您的对象转换为byte[]
  • 要存储的MapDB(或您喜欢的任何其他嵌入式 NoSQL 解决方案)。
于 2013-10-23T18:32:49.493 回答
2

我认为让应用程序惨遭失败并不是一个理想的设计选择。您应该对集合的大小设置阈值并决定在这种情况下要做什么:将其刷新到某处(磁盘?),发送通知(JMX/电子邮件),抛出错误(或让 OOME 传播)。

也就是说,我会给你一个设计建议。从您对服务的简短且略显神秘的描述来看,在我看来,您需要一个工作队列来坐在您的服务之外的某个地方,例如,JMS 服务器甚至数据库。通过这种方式,您的后台进程将能够从队列 (db) 中提取请求并处理它,即使您的服务因任何原因而死亡。

于 2013-10-23T18:47:40.023 回答
2

这是我在 Collection.add 规范中找到的内容:

如果一个集合拒绝添加一个特定元素,除了它已经包含该元素之外,它必须抛出一个异常(而不是返回 false)。这保留了在此调用返回后集合始终包含指定元素的不变量。

它没有指定哪个异常,所以不同的集合可能会抛出不同的异常。

于 2013-10-23T18:31:35.687 回答