目前,在移动终端的使用方案中将使用大量消息推动。推送消息可以帮助操作员更有效地实现操作目标(例如推动用户营销活动或提醒应用程序的新功能)。
对于推送系统,需要以下两个特征:
在推送系统中,稳定性测试中的长连接群集和一段时间后的应力测试级别运行。概率将以较小的概率(频率约为每月一次)的时间效应挂起。
推送系统中的长连接节点(代理系统)基于Netty开发。该节点维护服务器和手机终端的较长连接。在线问题发生后,添加NetTY内存泄漏监测参数以调查问题。没有发现问题。
由于长连接节点是由Netty开发的,为了促进读者,让我们简要介绍Netty。
Netty是一个由高性能,异步事件驱动的NIO框架,基于Java Nio提供的API实现。IT为TCP,UDP和文件传输提供了支持。作为最受欢迎的NIO框架,Netty已获得广泛应用,Dubbo和其他开源组件也是基于Netty的Nio框架构建的。
首先,这是由长连接的数量引起的,但是在调查日志和分析代码之后,发现这不是由此引起的。
长连接的数量:390,000,如下所示:
每个通道字节的大小为1456,根据400,000长的连接计算,这不会导致内存过多。
检查GC日志,并在挂起该过程之前发现该过程经常是完整的GC,但是没有减少内存,并且怀疑该过程的外部内存泄漏堆。
ChannelOutBoundBoundBuffer对象将接近5G内存,并且基本上可以确定泄漏的原因:引起了ChannelOutBoundBuffer的入口次数。查看可以分析ChannelOutBoundBuffer的源代码,即ChannelOutBoundBuffer中的数据。
它没有写并导致积压。ChannelOutBoundBuffer是一个链接列表。
实际上有判断该连接是否可用(频道。发挥),并且会关闭超时连接。从历史经验判断,这种情况发生在连接半开放的情况下(客户端是异常)。
根据上述猜想,测试环境得到了复制和测试。
1)模拟客户端群集,并使用长连接服务器构建连接,以在客户端节点,模拟服务器和客户端网络异常的场景中设置防火墙(也就是说,通道的成功呼叫成功,成功,是成功的。但是数据不能发送出来)本质
2)调整外部内存的小堆栈,然后继续向先前的客户端发送测试消息。Message大小(约1K)。
3)根据128m内存计算,实际上,它将显示超过9W。
当未写入频道时,请关闭自动启动;
可以编写数据时自动启动;
阐明:
AutoRead的作用是更准确的速率控制。如果已打开,Netty将帮助我们注册以读取事件。阅读事件后,如果可以读取网络,则Netty将从Channel中读取数据。如果关闭AutoRead,则Netty将不会注册该事件。
这样,即使将数据发送到最后,它也不会触发读取事件,以免从频道读取数据。当recv_buffer满足时,将不会收到数据。
注意:使用高水位和低水位,以后有创造力
该频道不仅可以检查channel.iswrite()的判断,ISACTIVE只需要确保是否激活了连接,以及是否可以由ISWRITE编写。
注意:Isstrable可以控制ChannelOutBoundBuffer,以防止其无限扩展。它的机制是判断集合的高水位和低水位的设置。
修改修饰后,未报告测试为27W;
通常,Netty数据处理过程如下:将读取数据发送到业务线程处理,并且在发送之前完成处理(整个过程都是异步)。为了增加网络的吞吐量,Netty在业务层和套接字之间添加了一个Channeloutboundbuffer。
调用channel.write时,所有编写的数据实际上并未编写套接字。取而代之的是,我首先写了ChannelOutBoundBuffer。它在调用Channel.flush.blush.baf.baf.flush.baf中确实写在插座上。如果您不控制通道的速度。write,则此缓冲区中会积聚大量数据。当插座无法编写数据时(此时ISACTIVE是无效的)或慢慢写入。
可能的结果是资源的耗尽,如果将ChannelOutBoundBuffer存储在DirectByteBuffer中,这将使问题更难检查。
该过程可以抽象如下:
从上面的分析可以看出,步骤太快(几乎要处理),或者无法下游的数据可能引起问题。这实际上是一个匹配的问题。
超过高水位
当ChannelOutBoundBuffer的容量超过高水位设置阈值时,Isbritable()返回false,设置频道集(setunbrabletable),并触发firechannelwritabilitychaanged()。
低水位以下
当ChannelOutBoundBuffer的容量低于低水位设置阈值的容量时,Isbritable()返回true,设置写入通道并触发FireChannelWritabilityChaanged()。
当ChannelOutBoundBuffer的容量超过高水位设置阈值时,Isbritable()返回false,表明该消息已堆叠,并且需要降低写作速度。
当ChannelOutBoundBuffer的容量低于低水位设置阈值时,Isbritable()返回true,表明消息太小,需要提高写作速度。经过上述三个步骤,在线部署在线观察到,半年没有任何问题。
作者:Vivo Internet Server Team-Zhang Lin