基于Netty的消息推送服务器集群设计与实现
2018-05-15徐龙光何顶新
徐龙光 何顶新
摘 要:消息推送是当前移动应用中十分必要的一项技术,服务者需要使用消息推送以保持用户活跃度,提高应用存留率。为了满足消息推送的需求和增强推送系统的性能,采用Netty网络编程框架并搭建消息推送服务器集群,使用TCP链接发送心跳包,以保持和维护连接状态进行消息推送。通过性能测试,结果表明服务器集群可以分散链接压力,有效提高服务性能。
关键词:消息推送;Netty;长连接;服务器集群
DOI:10.11907/rjdk.172207
中图分类号:TP319
文献标识码:A 文章编号:1672-7800(2018)004-0118-02
Abstract:Information pushing system is a necessary technology in current mobile applications. The server needs to use information pushing to keep the user's liveness and increase the retention rate of the application. In order to meet the needs of information pushing and enhance the performance of pushing system, Using Netty network programming framework building a information pushing service cluster, and using TCP toit is proposed to employ Neety network programming framework to build an information pushing service cluster and use TCP to send heartbeat package to send heartbeat package to maintain the connection status. Through the performance test, the results show that the service cluster can distribute link pressure and improve the service performance effectively.
Key Words:information pushing; Netty; long polling; server cluster
0 引言
消息推送是当前移动应用和网页应用中常用的一种服务和技术,目的在于从服务器端主动向客户发送消息。常用的推送技术包括客户端轮询、长连接、APNS、C2DM[1]等,本文采用TCP/IP长连接方式。消息推送有时面临百万级甚至更多链接数,需要由服务器集群提供足够的硬件性能和链接稳定性。
1 Netty簡介
Netty[2]是一个致力于快速开发的事件驱动的异步网络编程框架和工具,它基于JAVA NIO开发,开发者可采用Netty基于Channel对网络通信进行开发。Netty在提供很好性能的同时,极大地简化了网络编程,可进行如TCP、UDP套接字服务器的开发。由于Netty的易用性和高性能,其被众多大型项目采用为网络通信模块的编写框架。
1.1 Netty优化选项
Netty封装了JAVA NIO的ByteBuffer为ByteBuf,简化了对缓冲区的操作。在高性能场景中,可以直接分配堆外内存池作为缓冲区,从而减少内存拷贝和上下文切换,以此提升性能。Netty下有两种NIO实现方式,一种基于Select,另一种基于Epoll[3]。相较于Select,Epoll针对有大量链接时的情况进行了改进,采用EpollEventLoopGroup替代NioEventLoopGroup作为线程组,在链接数增多时可以显著提升性能。
2 系统设计
2.1 协议设计
当前有一些基于XMPP协议的推送服务方案[4],并且有一些方案是代码开源的,但是对于单纯的推送功能,XMPP协议有相当程度的冗余。基于消息推送的目的,重新设计一个通信协议,并且定义消息模型是十分必要的。如图1所示为传输协议的设计。2个字节的消息类型标志位用来表示消息类型,还有2个字节代表消息体长度,之后是消息体。
消息体设计代码如下:
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
private String type;
private String content;
private String sender;
private String receiver;
private String format;
private TimeStamp timestamp;
……
}
type 为自定义的消息类型,sender表示消息发送者账号,reciver表示消息接受者,content表示消息内容,与fortmat结合可以组成任何消息类型,如text、json、xml等。timestamp为时间戳,用于心跳机制的断线重连和传递消息传输时间。
2.2 心跳机制设计
通常情况下,TCP[5]链接一旦连接上,就一直保持开启状态,但服务器和客户端只是保存了链接开启状态,并没有实际的物理通路。并且由于网络情况十分复杂,如果不是正常关闭TCP链接,而是由于网络或程序异常导致一方TCP链接关闭,另一方则无法得知链接失效,使客户端不能自动重连,服务器端也无法得知对方已不在线,不能释放无效链接。虽然现在大多数TCP协议的实现中都有保活定时器机制保障链接存活,但是其默认超时时间2h过长。不同系统更改超时时间方法不一,没有通用的API接口,并且在一些特殊的网络环境中还会使保活机制失效,所以在应用层中实现心跳包是十分必要的。Netty中可以通过将IdleStateHandler类添加进Channel的PipeLine中,实现指定时间内没有读或写时向对方发送心跳包。系统中,设计链接失效时间为100s,每30s如果客户端没有写消息,则向服务器发送心跳包;若服务器没有回应,则利用上次服务器回应的消息体中的Timestamp与当前系统时间进行比较;若超过100s则链接失效重连。服务器接到心跳包则给予回应。
2.3 服务器集群设计
服务器集群的搭建[6]主要包括一个链接调度服务器,若干数据逻辑服和数据库服务器,其中,链接调度服务器也可以使用数据逻辑服务器充当。数据逻辑服务器是客户端真正连接的服务器,处理各种业务逻辑与推送消息,数据库服务器基于MysQL[7]构建,在本系统中主要负责存放各个链接的信息,使各个独立的数据逻辑服务器和链接调度服务器能够安全地共享数据。服务器集群框架如图2所示。
不同于只使用单台服务器时,客户端直接向固定服务器IP发起登录请求、建立链接,在集群环境下,客户端先向链接调度服务器发起HTTP请求,获取相对空闲机器的IP,然后再向该空闲机器发起登录请求,建立链接。本文自定义一个Session数据模型,主要字段包括绑定的Netty Channel名称,链接绑定的服务器IP、绑定账户的ID等,用来管理和操作链接。用户在登录时将该Session信息存入数据库,可以统计各服务器的链接数,以及寻找到Session存在于哪台服务器上。链接调度服务器采用最少链接法[8]对长连接进行调度,该服务器利用用户登录时存储在数据库里的链接信息,统计各个数据逻辑服务器的链接数量,使新链接总是连上最少链接数的数据逻辑服务器。在一台数据逻辑服务器推送消息时,先判断当前Session的链接是否存在于当前服务器,若存在,则直接利用该链接进行消息推送;若不存在,则需要查找数据库,找到该链接存在的服务器,并向该服务器转发消息,并由其进行消息推送。
3 性能测试
通常的性能测试需结合具体应用场景,在生产环境相同的硬件配置下,估计用户的实际操作行为,采用一定策略进行模拟,以产生对服务器的大量请求。而为了与单机时的并发数作对比,以测试服务器集群分散请求的能力,考虑平台搭建的简易型,可以使用VMware虚拟来搭建服务集群进行测试。测试使用的宿主机配置为CPU: Intel E3-1231 v3 3.4GHz,内存32GB,硬盘为1T机械硬盘,操作系统为Windows 7。每台逻辑服务器设定虚拟机的CPU数为4,4GB内存,20GB硬盘。测试采用的策略是,采用Apache JMeter设定TCP并发链接数,并无限循环给服务器发送test字符串,服务器回应received字符串。单台服务器测试数据如表1所示,两台服务器测试数据如表2所示。通过测试可以看出,通过将链接压力分散到不同服务器上,可以提高并发链接数。
4 结语
针对移动端APP中消息推送的需求,本文提出一种基于Netty网络编程框架的服务器集群设计,介绍了Netty框架的原理及优势,并针对业务需求提出了一些优化手段,阐述了设计中的协议设计、消息模型、心跳机制以及服务器集群架构。通过性能测试,证明可以通过服务器集群分散链接压力,提高并发数,具有一定实用性。
参考文献:
[1] 张长学,张伟,董智明.移动推送技术面面观[J].移动通信,2011(5):21-27.
[2] 李林锋.Netty权威指南[M].北京:电子工业出版社,2014.
[3] 余光远.基于Epoll的消息推送系统的设计与实现[D].武汉:华中科技大学,2011.
[4] 代超.基于Netty的面向移動终端的推送服务设计[J].软件,2015,36(12):1-4.
[5] 罗亚非.基于TCP 的Socket 多线程通信[J]. 电脑知识与技术:学术交流,2009,5(3):563-565,598.
[6] 胡晓燕.基于服务器集群的推送技术的研究与应用[D].南京:南京理工大学,2014.
[7] 刘鑫.MySQL 和PostgreSQL 的对比选择[J]. 沈阳工程学院学报,2011,7(2):171-173,177.
[8] 任亨.基于MQTT协议的消息推送集群系统的设计与实现[D].沈阳:中国科学院沈阳计算技术研究所,2014.
(责任编辑:黄 健)