walkor / channel

Interprocess communication component for workerman
137 stars 49 forks source link

关于 Channel Server 的一个较严重的问题 #16

Open xpader opened 2 months ago

xpader commented 2 months ago

近期项目中的 Channel Server 有严重的内存泄露问题,百思不得解,Channel Server 只负责消息的传递,本身不运行什么业务,怎么会内存泄露,而且之前运行一两个月也没什么异常。

后经过好多天的排查,发现是通过 Channel Server 传递闭包导致的内存泄露,闭包的序列化是使用 https://github.com/opis/closure 实现的,而 opis/closure 存在某些情况下的内存泄露。

而 Channel Server 也仅是传递,为什么会内存泄露呢?这就是 Channel Server 设计上的一个较严重的问题,Channel Server 会反序列化接收到的信息,从中拿到 channel 或者 queue 的名称等一些关联信息,然后再序列化后发送给其它进程,重点就是这里,因为整个信息是在一个大的数组中传递的,反序列化再序列化并不是只涉及到 Channel 组件自己的信息,也会包含业务传递的信息,但实际上 Channel 完全不关心业务数据,可却同时也会对业务的数据进行了反序列化和序列化,造成了完全不必要的性能浪费和其它隐患。而恰恰是这里执行了 opis/closure 的反序列化和序列化,导致内存的泄露发生在了 Channel Server 进程中。

改进思路是,把传递的消息进行拆分,让业务的数据序列化和反序列化只发生在调用方和接收方的进程中,Channel Server 仅对自己需要的关联信息进行相应处理,而业务数据则完全原样直传,避免业务造成的性能浪费、内存泄露等隐患发生在 Channel Server 中。

xpader commented 2 months ago

我有几个较大的改进想法。

walkor commented 2 months ago

不能破坏性更新,需要兼容老版本,欢迎pr

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: Pader @.> 发送时间: 2024年7月30日 18:45 收件人: walkor/channel @.> 抄送: Subscribed @.***> 主题: Re: [walkor/channel] 关于 Channel Server 的一个较严重的问题 (Issue #16)

我有几个较大的改进想法。

Channel 数据的传递不再使用 php 的 serialize/unserialize,而是直接 pack() 二进制打包,定义好各种头信息里的长度和定义,Channel 本身也仅仅是需要传递调用类型,名称这类信息,不用太复杂的处理,这样也可以更好的兼容二进制数据的传递。

对 Client 的方法名称进行大改,原来的名称和用法总感觉有点不好理解,我想把发布订阅模式的方法名改为 on(), once(), off(), emit(),消息队列的方法名改为 enqueue, dequeue, watch, unwatch。但这会带来破坏性更新。

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>

xpader commented 1 week ago

等有空的时候我先来改进其中的部分