我的决策引擎构建在uWSGI和Nginx的python-烧瓶框架上。作为通过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从app开始的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 (作为一个单独的服务运行)和烧瓶应用程序都在同一个服务器上运行(负载均衡器下有3-8台服务器)。
有时内存使用量在稳步增加,并抛出Cannot allocate memory
同时计算记分卡。然后,有时它会自动自行解决。记分卡在HTTP请求下与其他规则(顺序运行)一起运行,但错误仅在计算记分卡时报告。假设它需要更多的内存,因为它涉及到h2o。这个周期的流量看起来是一样的。所以我希望这不是因为交通拥挤。
据我的调查,一些记忆挂在某处,没有释放。
为了释放挂起的内存并减少影响,我做了以下解决方案
1 GC在h2o中的应用
https://aichamp.wordpress.com/2016/11/10/calling-h2o-garbage-collect-from-python
重新启动2计划服务--用新服务器优雅地替换旧服务器。
我想了解内部正在发生什么,并引入一个适当的解决方案,而不是一个解决办法。我将非常感谢你的帮助。
供你参考,
我还没试过
1将H2o集群更新为新版本,因为当前版本太旧(1年、7个月和11天)-同意最好使用最新版本,但不能保证不会再次发生相同的情况,而且在验证分数、结果等方面也需要更多的努力。
2我没有通过使用min_mem_size来限制H2o的内存使用,因为我不希望记分卡评估失败。
和
我打算去
1添加了一个内存分析器,以方便地理解与我的应用程序相关的每一段/进程的内存利用率
编辑
2将h2o从烧瓶应用程序中分离出来,并将其存放在不同的服务器中,这样就很容易扩展。-尽管如此,也有可能出现同样的问题。
谢谢
发布于 2020-04-12 14:56:55
您所描述的方法与我推荐的方法不同。
为了简单起见(忽略多台服务器和负载平衡),我将绘制您的安装程序的架构图,如下所示:
[Client HTTP program] -> [python flask app] -> [java scoring backend]这个高级架构很好,但是您已经着手实现java评分层部分,我将说这是可能的最困难的方法,而不是预期的方法。
其目的是只使用MOJO和轻量级的MOJO运行时。一种简单的方法是将MOJO封装在一个非常简单的最小web服务中。
下面是指向MOJO的javadoc的链接:
一个github回购演示如何在简单的Java容器中使用MOJO:
另外,这里有一个旧的github,您可能会发现它很有用,它使用POJO而不是MOJO。魔法更好。使用MOJO而不是POJO,但您可能会发现阅读本文中的文档很有帮助:
注意,如果您这样做,您仍然可以按比例/负载平衡python烧瓶应用程序和java评分后端服务(如果您愿意的话),尽管我的期望是java将比python快得多,因此,将python和java合并在一起可能更容易,并让python向本地java发出请求。
好了,现在我已经讨论了最佳实践方法,让我指出一些问题,我可以从您现在正在做的事情(困难的方式)。
,
不建议将H2O-3服务器进程作为长期运行的评分服务运行。但是如果你真的想这样做,可以采取以下步骤:
- The in-memory objects need to be cleaned out. You can find them with the h2o.ls() and remove them with the h2o.rm() calls in the R/python client APIs. Both the datasets and the scores would need to be cleaned up. You probably don't want to remove the model itself, though.
- I don't expect you need to manually trigger garbage collections in the Java process, but you can if you want to. Personally, I only do that when I have turned on Java flags like -XX:+PrintGCDetails -XX:+PrintGCTimeStamps so I can see the effect of the compaction on how much free heap memory remains after a Full GC. I do this so I can see whether objects are really being retained, so I can confirm they are getting cleared out. I like to give those logs to [http://gceasy.io](http://gceasy.io/) and visualize them.
- Do monitor the logs to see the free heap remaining after a Full GC.
- Even if you are doing the right stuff in terms of cleaning up memory, give the H2O-3 server process lots of memory. I wouldn't even run it on my laptop with a smaller -Xmx than 5G. As such, I would characterize the original poster's Java heap as severely under-provisioned (`H2O cluster free memory: 1.656 Gb`).
- If you see the free heap remaining after Full GC creeping up, restart the Java process, since this is not the standard use case and not something that gets thoroughly tested. The H2O-3 clusters are thought of by the development team as more as short-to-medium lifetime services (hours/days) than long-running services (months+, e.g. nginx/apache).
希望这能帮上忙!
https://stackoverflow.com/questions/61172226
复制相似问题