ade*_*ean 5 erlang elixir beam
我们有一个 erlang/elixir 应用程序(在 18/erts 7.3.1 上)可以处理大型 json 负载。??
这是一个典型的工作流程:
侦听器从 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、poison 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}。我们在函数入口处打印 VM 二进制空间信息(以 KB 为单位),日志列在下面。这是一天中的“安静”时间。可以看到二进制空间逐渐增大。再次 :recon.bin_leak(N) 或 :erlang.garbage_collect() 对这种增长没有影响。
11:40:19.896 [警告] 二进制 1:3544.1328125
11:40:24.897 [警告] 二进制 1:3541.9609375
11:40:29.901 [警告] 二进制 1:3541.9765625
11:40:34.903 [警告] 二进制 1:3546.2109375
--- 一些处理---
12:00:47.307 [警告] 二进制 1:7517.515625
--- 一些处理---
12:20:38.033 [警告] 二进制 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
Run Code Online (Sandbox Code Playgroud)
相反,使用 term_to_binary(data, [:compressed]) 我可以避免一些头痛。
感谢您的所有意见和评论。非常感激!