Erlang SSL TCP 服务器和垃圾收集
Posted
技术标签:
【中文标题】Erlang SSL TCP 服务器和垃圾收集【英文标题】:Erlang SSL TCP Server And Garbage Collection 【发布时间】:2018-01-28 21:19:45 【问题描述】:编辑:问题似乎与 SSL 认证和内存泄漏有关。
我注意到如果你的进程(它是一个服务器)存在很长时间,并且客户端将数据发送到服务器(recv),那么 Erlang 垃圾收集永远不会被调用(或很少)
服务器需要数据(执行操作),并且数据可以是可变长度的(由于诸如“Hello”或“How are you doing”之类的消息)。因此,Erlang 进程似乎会堆积垃圾。
你怎么能正确处理这个,Erlang进程必须接触recv数据,所以它是不可避免的吗?或者您是否必须想出接触可变长度数据的次数更少的设计(例如立即将其传递给端口驱动程序)。
产生一个工人来处理数据是一个糟糕的解决方案(数百万个连接......),使用工人基本上是一回事,对吧?所以这让我的选择很少。
谢谢...
【问题讨论】:
你需要更多关于erlang GC的细节,我推荐阅读hamidreza-s.github.io/… 【参考方案1】:如果服务器保留接收到的消息的时间超过了它需要的时间,这是服务器实现中的一个错误。通常,当请求完成处理时,服务器应该忘记对请求中数据的所有或大部分引用,然后数据将变成垃圾并最终被收集。但是,如果您将每个请求的数据粘贴在进程状态的列表中,或者在 ets 表或类似的表中,您将得到内存泄漏。
对于大于 64 字节的二进制文件有一点例外,因为它们是通过引用计数来处理的,并且对于内存分配器来说,看起来还不需要执行收集,尽管使用的字节数已关闭- 这种二进制文件的堆可能非常大。
【讨论】:
【参考方案2】:以防万一有人发现自己在同一条船上。当一次用许多连接敲击服务器时,这是已知的/正在发生的。我想。
在没有 ssl 的情况下,我的会话大约为 8KB,并且资源正在按预期触发 GC。使用 SSL 后,它增加到约 150KB,并且内存不断增长。
http://erlang.org/pipermail/erlang-questions/2017-August/093037.html
【讨论】:
你可以尝试通过调用 erlang:garbage_collect/0/1/2; 来尝试强制 GC见erlang.org/doc/man/erlang.html#garbage_collect-0。如果在每个请求后 GC:ing 有效,请尝试将其减少到每个 n:th 请求并为 n 找出一个合适的值。 我不知道它是否解决了问题,但即使使用 SSL 进行所有这些修复,用户进程也会增加 142+KB(这没有任何逻辑,只是一个 ssl:recv)。这是无法接受的。我的解决方案是仅使用 SRP 登录凭据并为数据启用某种类型的加密(可能是 AES)。【参考方案3】:您可能在处理大型 SSL/TLS 会话表时遇到问题。我们(OTP 团队)历来对这些表存在一些问题,因为如果您没有一些限制机制,它们可能会变得非常大。唉,在最新的 ssl 版本中,其中一个限制机制被破坏了,但是这个补丁很容易修复它。作为一种解决方法,您还可以牺牲一些效率并禁用会话重用。
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index ca9aaf4..ef7c3de 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -563,7 +563,7 @@ server_register_session(Port, Session, #statesession_cache_server_max = Max,
do_register_session(Key, Session, Max, Pid, Cache, CacheCb) ->
try CacheCb:size(Cache) of
- Max ->
+ Size when Size >= Max ->
invalidate_session_cache(Pid, CacheCb, Cache);
_ ->
CacheCb:update(Cache, Key, Session),
【讨论】:
以上是关于Erlang SSL TCP 服务器和垃圾收集的主要内容,如果未能解决你的问题,请参考以下文章