20

我在 AWS 机器上运行 Tomcat 8.5.9,部署了 10 个不同的 WebSocket 应用程序,每个应用程序基本上都充当消息代理。https 连接器使用的是 Http11NioProtocol。我设置的唯一参数是 maxThreads=200 以及证书信息。

请求量不是很高。它从周一早上开始运行,经理状态如下:

最大线程数:200
当前线程数:38
当前线程忙:0
保持活动套接字数:1最长
处理时间:234 毫秒
处理时间:17.254 秒
请求数:33351
错误数:325
接收字节:0.00 MB
发送字节:34.07 MB

几天后,我注意到内存使用量继续增长。我必须大约每两周左右重新启动一次 Tomcat 服务,以防止出现 OutOfMemoryException。

我一直在使用 Eclipse MAT 进行堆转储和分析,它总是将 WsFrameServer 类作为问题嫌疑人。最近的转储显示以下内容:

由“java.net.URLClassLoader @ 0x6c0047c28”加载的“org.apache.tomcat.websocket.server.WsFrameServer”的5146个实例
占用了1383143200
(73.13%)字节。这些实例引用自
“java.util.concurrent.ConcurrentHashMap$Node[]”的一个实例

Dominator Tree 目前有 106,000 个条目,其中大部分是 WsFrameServer 类。

我做错了什么还是这是“正常的”?在 Tomcat 或连接器上是否有任何特定设置我应该设置以防止这种情况发生?

提前致谢。

编辑:我不确定这是否有帮助,但这是 VisualVM 监视器的样子:

VisualVM 监视器

4

3 回答 3

5

没有更多细节很难确定,但这可能与您的会话保留有关。我认为正在发生的事情是将WsFrameServerwhich extendsWsFrameBase 添加到会话中。
如果您有无限的会话保留策略,那么您最终将耗尽内存。

尝试设置一个非 0sessionTimeout

于 2017-07-31T06:18:15.280 回答
0

您的问题中缺少代码。(尤其是你如何管理 websocket 连接)

您是否在异步模式下使用了tomcat,并在某处列出了连接列表?

您不会忘记将关闭和错误事件绑定到从列表中删除错误连接的代码?

于 2017-08-04T12:19:28.017 回答
0

众所周知,Java GC 是惰性的。它的内存会继续增长,直到它不能有更多的内存,然后会触发 GC 来收集垃圾。

从您的 VisualVM 的屏幕截图中,我们可以看到内存使用量相对正常:随着时间的推移使用更多内存,GC 后内存使用量下降。

所以我想知道你的应用程序是否真的会因为OOM而崩溃。您可以在您的测试环境中尝试,并获取 OOM JVM 转储进行分析,这更有用。

顺便说一句,我建议 VisualVM over MAT,因为 MAT 会包含一些无法访问的对象作为 GC root。它会使内存分析非常低效,并给出与我在我们的一个项目中遇到的其他工具不同的结果。

于 2017-08-05T01:57:49.057 回答