百亿级实时消息推送的实战经验

1、信鸽的挑战

应用的用户的生命周期来说分5个阶段,即用户的获取、激活、留存、传播和收入,信鸽的消息推送是触达用户,提升留存的重要途径。

信鸽平台现已服务于数万的App开发者,日推送消息数60亿,推送支撑能力超过百亿;而精准推送是有效提高消息打开率的手段。信鸽的实践中案例数据表明,精准推送的平均CTR是全量推送的4倍! 那么,如何实现海量数据的压力下,满足实时、精准的推送要求,这里有很大的挑战。

这里我们主要讨论的是对于信鸽后台的挑战,主要有这三个关键字:海量、实时和精准。 海量是指,信鸽终端并发长连接是数千万,日推送量也有百亿的量级,服务于很多大客户,如王者荣耀,日活跃数千万,其推送量可想而知。 另外一些特殊行业的App,也有特别的推送诉求。比如资讯类的应用,时效性要求非常高,需要每秒千万级的推送速度。 而另一些应用则需要在达到运营目标的前提下,希望尽量减少对用户的骚扰,即精准推送。

2、信鸽的应对之道

1对于信鸽面临的挑战,我们做了哪些解决方案?

2优化方案:操作系统优化

先看一下在操作系统这个层级是如何对海量并发长连接的接入进行优化的。这里主要挑战是在内存,通过slabtop命令可以看到当前系统内存分配的情况。从这一栏可以看到,当我们构建了大概200万长连接的时候,整个系统的内存基本上已经满了。对于长连接的内存使用,会消耗在这6个数据结构上。 我们深入分析这6个来自epoll模型和内核TCP协议栈的数据结构。对于epoll模型,底层实现是一个特殊的文件系统,epoll文件的内容主要是保存了一棵红黑树和就绪的被侦听文件列表rdllist,红黑树的节点是被侦听文件对象。epoll主要提供了三个API:epoll_wait、epoll_create、epoll_ctl。当我们通过epoll_ctl把一个文件加入到epoll的时候,会创建两个数据结构epitem、eppool_entry,epitem关联到被侦听的文件fd,eppool_entry保存了事件就绪时设置rdllist的回调函数ep_poll_callback。我们从另外一个链路看一下网卡的收包流程,当数据包过来的时候,网卡接收完数据会产生一个硬中断,数据通过DMA拷贝到内存。系统通过软中断守护进程,调用网卡的驱动来完成数据包的解析并最终调用poll方法。poll方法会回调设置好的ep_poll_callback,即把fd挂到rdllist中,当调用的epoll_wait时候,即可获取到就绪的fd集合。

对于海量的并发连接,主要通过调整操作系统的配置来解决。信鸽使用了公司自研的tlinux 2.0,系统对于内存这一块也做了比较多的优化,具体的配置参数如下,可以看到,主要也是一些epoll的限制和TCP的内存的限制。

3优化方案:Server框架优化

看完操作系统层级的优化,我们再来看一下另一个主要性能优化的点——server框架。

这里的Proxy主要用于接入网络的请求,具体的业务逻辑代码是放在Work进程里面处理。整个框架做了一个通用的抽象,将一次数据请求主要分为数据接收、数据路由、最后是具体的数据处理。数据接入进程和具体数据处理进程,通过无锁的共享内存来通信,这样就避免了很多不必要内存拷贝和消息编解码操作。

4优化方案:协议栈优化

下面我们看一下协议栈的优化。这里的协议栈主要是指linux内核TCP协议栈。 linux内核的协议栈主要问题是相关Socket的方法都是系统调用,需要从用户态切换到内核态,数据从内核空间到用户空间也需要进行额外的内存拷贝操作。业界有一些开源的用户态TCP协议栈,可以解决这两个问题。 使用用户态的TCP协议栈需要优化的点是相关的接口和系统自带的Socket接口命名不一致,直接使用涉及到大量代码的修改,我们怎么样做到在不修改代码的情况下用TCP协议栈呢?这里是通过Hook机制,拦截相关Socket系统调用,dlsym符号解析返回自定义的Socket方法。

5优化方案:硬件性能挖掘

下面我们再看一下单机性能优化的最后一个点——对于硬件性能的挖掘。硬件性能的挖掘,主要是善于利用Intel CPU的指令集。可以拿我们经常使用的CRC32操作来举例。一般的CRC32实现是根据算法定义来执行字节转码操作,而Intel提供了一套SSE4.2的指令集,它里面包含CRC32的方法。我们可以看一下35W次计算两者的耗时对比,直接用Intel的指令集比一般的实现方法快6倍(如下图所示)。

6小结

性能好,推送才能顶住海量信息的压力,支撑公司内外业务核心,提供强有力的通道支持。

3、实时方案的构建

对海量设备进行实时推送主要的解决方案是针对推送的场景优化存储结构,同时将单个推送的RPC节点间调用转换成分布式的批量位图运算,优化Android终端长连接,接入集群分多地部署,做最近接入,和APNs的交互使用HTTP/2协议,对无效的token自动做数据清理。

我们这里举一个具体的场景来说一下倒排索引是如何应用到实时推送中的。

对于一个传统的系统来说,一次推送可以这样实现,一个应用下的N个用户的推送,转换成N次RPC节点间调用,人群信息、通道信息、地域信息分别保存在Mysql或者Nosql数据库中,每个RPC调用,需要到数据库里面检查一下他是否是男的,是否是广东的用户,再看一下是不是华为的设备或者小米的设备,判定完之后要进行地域的检索,看看接入的是哪个集群。整个流程下来之后,要经过大量的数据库操作,才能完成一次推送。 但是经过倒排索引的构建之后,所有的数据都可以放到内存中。比如男性人群,可以构建一个bitmap,小米的通道也是一个bitmap,华为的通道也是一个bitmap,不同的地域分别是不同的bitmap。当一次任务下发的时候,对bitmap进行一些&操作,就可以把最终需要推送的人群下发到相应的接入机中,整个过程可以做到ms级别。对于推送下发整个流程,检索是一方面,另一方面还需要查询路由信息找到终端TCP长连接的接入机,这些路由信息包含接入机的编号、进程的编号、长连接socket fd的编号,用一个long数据类型即可保存,所有的路由信息保存在分布式的Nosql内存数据库中,整个推送流程只有接入机的路由需要进行数据库的查询,结合本地的缓存,可以做到kw/s的推送下发速度。

4、精准推送的构建

1基本概念

信鸽的推送系统主要分为三部分:

  • 第一部分是数据;
  • 第二部分是具体的系统实现;
  • 第三部分是具体的应用。

具体的应用有这三个:

  • 实时推送;
  • 推送助手;
  • ABTest。

推送助手和ABTest的作用是更好地帮助用户使用消息推送来进行产品的运营。比如推送助手,对于很多运营人员来说,可能没有相关的运营经验,对内容的管理,他可能只大概知道需要推送的目标群体,但是他对推送文案不知道如果编写会更好,这个时候我们后台会对历史的推送进行数据的收集,对文案和推送的效果进行关联性的分析,当他选择一个推送场景的时候,我们就会把一些文案的样式和关键词给到他,让他自己组织出一个更好的推送的文案。另外一个是ABTest,用户自己手里有几个文案或者目标推送人群,当他不确定的哪个更合适的时候,我们给他提供ABTest的能力,从目标推送人群中抽取部分测试用户,多个文案经过实时推送,在几分钟的时间里,把推送的效果即点击率反馈给用户,系统自动或者由用户选择一个最佳的推送文案或者是一个最佳的目标人群对剩下的用户进行推送。

2系统实现

下面看一下系统的实现:主要分实时和离线。 离线部分主要是用来进行人群的挖掘。对于精准推送来说,它的核心是根据应用运营的目标将消息推送给匹配的目标人群。应用的运营的目标一般有提升用户活跃度,潜在流失用户挽回,提升应用收入等,不同人群的挖掘方法可能不尽相同,但流程基本一致,一般会分为数据的准备、模型的构建、预测结果、输出。 我们这里举一个实际的潜在流失用户人群挖掘的例子。我们想预测一下这个应用里面可能有哪些人是会流失的,这样应用可以针对这部分人群做一些挽留的推送。原始数据保存在HDFS或者TDW里面,经过数据加工以后,把用户可能流失的一些特征给提取出来,比如说有首次注册的时间、每日启动的次数、每日的活跃状态和最近登录的时间。 上述特征提取后有两条路径:

  • 一是要构建一个潜在流失用户预测的模型;
  • 二是在模型的基础上进行潜在流失用户的预测。

对于模型构建部分,需要结合真实的流失情况和特征,作为训练的样本,经过算法模型的训练之后,我们就得到了一个潜在流失用户预测的模型。对于每天新增的数据,我们也是经过特征提取之后,把数据输入这个模型里面,就会得到一个具体的预测结果即可能会流失的人群集合。 对于算法模型,我们这边主要用了一些机器学习里面的统计学习的方法,没有用到一些现在比较火的深度学习的方法。因为我们在实际进行训练的时候发现当我们的数据样本非常大的时候,用一般的比如C4.5决策树模型,通过一些判定规则,就能够知道用户是否流失,或者是贝叶斯,通过特征类别的条件概率分布预测是否会流失,采用这些模型召回率可以达到0.76和0.89的水平,已经满足我们的应用场景,所以没有采用计算复杂度更高的深度学习的模型。

5、实时效果评估

上面这些数据到进入到系统的时候,主要会做两部分的操作:

  • 第一部分是根据推送文件指定的方法进行数据的抽取、过滤、转换、加载并更新相关的倒排索引数据;
  • 第二部分是当真正需要指标输出的时候,我们会有一个管理的节点,进行计算规则的下发,比如说点击的用户里面有多少是男的,检索以后进行一次bitmap的&操作,就能统计出有多少用户了。数据会实时刷新到Redis存储中,应用开发者在前台查询结果的时候,我们就会把这个结果反馈给用户。

能看到这里的都是真爱!

原文发布于微信公众号 - IT技术精选文摘(ITHK01)

原文发表时间:2018-05-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张戈的专栏

详解Linux系统的CPU负载均值

上一篇文章的最后,作者提到了文章的参考来源,我特意前往访问了下,发现写得非常不错,特转过来,可以结合阅读,以便更容易理解 CPU 负载这个概念。 你可能对于 L...

4159
来自专栏SDNLAB

SDN技术分享(十):GoogleFiber的宽带接入速率控制解决方案

本次分(zhuang)享(bi)呢,主要探讨一个新兴SP客户的案例。 G家,这是非传统的SP。我们一起来看一下G家的市场策略以及使用的关键技术. 内容比较多,我...

37513
来自专栏SDNLAB

SDN技术分享(十):GoogleFiber的宽带接入速率控制解决方案

本次分(zhuang)享(bi)呢,主要探讨一个新兴SP客户的案例。 G家,这是非传统的SP。我们一起来看一下G家的市场策略以及使用的关键技术. 内容比较多,我...

2837
来自专栏腾讯云技术沙龙

甘恒通:腾讯信鸽海量移动推送服务构建

我分享的主题是腾讯信鸽海量移动推送服务的构建,在加入腾讯TEG数据平台部后,我主要从事大数据相关的一些系统和应用开发。最近一两年主要是构建腾讯云推送,也就是信鸽...

68510
来自专栏IT技术精选文摘

理解Linux中Load_average负载

负载均值在 uptime 或者 top 命令中可以看到,它们可能会显示成这个样子:load average: 0.09, 0.05, 0.01 很多人会这样理解...

19410
来自专栏鹅厂网事

数据中心网络中的hash问题研究

"鹅厂网事"由深圳市腾讯计算机系统有限公司技术工程事业群网络平台部运营,我们希望与业界各位志同道合的伙伴交流切磋最新的网络、服务器行业动态信息,同时分享腾讯在网...

2355
来自专栏SDNLAB

浅谈基于意图的网络(IBN)

在园区网络中,有许多新兴趋势影响着未来网络建模的方式,这些趋势包括移动性、物联网(IoT)以及跨有线和无线连接的统一安全性。

902
来自专栏后台系统海量服务

自适应柔性模型

“弃车保帅”, 是对柔性的一个最形象的描述。但是传统的柔性,一般存在各种缺陷。

1405
来自专栏网络

理解Linux中Load

负载均值在 uptime 或者 top 命令中可以看到,它们可能会显示成这个样子:load average: 0.09, 0.05, 0.01 很多人会这样理解...

1739
来自专栏CSDN技术头条

HBase在滴滴出行的应用场景和最佳实践

背景 对接业务类型 HBase是建立在Hadoop生态之上的Database,源生对离线任务支持友好,又因为LSM树是一个优秀的高吞吐数据库结构,所以同时也对接...

2736

扫码关注云+社区