问题背景
频繁调用cli命令模拟告警,dbus-daemon内存持续上涨到400M
问题根因
dbus设计之初(20年前),malloc的实现还比较慢速,所以实现了一个cache机制来加速,它会复用之前申请过的内存块,避免频繁的内存分配和释放
dbus-daemon内存为什么会增长:在大压力场景下(生产消息的速度远远超过消费消息的速度),dbus-daemon处理消息的速度跟不上新增消息的速度,若dbus-daemon处理的消息在之前没有可复用的cache,此时cache会不断扩容,于是在此场景下dbus-daemon的内存会持续增长
1. DBusLink cache为什么不做限制?
在大压力场景下,dbus-daemon已经难以处理消息,若此时限制DBusLink cache的扩容,又会回到频繁的内存分配和释放,更难以处理消息,更容易遭受拒绝服务攻击。DBusLink cache虽然没有限制,但是dbus-daemon内存是有限制的,且可根据配置文件限制其消息处理速度,以避免其cache不断扩容,进一步限制dbus-daemon内存增长
2. 压力消失之后dbus-daemon内存为什么没有减少?
1)dbus-daemon是通过glibc提供的free函数释放内存的,而glibc管理内存时,一般是申请一大片内存后自行管理,满足一定条件后才归还给OS,所以dbus-daemon free的内存不一定归还OS,dbus-daemon增长的内存也就不一定会减少
2)cache扩容加深了内存碎片化,导致glibc更难以将申请出来的内存归还给OS,进而导致dbus-daemon增长的内存不会减少
案例结论
因dbus社区策略(cache不做限制的策略是为了缓解拒绝服务攻击)和dbus代码耦合元素过多(短期内无法评估限制cache后带来的影响),DBusLink cache机制只能暂时保持现状。可以通过修改dbus-daemon配置文件的配置项max_outgoing_bytes控制dbus-daemon内存上涨幅度
解决方案
修改dbus-daemon配置文件/opt/bmc/dbus.config,其配置项max_outgoing_bytes用于限制单个连接或会话中待发送数据队列的最大字节,其大小与dbus-daemon内存上涨上限成正相关,将max_outgoing_bytes大小从20M减小为5M,dbus-daemon内存上涨上限下降到128M左右