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

Python Web应用程序中H20的内存泄漏,python,pandas,h2o,Python,Pandas,H2o,我的决策引擎是基于PythonFlask框架和uWSGI和Nginx构建的。 作为通过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_PAT

我的决策引擎是基于PythonFlask框架和uWSGI和Nginx构建的。 作为通过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台服务器)

有时,内存使用量在稳步增加,并且
无法分配内存

在计算记分卡时。有时,它会自动沉降。记分卡在HTTP请求下与其他规则(顺序运行)一起运行,但仅在计算记分卡时报告错误。假设与h2o有关,它需要更多的内存。整个周期的交通量看起来都是一样的。所以我希望这不是因为交通拥挤

根据我的调查,有些记忆挂在某个地方,而且没有释放出来

我做了以下变通方法来释放挂起的内存并减少影响

1python水溶液中的GC

  • 没有经历过积极的影响
2定时服务重启-以新服务器优雅地替换旧服务器

  • 经历了积极的影响。60-70%的错误消失了
我希望了解内部发生的情况,并引入适当的修复方法,而不是解决方法。非常感谢您的帮助

供您参考

我还没试过

1将H2o cluster更新为新版本,因为当前版本太旧(1年、7个月和11天)-同意最好使用最新版本,但不能保证不会再次发生同样的情况,并且所需的工作更多地是验证分数、结果等

2我没有使用
min\u mem\u size
限制H2o的内存使用,因为我不希望记分卡评估失败

我正计划

1添加内存档案器,以轻松了解与我的应用程序相关的每个片段/进程的内存利用率

编辑

2将h2o从flask应用程序中分离出来,并将其托管在不同的服务器中,以便于扩展。 -不过,同样的问题也是可能的

  • 我浏览了一些内存分析器,但仍然无法最终确定一个最适合我当前情况的。我也想得到一个关于这方面的建议

谢谢

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

为了简单起见(忽略多个服务器和负载平衡),我将绘制如下设置的架构图:

[Client HTTP program] -> [python flask app] -> [java scoring backend]
这种高级架构很好,但是您已经开始实现java评分层部分,我将说这是最困难的方法,而不是预期的方法

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

以下是MOJO的javadoc链接:

一个github repo演示了如何在简单的Java servlet容器中使用MOJO:

另外,这里有一个使用POJO而不是MOJO的较旧的github回购协议,您可能会发现它很有用。魔咒更好。使用MOJO而不是POJO,但您可能会发现阅读本回购协议中的文档很有帮助:

注意:如果您这样做,您仍然可以根据需要单独扩展/负载平衡[python flask app]和[java scoring backend]服务,尽管我的预期是java将大大快于python,因此将python和java分成两组进行扩展可能更容易,并让python向本地java发出请求


好的,既然我已经谈到了最佳实践方式,那么让我指出一些我可以在您现在所做的事情中发现的问题(困难的方式)

  • 你没有提到你是一次得分一行还是批量得分。使用完整的H2O-3服务器本身进行评分更适合批量评分,一次评分一行的效率非常低。解析过程是重量级的,评分过程是一次一行的重量级的。这将影响延迟

  • 虽然您可以将MOJO对象本身读入一个完整的H2O-3服务器进程,并将其用于批处理评分,但在实时HTTP工作流中这样做从来都不是目的。(有趣的是,在H2O-3存在的最初5年里,支持这一点甚至是不可能的。)

  • 如果你自己不清理,肯定会有内存泄漏

    不建议将H2O-3服务器进程作为评分的长期服务运行。但如果你真的想这样做,请采取以下步骤:

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

    • 我不认为您需要在Java进程中手动触发垃圾收集,但如果您愿意,可以这样做。就我个人而言,我只有在打开Java标志时才会这样做,比如-XX:+PrintGCDetails-XX:+PrintGCTimeStamps,这样我才能看到压缩对完整GC后剩余空闲堆内存的影响。我这样做是为了查看对象是否真的被保留,以便确认它们是否被清除。我喜欢把那些日志交给和visu