Erlang Binary Leak?

我们有一个处理大型json有效负载的erlang / elixir应用程序(在18 / erts 7.3.1上).

这是一个典型的工作流程:

>侦听器从rabbitmq获取令牌并发送到gen_server.
> gen_server将令牌放入具有未来时间(当前n秒)的ETS表中. gen_server中的计划作业将从ETS中获取过期的令牌,并使用这些令牌启动几个短期进程.
>这些短暂的进程从elasticsearch(使用hackney)下载30-50k json有效负载并对其进行处理,然后将结果上传回elasticsearch,之后进程立即死亡.我们跟踪这些过程并确认它们已经死亡.我们每秒处理5-10个这样的请求.

问题:我们看到一个不断增长的二进制空间,并在48小时内增长到几个GB(通过观察者和调试打印看到).手动GC也没有影响.

我们已经添加了“recon”并运行了recon:bin_leak,但是这只会释放几KB并且不会对不断增长的二进制空间产生影响.

堆栈:Erlang 18 / erts 7.3.1,elixir 1.3.4,hackney 1.4.4,毒药2.2.0,timex 3.1.13等,这些应用程序都没有内存.

过去有没有人遇到过类似的问题?将不胜感激.

2017年9月15日更新:

我们更新了我们的应用程序到Erlang 19 / ERTS 8.3和hackney和毒药库到最新,仍然没有进展.这是GenServer中的一些日志,它使用spawn / receive或send_after定期向自己发送消息.在每个handle_info中,它查找一个ets表,如果它找到任何“符合条件”的条目,它会产生新的进程.如果没有,它只返回一个{:noreply,state}.我们在函数入口处打印VMs二进制空间信息(以KB为单位),日志列在下面.这是一天中的“空闲时间”.你可以看到二进制空间的逐渐增加.再一次:recon.bin_leak(N)或:erlang.garbage_collect()对这种增长没有影响.

11:40:19.896 [warn]二进制1:3544.1328125

11:40:24.897 [warn]二进制1:3541.9609375

11:40:29.901 [warn]二进制1:3541.9765625

11:40:34.903 [warn]二进制1:3546.2109375

—一些处理—

12:00:47.307 [warn]二进制1:7517.515625

—一些处理—

12:20:38.033 [warn]二进制1:15002.1328125

在我们的旧Scala / Akka应用程序中,我们从来没有遇到这样的情况,该应用程序多年来处理量超过30倍而没有问题或重新启动.我写了两个应用程序.

最佳答案 我们发现memory_leak来自一个私有的可重用库,它向Graylog发送消息,并使用下面的函数压缩该数据,然后通过gen_udp发送它.

defp compress(data) do
    zip = :zlib.open()
    :zlib.deflateInit(zip)
    output = :zlib.deflate(zip, data, :finish)
    :zlib.deflateEnd(zip)
    :zlib.close(zip)  #<--- was missing, hence the slow memory leak.
    output
end

而是使用term_to_binary(数据,[:压缩]),我本可以省去一些麻烦.

感谢所有的意见和建议.非常感激!

点赞