Python Web应用程序中H20的内存泄漏

问题描述 投票:-1回答:1

我的决策引擎是基于uWSGI和Nginx的python-flask框架构建的。作为通过HTTP请求评估用户的一部分,我运行h2o == 3.20.0.7的计分卡来生成分数以对用户做出决策。下面给出一些有关如何在我的应用程序中使用h2o的清晰信息

h2o.init()  # initialize 

predictions = h2o.mojo_predict_pandas(features_df, MODEL_MOJO_ZIP_FILE_PATH, MODEL_GENMODEL_JAR_PATH)  # generate score
# features_df -> pandas DF

从应用开始的H2o详细信息

--------------------------  ----------------------------------------
H2O cluster uptime:         01 secs
H2O cluster timezone:       Etc/UTC
H2O data parsing timezone:  UTC
H2O cluster version:        3.20.0.7
H2O cluster version age:    1 year, 7 months and 10 days !!!
H2O cluster name:           H2O_from_python_unknownUser_t8cqu9
H2O cluster total nodes:    1
H2O cluster free memory:    1.656 Gb
H2O cluster total cores:    4
H2O cluster allowed cores:  4
H2O cluster status:         accepting new members, healthy
H2O connection url:         http://localhost:54321
H2O connection proxy:
H2O internal security:      False
H2O API Extensions:         XGBoost, Algos, AutoML, Core V3, Core V4
--------------------------  ----------------------------------------

H2o(作为单独的服务运行)和flask应用程序都在同一服务器上运行(负载均衡器下的3至8台服务器)。

有时内存使用率稳定增加并抛出Cannot allocate memory

计算计分卡时。然后有时它会自动自行解决。记分卡与HTTP请求下的其他规则(顺序运行)一起运行,但该错误仅在计算记分卡时报告。假设,与h2o有关,它需要更多的内存。在此周期内,流量看起来是相同的。所以我希望这不是由于人流量大。

根据我的调查,某些内存挂在某处,并且没有释放。

我做了以下解决方法释放挂起的内存并减少影响

1来自python的h2o中的GC

https://aichamp.wordpress.com/2016/11/10/calling-h2o-garbage-collect-from-python

Python H2O Memory Management

  • 未产生积极影响。

2计划的服务重新启动-用新服务器正常替换旧服务器。

  • 经历了积极的影响。 60-70%的错误消失了。

我想了解内部正在发生的事情,并介绍适当的修复方法而不是解决方法。帮助将不胜感激。

供参考,

我还没尝试

1将H2o群集更新为新版本,因为当前版本太旧(1年,7个月和11天)-同意最好使用最新版本,但不能保证相同版本不会再次发生,并且在验证分数,结果等方面也需要更多的努力

2我没有通过使用min_mem_size来限制H2o的内存使用,因为我不希望记分卡评估失败。

我打算去

1添加内存分析器,以轻松了解与我的应用相关的每个部件/进程的内存利用率

  • 我经历了一些内存分析器,但是仍然无法完成最适合我当前情况的分析器。我也想对此提出建议。

谢谢

python pandas h2o
1个回答
0
投票

您描述的方法与我建议的方法不同。

为了简单起见(忽略多个服务器和负载平衡),我将这样绘制您的设置的体系结构图:

[Client HTTP program] -> [python flask app] -> [java scoring backend]

这种高级架构很好,但是您已经实现了Java评分层部分,我会说这是最困难的方法,而不是预期的方法。

预期的方法是仅使用MOJO和轻量级的MOJO运行时。一种简单的方法是将MOJO包装在非常简单的最小Web服务中。

这里是MOJO的javadoc链接:

和一个说明如何在简单的Java servlet容器中使用MOJO的github回购:

[此外,这是一个较旧的github存储库,您可能会发现使用POJO而不是MOJO很有用。 MOJO更好。使用MOJO而不是POJO,但您可能会发现阅读此存储库中的文档很有帮助:

[注意,如果您以这种方式进行操作,那么您仍然可以根据需要分别缩放/负载均衡[python flask app]和[java scoring backend]服务,尽管我希望Java会比python快得多,所以仅将python和java分成两个组,并让python向本地java发出请求可能会更容易。


[好,现在我已经讨论了最佳实践方法,让我指出一些我可以在您现在正在做的事情中发现的问题(困难的方法)。

  1. 您没有提到您是一次计分还是批量计分。使用完整的H2O-3服务器本身进行评分更适合于批处理评分,而一次只能对一行进行评分的效率极低。解析过程非常繁琐,而计分过程一次仅占一行。这将影响延迟。

  2. 尽管您可以将MOJO对象本身读入完整的H2O-3服务器进程并将其用于批处理计分,但是在实时HTTP工作流中执行此操作绝不是目的。 (有趣的是,在H2O-3出现的最初5年中,甚至都没有实现此目的的支持。)

  3. 如果您不自己清理,肯定会有内存泄漏。

    不建议将H2O-3服务器进程作为长期运行的评分服务。但是,如果您确实想要这样做,请执行以下步骤:

    • 需要清除内存中的对象。您可以使用h2o.ls()找到它们,并通过R / python客户端API中的h2o.rm()调用将其删除。数据集和分数都需要清理。不过,您可能不想删除模型本身。

    • 我不希望您需要在Java进程中手动触发垃圾回收,但是可以。就我个人而言,只有在打开-XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps之类的Java标志时,我才这样做,这样我就可以看到压缩对Full GC之后剩余多少可用堆内存的影响。我这样做是为了查看是否确实保留了对象,因此可以确认它们已被清除。我喜欢将这些日志提供给http://gceasy.io并对其进行可视化。

    • 监视日志以查看完整GC后剩余的可用堆。

    • 即使在清理内存方面做得正确,也要为H2O-3服务器进程分配大量内存。我什至不会在-Xmx小于5G的笔记本电脑上运行它。因此,我将原始发布者的Java堆描述为严重不足(H2O cluster free memory: 1.656 Gb)。

    • 如果您看到Full GC爬升后剩余的可用堆,请重新启动Java进程,因为这不是标准用例,也不是经过全面测试的东西。开发团队认为H2O-3集群比起长期运行的服务(月数,例如nginx / apache),更像是中短寿命的服务(小时/天)。


    希望有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.