如何用netty来搭建亿级消息推送网关
Posted 科技中通
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用netty来搭建亿级消息推送网关相关的知识,希望对你有一定的参考价值。
一、业务背景
中天门户(业务系统web门户)的消息推送功能模块(主要推送订单数据和问题件给需要处理的部门,提醒他们及时处理货物流通时的问题)、C端网页端用户中心的微信二维码扫描登录模块、快递管家(商家下单打印系统)消息推送模块,都遇到了性能问题和消息触达及时性问题,问题的原因是推送所用的架构模式都是短连接模式,所谓的短连接模式是client向server发起连接,server接到请求,双方建立连接,client向server发送消息,server回应client,一次读写完成双方都可以发起close请求。短连接的应用,以之前C端微信二维码登录为例,如下图:
当用户通过微信扫描后,微信开放平台会发消息给C端后台服务,而网页端每隔几秒钟不停的向C端后台服务发送请求,来确认是否有用户通过微信扫描登录。
由于短连接对于服务器来说较为简单,存在的连接都是有用的连接,不需要额外的控制,但如果客户端连接频繁,会在tcp的建立和关闭上浪费时间,且由于每次请求都需要线程去处理,服务器性能也不高,如果在线用户数量过多的话,每隔个一两秒请求一次,服务器就会承受很大的压力。
消息推送除了性能和及时性以外,我们还需要知道哪些用户在线、解决单台机器支撑数十万乃至百万用户的在线推送问题、具有支持多协议的功能,比如方便后端服务调用的RPC协议。基于此我们自主研发了消息推送网关,对外通过实现socket/websocket/长轮询等协议,对内部系统提供dubbo、http、RMI 服务,简化了消息推送中客户端和服务端之间的技术复杂度。
二、架构设计思路
在浏览某些网页的时候,例如 QQ网页版、在线客服服务、CSDN站内私信消息等类似的情况下,我们可以在网页上进行在线聊天,或者即时消息的收取与回复。可见,这种功能的需求由来已久,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询、Comet技术、WebSocket技术、SSE(Server-sent Events):
通过几种模式的对比,可见Comet、websocket更适合现有场景的需求,即只使用chrome/firefox做为浏览器的内部系统,使用websocket技术,外部系统使用Comet技术。所以Comet长轮询和websocket 将作为消息推送网关的主要支持协议,为了同时能够兼容这两种模式且发挥服务器的最大性能,使用了netty作为框架底层来实现。
三、实现原理
消息推送网关基于netty4 ,客户端与服务端建立TCP 全双工通道的NIO模式,和传统的一个连接一个线程式的BIO不同,NIO是非阻塞的,能支持更多的连接。
四、整体架构
客户端注册后,针对每个用户发放一个ID,作为该客户端的标识。在敏感的数据交互场景中,若有连接进来,需要进行鉴权,对于非法的连接进行拒绝,对于合法的连接进来后,注册到注册中心,这样就知道每个客户端的连接在哪个服务器上。
每个模块的角色:
1. Boss Group线程组:作为服务端Acceptor线程,用于accept客户端连接,并转发给WorkerGroup中的线程;
2. Worker Group线程组:作为IO线程,负责IO的读写,从SocketChannel中读取报文或向SocketChannel写入报文;
3.连接空闲检测Task:作为定时任务线程,执行定时任务,例如连路空闲检测;
4.pipLine: 是一个负责和执行ChannelHandler的职责链;
5.编解码器:负责接收数据的加解码;
6.分块写处理器:主要用于大文件传输;
7.对象聚合器:会把请求转换成另外一个对象;
8.proxy server :调用后端接口代理;
9.http服务:主要是用于暴露Http服务给路由分发服务;
10.路由分发服务:主要是通过注册中心,知道某个用户的连接在具体哪一台机器,后端无需关注用户登录在什么机器,只需要知道用户的ID,就可以对用户所登录在线的机器发送消息,由路由分发服务来找到对应的网关,对外暴露dubbo\RMI\http协议,满足不同调用需求。
该系统可以进行横向伸缩,当需要支持更多的客户端或者需要传输的数据时,通过新增机器就可以满足,理论上是没有上限的。
五、上线后成果
消息推送网关已经应用于中天门户的消息推送功能模块、C端用户中心的微信二维码扫描登录模块、云打印中的PC/移动端打印信息推送模块,尤其解决了业务系统门户(中天门户)即时消息推送不畅的问题。
消息推送:最早门户消息提醒并非使用长连接而是使用HTTP短轮询,每个用户发消息过来后产生一个对后台服务的远程调用,在用户量小时,对后台压力并不是很大,而如果用户数变大后,后台将开始出现服务超时等现象且当用户数达到3W后系统频繁宕机,反应在功能上就是用户收不到消息,而现在中天作为业务系统门户,每天登录用户将超过10W+,通过网页版前端登录后,跟服务端保持长连接,后端根据用户ID,针对某个用户的消息进行推送,触达及时且单一机器可承载用户数更多;
微信图像二维码登录:实现用户使用微信扫一扫,在扫描图像二维码后微信会回调后台接口,后台需要及时通知到客户端,客户端收到后进行登录跳转,前期二维码扫描登录,是通过每5秒短轮询一次后台判断用户是否已经通过微信扫描,这样由于每次请求都需要进行加解密操作,当用户量大时后台负载也变大,且用户反馈扫描后长时间无反应或者反应很慢,用户体验不好,使用消息推送网关后单台机器即可支撑且完美解决客户体验问题。
打印消息推送:由于打印消息推送和普通的消息推送的区别在于推送打印数据的时效要求和.net交互,之前使用的第三方推送由于心跳间隔比较长,如果网络抖动或者在心跳间隙断开,后台并不知道,这样推到前端就无法触达,消息推送网关通过缩短心跳间隔时间和后台调整获取打印消息的逻辑解决。
除了以上场景,还能满足以下一些场景:
在线人数实时报表:通过session管理器可以实时拿到在线的session以及用户通过哪些客户端连接。
聊天室:通过两个客户端都连接到网关,通过服务代理把消息进行交换。
文件上传下载:在上传时会将文件分成多个小块chunck,比方说:一个文件10M,网关会用ChunckedWriteHandler(支持异步发送的码流(大文件传输)但不占用过多的内存,防止java内存溢出)类将这个文件拆分,比如说分成10份,每份1M分10次进行传输,将10次传输封装成1个response进行响应,这样每次传输的内容小所以够快。
基础资料实时同步:现在智能终端或者PDA的基础资料大部分采用开机下载和定时拉取的设计,可以通过消息推送网关,把更新的基础资料数据实时分发,解决基础资料同步延时问题。
六、未来展望
对于消息推送网关在中通多客户端消息推送场景的应用比较多,解决了消息推送对于业务开发的复杂性问题和消息触达及时性问题,消息推送网关还在不断的优化,下阶段将在此基础上把APP的推送进行整合,做到无论用户从APP端还是从网页端上线,都可以通过网关进行推送,后台业务系统无需关注用户在哪个端上线。
团队简介
营销信息化团队,是一个有着梦想的团队。抱着敢想、敢干、会干、干成的精神,不断前进不断进步。我们的目标是提高企业的信息化水平和市场营销水平,打造智能化信息系统,我们致力于支撑中通的末端、B端、C端、CRM、推送平台的建设。目前我们拥有先进的技术栈,也有丰富的微服务架构、分布式架构经验,欢迎大家加入。
以上是关于如何用netty来搭建亿级消息推送网关的主要内容,如果未能解决你的问题,请参考以下文章
如何用java给指定的微信用户推送消息,每天早上十点推送一条消息。麻烦说的仔细一点,最好能给出实例谢谢