本文共 1909 字,大约阅读时间需要 6 分钟。
近年来,移动互联网和物联网开发的同学纷纷向我咨询推送服务相关问题,这些问题主要集中在以下几个方面:Netty是否适合作为推送服务器、一个Netty服务器最多能支撑多少个客户端、以及Netty在推送服务中遇到的各种技术问题等。
通过分析这些问题,我希望通过本文的案例分析和对推送服务设计要点的总结,帮助大家在实际工作中少走弯路。
在移动互联网时代,推送服务已成为App应用不可或缺的一部分。推送服务通过向用户发送通知、广告等消息,显著提升了用户的活跃度和留存率。随着物联网的普及,智能家居设备的接入数量呈快速增长,这使得推送服务面临着更大的挑战。
针对这些问题,部分企业提出了自己的解决方案,比如京东云推出的推送服务,通过多应用单服务单连接模式和定时心跳优化解决了电量和流量问题。
智能家居的MQTT消息服务中间件服务器需要维持10万用户的在线长连接,每天处理2万个并发消息请求。随着时间推移,程序出现内存泄露现象,怀疑Netty的Bug是导致问题的原因之一。
服务器配置为16G内存、8核心CPU,Netty中boss线程池设置为1个,worker线程池为6个,其余资源留给业务使用。后来将worker线程池调整为11个,问题依旧。
Netty版本为4.0.8.Final。
通过内存堆栈dump和对象关系分析,发现Netty的ScheduledFutureTask实例数量激增,达到10W个左右。进一步调查发现,IdleStateHandler用于处理链路空闲状态时设置的超时时间过长(15分钟),导致大量定时任务被创建并存活,占用大量内存。
每个长连接都持有一个ScheduledFutureTask,且这些任务保存有业务成员变量。尽管持久代设置较大,但这些定时任务未被及时回收,最终导致内存泄露。
重新设计IdleStateHandler的超时时间为45秒后发现内存问题得到有效解决。分析表明,100个长连接即便有长周期定时任务,也不会导致内存泄露问题,因为新生代通过minor GC即可回收内存。
作为高性能的NIO框架,Netty确实适合开发高效的推送服务,但要实现稳定性和性能的平衡,需要在设计阶段针对推送服务特点进行优化。
在Linux系统中,文件句柄数默认限制较低(如1024),直接导致Netty服务器接收客户端连接时遇到“too many open files”错误。通过修改内核参数和调整用户限制,可以将句柄数提升到1000000级。
ulimit -acore_file_size unlimitedulimit -nofile 1000000
在百万级推送服务中,服务端需要处理频繁的网络异常和客户端断连。以下是优化建议:
移动无线网络的特点决定了推送服务的心跳周期需要谨慎设计。合理的周期设置可以平衡客户端链路的稳定性和网络资源消耗。
对于海量长连接的推送服务,内存池能够显著减少内存泄漏和GC压力。通过使用PooledByteBufAllocator,可以实现缓冲区的动态管理,避免内存浪费。
合理设置TCP接收和发送缓冲区大小(如32K),优化软中断分配,提升网络通信性能。
合理配置JVM参数,避免Full GC,确保内存管理的高效性。
通过Netty的优化配置和合理设计,可以实现高性能的百万级推送服务。关键在于充分了解Netty的特点,合理设置心跳周期、优化内存管理、配置合适的TCP参数等。
转载地址:http://rjcfk.baihongyu.com/