年期间你参与百度的抢红包活动了吗?但是对这场活动批判的声音一直不绝于耳,我们在天天问讨论了这个问题,来一起看看大家是怎么说的吧~enjoy~
百度春晚豪掷9亿,能否达到其导流的目的?@问多多
今年,百度成为了春晚的独家互动合作伙伴。在春晚期间,它总共送出价值9亿人民币的红包。这次百度砸下重金,能否达到其导流的目的?
说下小问的情况,摇到手酸一共摇了2块钱,结果提现时候发现还要下载各种百度全家桶安装包,有点反感就直接卸载了。
(1)百度App本次春晚投放的目的还是扩大下载量,目前一二三线城市用户渗透率上升空间不大,而且很多对百度已经有比较大的成见,空白手机用户主要还是在四五六城市至十八线小镇,没有什么节目比春晚更强了。
9亿的话如果能够带来900万的下载量,一个用户获客成本也就100块钱,很值。还不算广告效益。至少大家知道了百度是App,不只是PC的搜索框,这个品牌认知对于百度非常重要。
(2)今年春晚百度非投不可,因为百度不投,就有头条会投。抖音和百度争夺独家冠名非常激烈,即使百度的效果不理想,也能够战略阻止头条在农村市场的进一步扩张。
其实头条在农村用户那里渗透率不足10%,这个是趣头条的数据,我不知道准不准确,但是抖音可能是有的。
百度为什么要战略防御头条呢?因为两家的盈利模式都是广告公司,百度的广告模式已经由大搜模式转向到信息流模式了。
(3)百度App春晚分四轮进行,主要是摇一摇模式。参与的门槛相对还是比较考虑“用户体验”的,而抽奖的门槛的话,如果门槛越低,其实越闹影子,难度越大,其实分的钱更实在。
我和答主一样,基本上没有去薅羊毛抢红包的意愿,我这两年过年时候可能要发出去2万的红包,当然不会寄希望于抽奖。但是不能说红包大战没有效,其实类似我这样的用户行为已经不再具备一般用户行为特征,靠自己的行为得出的结论无疑是有偏差的。这也是调查研究和结果反馈的意义所在。
(4)红包大战对于存量用户的意义不再抢多少钱,而在于用户提现的动作,换句话说,不是看Appstore以及安卓市场上的排名,而是去看有多少下载了App的用户去绑卡,绑卡就意味着是活跃的真实用户,其数据的准确率可以用来做征信,以及百度的金融业务即度小满。如果不绑卡的话,有余额的话,App被卸载的概率会非常低。
(5)客观去理解9亿或者10亿,这些是广告主或者说品牌商的广告费用,百度等于把这些金主的广告费直接分给用户,用户在抢红包的时候其实广告主也有曝光的,并非是百度自己的现金池,可能会有广告主的账期存在,但是红包大战本身也是一个商业模式。
以上一孔之见。
有个疑问,百度瞄准的确实是三四线的下沉用户,可是这部分用户下载完了要提现,发现还要绑定银行卡,有多少这部分的用户会绑卡呢?就我身边的亲戚来说,他们大部分是不愿意随便绑卡的,支付宝微信在市场上花了好几年的功夫才让他们敢于绑卡的。
引流肯定是有效果的,本人看到后既没有参与也没有提现。
说下我的行为路径:
第一步:手机里没下过百度APP,先打开了百度网页,网页上赫然几个大字,下载APP领红包,嗤笑一声表示理解,下载了APP,最开始是和支付宝类似的集卡预热活动,但是卡的种类也太多了吧,好像有7、8张,直接劝退了我(其实后来发现卡的种类虽多,却并不难集,这也给活动运营们敲个种,别搞太多花花绿绿的,卡片数量也是学问,像人家支付宝搞5种卡片就不多不少了)
第二步:等到春晚主持人宣布摇红包,四轮全部参与,开始狂摇,最后得了几块钱吧。
第三步:失望中准备提现,发现哎哟,还得等24小时审核,耐心已经被磨没,我要的就是新年抢红包的这个气氛,还搞个缓冲时间。
第四步:24小时过去,准备提现,发现,原来还是下载N个APP一个一个领啊,再想一下还有绑卡什么的操作,算了放弃了。
综上,这个活动让我觉得自己是一根羊毛被薅了,所以我怒卸百度APP,别说给百度系其他APP导流,百度APP我都不要了!我应该是个典型用户吧。
百度:下载一天,提现完卸载,收了9.58。
支付宝:扫福、答题、喂鸡、浇花、线下支付、操作10天,领了1.68,真棒。
论复杂的用户心理。
不能单单拿百度的春晚营销来说话,要对比一下百度和其他竞争对手的风格。
以百度和支付宝为例,百度只是单独场景的一次运用,仅仅在春晚摇红包,支付宝是一系列的运营过程,并且在运营过程中充分给客户游戏一般的体验。
由于它只是一个单次活动场景,用户的潜在逻辑是这是一项任务并且获得报酬。随后百度在后端设置上,需要用户各种下载APP才能领红包,这个对于用户来说会觉得投入产出比不成比例。
支付宝是通过游戏化的运营场景,让客户转移了参与目标大家在游戏的过程中反而淡化了利益诉求,更加像是一次较长时间的社交活动,所以即使麻烦一些用户也可以忍受。
说到底,还是初心的问题,赤裸裸的商业活动和体验班的社交营销是完全不同的感受。
是否达到引流?答案是:是的
但究其根本,是否只有引流这一个目的?答案是:绝对不是。
引流、品牌运营、产品推送 这三个目的比起来,可能引流就显得不是那么明显。
产品推送:从每天打开百度后的任务(给抽奖机会)就能看出来有这不同的任务去做,而最主要的是、需要一定用户消耗的就是下载好看、全民小视频、看多多,起码在这个活动前我对这些APP并不了解,百度可能借此机会将这3款软件进行强推,相信相关产品线过年都加班了吧。
三个软件在激活用户上也都用奖励抽奖次数进行了运营,如看一个视频之类,并且达到要求后系统提示,可以直接根据提示进行跳转也是很人性化的设定。
品牌营销:去除产品的思维,单说百度,用户一听百度搜索、度娘、百度一下、百度图片,而对于其他产品可能认知度就比较差了,这个活动还有一个目的就是让用户知道:小视频领域百度也在做,新闻也在做……
想是一方面,做又是另一方面。
多个APP,用户早就眼花缭乱,操作简单,用户只需要点点点,导致引流来的用户,只要有点洁癖,就会把软件统统删掉,引流来的用户并不能真正的触及产品,还不如来个:分享新年饺子视频就送1元来的块,起码用户有了沉默成本。
至于活动内容本身(集卡),楼上说过数量有学问,我觉得有道理,但可能是考虑到不想和支付宝重复,凑成了10个,其实也还行,我在这里不累述。
欢迎讨论!探讨大厂模式。
结论先行,目的已然达到。
光看整体资金规模9亿,一看很大,但是有多少用户被参与,审核,提现拦了一步又一步,真正的成本想必并没有那么夸张。
说下目的,通过春晚的覆盖进行下沉,一二线城市的整个渗透不用多言,我不怎么用用百度,但是肯定是知道的。
对于一二线城市的用户,几块钱红包的诱惑可能,不会一步一步下载APP,各种注册审核。但是对于三四五线城市就不是了,他们没有被互联网红利覆盖过,所以当微信,支付宝,百度们来“撒钱”的时候,有多少这样的目标人群能够把持住自己。
下了APP——注册了账号——成为了用户——使用了产品。
首先说,不管是不是摇红包的玩法,哪怕是个其他的玩法,跟春晚合作,一样可以达到导流的目的,只是中国人对春节收红包这个传统概念一直很认同。
亮点1:摇一摇是一个主要玩法,分时段的摇一摇瓜分是一个很好的设计流程,如果摇一次就结束,会减少用户粘性和兴趣,甚至有的用户会认为没玩够,这样设计,即使第一次没得到多少红包,用户的心里反应是还有下次。选择继续下一轮的用户会占大比例。
亮点2:在摇一摇结束的闲时,用户可以下载百度推荐的一些列产品并领取红包。这一项设计是对百度和用户都是有利的,但是个人认为大多数用户会选择在某一段闲时一次性全部下载完毕,这样虽然下载量有了,但是又有多少人下载后回去大概体验一下产品呢,都是下载完一个就继续下一个。
如果这里的流程能完善下,或许更能达到百度想要的效果,比如分时段性的引导下载,吊着用户胃口,比如8:00摇完后,引导下载一个,并模糊的告知下一个闲暇时段下载可领取88元红包,并不是一下子完全告知用户下载可得多少红包,也不是一下子全都堆给用户。
导流是肯定有的吧。
只是导了多少和留存多少的问题。
说活动恶心,百度也是没有办法,这种商业活动很多人都在玩,淘宝集能量也是N个App去签到,但是百度错就错在,这一切来得太突然了,没有提前宣告(或许可以,以全家桶集体拜的喜庆方式提前告知,让用户有心理预期),没有其他选择(要不让我选就在本App领取不下载其他,但红包金额折半也可以,虽然这个方案估计不可能)。让大家兴冲冲去抢红包的时候,却在大家没有预期下强制下载一堆APP,没有与民同乐反而处处都是商业味。
用户失望,活动失败也不是什么怪事了。
用红包吸引用户,追逐的是红包,会随红包水涨船高,而不是对内容对产品的真正的认可,但也会有保留一部分用户,这部分是一些什么样的用户呢,会是一些想继续参与抢红包活动的用户以及懒得管理各个app的用户,如果拥有这样的用户也算有些价值,但价值不大,因为这样的用户传播到用户群也会是同等的用户,从而形成负循环。
我是百度的长期使用者,很长时间我都保留百度这个app,直到有一天我发现可以从手机系统里自带的网站中登录百度,从此以后开始卸载百度,只有在什么时候需要百度的时候才会点开,这会是以后所有软件的常态,用的时候会启动,不用会删除以此来节省空间和页面。
就像软件商店中,需要的秒开一样,用完即退,除非里面有可以与用户产生互动的设计,否则很难吸引像我这样,要求效率的人。
每个app给自己定位不同,希望每一个app最后都能找到属于自己的定位,提供更好的内容服务以及用户体验,才是所有软件的生存之道,否则再多的激烈也只是徒劳。
用户不一样,所激励也是不同,没有说红包激励不好,只是相对人群,像我这样的人群,就完全没有必要,不会去参与,而且对我没我任何诱惑,不如实际多来点干货福利。希望对所有互联网的精英们有所帮助。
问题链接:https://wen.woshipm.com/question/detail/5vc898.html
对于百度红包你有什么想说的吗,来天天问和小伙伴们交流一下吧~
【天天问每周精选】第63期:互联网的春节效应,会让谁翻身?
【天天问每周精选】第62期:我们要不要紧紧黏住用户?
【天天问每周精选】第61期:据说大部分的产品经理都不喜欢自己的产品
【天天问每周精选】第60期:纳闷,天气类软件是怎么活下来的?
【天天问每周精选】第59期:价格补贴,贴着贴着把自己贴进去了
【天天问每周精选】第58期:「昙花一现」 的产品,是否算成功?
【天天问每周精选】第57期:为烂产品做运营,你是什么感受?
【天天问每周精选】第56期:我有些idea想找你聊聊
【天天问每周精选】第55期:了解抽奖设计背后的故事
【天天问每周精选】第54期:一年四季蹭热点,什么时候是个头啊
【天天问每周精选】第53期:你准备剁手了吗?来聊聊双十一的需求、玩法及未来
精选问题每周有,欢迎食用~配合回复味道更佳(∩_∩)
本栏目由天天问小编@Tracy 编辑,欢迎大家踊跃提问,一起交流。
题图来自Unsplash,基于CC0协议
然看到了《扛住 100 亿次请求——如何做一个“有把握”的春晚红包系统》一文,看完以后,感慨良多,收益很多。
图片来自 Pexels
正所谓他山之石,可以攻玉,虽然此文发表于 2015 年,我看到时已经过去良久,但是其中的思想仍然可以为很多后端设计借鉴。
同时作为一名微信后端工程师,看完以后又会思考,学习了这样的文章以后,是否能给自己的工作带来一些实际的经验呢?所谓纸上得来终觉浅,绝知此事要躬行,能否自己实践一下 100 亿次红包请求呢?
否则读完以后脑子里能剩下的东西不过就是 100 亿,1400 万 QPS 整流这样的字眼,剩下的文章将展示作者是如何以此过程为目标,在本地环境的模拟了此过程。
实现的目标:单机支持 100 万连接,模拟了摇红包和发红包过程,单机峰值 QPS 6 万,平稳支持了业务。
注:本文以及作者所有内容,仅代表个人理解和实践,过程和微信团队没有任何关系,真正的线上系统也不同,只是从一些技术点进行了实践,请读者进行区分。
背景知识
QPS:Queries per second(每秒的请求数目)。
PPS:Packets per second(每秒数据包数目)。
摇红包:客户端发出一个摇红包的请求,如果系统有红包就会返回,用户获得红包。
发红包:产生一个红包里面含有一定金额,红包指定数个用户,每个用户会收到红包信息,用户可以发送拆红包的请求,获取其中的部分金额。
确定目标
在一切系统开始以前,我们应该搞清楚我们的系统在完成以后,应该有一个什么样的负载能力。
用户总数
通过文章我们可以了解到接入服务器 638 台,服务上限大概是 14.3 亿用户, 所以单机负载的用户上限大概是 14.3 亿/638 台=228 万用户/台。
但是目前中国肯定不会有 14 亿用户同时在线,参考的说法:
http://qiye.qianzhan.com/show/detail/160818-b8d1c700.html
2016 年 Q2 微信用户大概是 8 亿,月活在 5.4 亿左右。所以在 2015 年春节期间,虽然使用的用户会很多,但是同时在线肯定不到 5.4 亿。
服务器数量
一共有 638 台服务器,按照正常运维设计,我相信所有服务器不会完全上线,会有一定的硬件冗余,来防止突发硬件故障。假设一共有 600 台接入服务器。
单机需要支持的负载数
每台服务器支持的用户数:5.4 亿/ 600=90 万。也就是平均单机支持 90 万用户。
如果真实情况比 90 万更多,则模拟的情况可能会有偏差,但是我认为 QPS 在这个实验中更重要。
单机峰值 QPS
文章中明确表示为 1400 万 QPS。这个数值是非常高的,但是因为有 600 台服务器存在,所以单机的 QPS 为 1400 万/600=约为 2.3 万 QPS。
文章曾经提及系统可以支持 4000 万 QPS,那么系统的 QPS 至少要到 4000 万/ 600=约为 6.6 万,这个数值大约是目前的 3 倍,短期来看并不会被触及。但是我相信应该做过相应的压力测试。
发放红包
文中提到系统以 5 万个每秒的下发速度,那么单机每秒下发速度 50000/600=83 个/秒,也就是单机系统应该保证每秒以 83 个的速度下发即可。
最后考虑到系统的真实性,还至少有用户登录的动作,真实的系统还会包括聊天这样的服务业务。
最后整体看一下 100 亿次摇红包这个需求,假设它是均匀地发生在春节联欢晚会的 4 个小时里。
那么服务器的 QPS 应该是 10000000000/600/3600/4.0=1157。也就是单机每秒 1000 多次,这个数值其实并不高。
如果完全由峰值速度 1400 万消化 10000000000/(1400*10000)=714 秒,也就是说只需要峰值坚持 11 分钟,就可以完成所有的请求。
可见互联网产品的一个特点就是峰值非常高,持续时间并不会很长。
总结:从单台服务器看,它需要满足下面一些条件。
①支持至少 100 万连接用户。
②每秒至少能处理 2.3 万的 QPS,这里我们把目标定得更高一些 ,分别设定到了 3 万和 6 万。
③摇红包:支持每秒 83 个的速度下发放红包,也就是说每秒有 2.3 万次摇红包的请求,其中 83 个请求能摇到红包,其余的 2.29 万次请求会知道自己没摇到。
当然客户端在收到红包以后,也需要确保客户端和服务器两边的红包数目和红包内的金额要一致。
因为没有支付模块,所以我们也把要求提高一倍,达到 200 个红包每秒的分发速度。
④支持用户之间发红包业务,确保收发两边的红包数目和红包内金额要一致。同样也设定 200 个红包每秒的分发速度为我们的目标。
想要完整地模拟整个系统实在是太难了,首先需要海量的服务器,其次需要上亿的模拟客户端。
这对我来说是办不到,但是有一点可以确定,整个系统是可以水平扩展的,所以我们可以模拟 100 万客户端,再模拟一台服务器,那么就完成了 1/600 的模拟。
和现有系统区别:和大部分高 QPS 测试的不同,本系统的侧重点有所不同。
我对两者做了一些对比:
基础软件和硬件
软件
Golang 1.8r3,Shell,Python(开发没有使用 C++ 而是使用了 Golang,是因为使用 Golang 的最初原型达到了系统要求。虽然 Golang 还存在一定的问题,但是和开发效率比,这点损失可以接受)。
服务器操作系统:Ubuntu 12.04。
客户端操作系统:debian 5.0。
硬件环境
服务端:dell R2950。8 核物理机,非独占有其他业务在工作,16G 内存。这台硬件大概是 7 年前的产品,性能要求应该不是很高。
服务器硬件版本:
服务器 CPU 信息:
客户端:esxi 5.0 虚拟机,配置为 4 核 5G 内存。一共 17 台,每台和服务器建立 6 万个连接,完成 100 万客户端模拟。
技术分析和实现
单机实现 100 万用户连接
这一点来说相对简单,笔者在几年前就早完成了单机百万用户的开发以及操作。现代的服务器都可以支持百万用户。相关内容可以查看 Github 代码以及相关文档、系统配置以及优化文档。
参考链接:
https://github.com/xiaojiaqi/C1000kPracticeGuide https://github.com/xiaojiaqi/C1000kPracticeGuide/tree/master/docs/cn
3 万 QPS
这个问题需要分 2 个部分来看客户端方面和服务器方面。
①客户端 QPS
因为有 100 万连接连在服务器上,QPS 为 3 万。这就意味着每个连接每 33 秒,就需要向服务器发一个摇红包的请求。
因为单 IP 可以建立的连接数为 6 万左右,有 17 台服务器同时模拟客户端行为。我们要做的就是保证在每一秒都有这么多的请求发往服务器即可。
其中技术要点就是客户端协同。但是各个客户端的启动时间,建立连接的时间都不一致,还存在网络断开重连这样的情况,各个客户端如何判断何时自己需要发送请求,各自该发送多少请求呢?
我是这样解决的:利用 NTP 服务,同步所有的服务器时间,客户端利用时间戳来判断自己的此时需要发送多少请求。
算法很容易实现:假设有 100 万用户,则用户 id 为 0-999999。要求的 QPS 为 5 万,客户端得知 QPS 为 5 万,总用户数为 100 万,它计算 100 万/5 万=20,所有的用户应该分为 20 组。
如果 time()%20==用户id%20,那么这个 id 的用户就该在这一秒发出请求,如此实现了多客户端协同工作。每个客户端只需要知道总用户数和 QPS 就能自行准确发出请求了。
扩展思考:如果 QPS 是 3 万这样不能被整除的数目,该如何做?如何保证每台客户端发出的请求数目尽量的均衡呢?
②服务器 QPS
服务器端的 QPS 相对简单,它只需要处理客户端的请求即可。但是为了客观了解处理情况,我们还需要做 2 件事情。
第一:需要记录每秒处理的请求数目,这需要在代码里埋入计数器。
第二:需要监控网络,因为网络的吞吐情况,可以客观的反映出 QPS 的真实数据。
为此,我利用 Python 脚本结合 ethtool 工具编写了一个简单的工具,通过它我们可以直观地监视到网络的数据包通过情况如何。它可以客观地显示出我们的网络有如此多的数据传输在发生。
工具截图:
摇红包业务
摇红包的业务非常简单,首先服务器按照一定的速度生产红包。红包没有被取走的话,就堆积在里面。
服务器接收一个客户端的请求,如果服务器里现在有红包就会告诉客户端有,否则就提示没有红包。
因为单机每秒有 3 万的请求,所以大部分的请求会失败。只需要处理好锁的问题即可。
我为了减少竞争,将所有的用户分在了不同的桶里。这样可以减少对锁的竞争。
如果以后还有更高的性能要求,还可以使用高性能队列——Disruptor 来进一步提高性能。
注意,在我的测试环境里是缺少支付这个核心服务的,所以实现的难度是大大地减轻了。
另外提供一组数字:2016 年淘宝的双 11 的交易峰值仅仅为 12 万/秒,微信红包分发速度是 5 万/秒,要做到这点是非常困难的。
参考链接:
http://mt.sohu.com/20161111/n472951708.shtml
发红包业务
发红包的业务很简单,系统随机产生一些红包,并且随机选择一些用户,系统向这些用户提示有红包。
这些用户只需要发出拆红包的请求,系统就可以随机从红包中拆分出部分金额,分给用户,完成这个业务。同样这里也没有支付这个核心服务。
监控
最后,我们需要一套监控系统来了解系统的状况,我借用了我另一个项目里的部分代码完成了这个监控模块,利用这个监控,服务器和客户端会把当前的计数器内容发往监控,监控需要把各个客户端的数据做一个整合和展示。
同时还会把日志记录下来,给以后的分析提供原始数据。线上系统更多使用 opentsdb 这样的时序数据库,这里资源有限,所以用了一个原始的方案。
参考链接:
https://github.com/xiaojiaqi/fakewechat
监控显示日志大概这样:
代码实现及分析
在代码方面,使用到的技巧实在不多,主要是设计思想和 Golang 本身的一些问题需要考虑。
首先 Golang 的 goroutine 的数目控制,因为至少有 100 万以上的连接,所以按照普通的设计方案,至少需要 200 万或者 300 万的 goroutine 在工作,这会造成系统本身的负担很重。
其次就是 100 万个连接的管理,无论是连接还是业务都会造成一些心智的负担。
我的设计是这样的:
①首先将 100 万连接分成多个不同的 SET,每个 SET 是一个独立、平行的对象。
每个 SET 只管理几千个连接,如果单个 SET 工作正常,我只需要添加 SET 就能提高系统处理能力。
②其次谨慎地设计了每个 SET 里数据结构的大小,保证每个 SET 的压力不会太大,不会出现消息的堆积。
③再次减少了 gcroutine 的数目,每个连接只使用一个 goroutine,发送消息在一个 SET 里只有一个 gcroutine 负责,这样节省了 100 万个 goroutine。
这样整个系统只需要保留 100 万零几百个 gcroutine 就能完成业务。大量的节省了 CPU 和内存。
系统的工作流程大概是:每个客户端连接成功后,系统会分配一个 goroutine 读取客户端的消息,当消息读取完成,将它转化为消息对象放至在 SET 的接收消息队列,然后返回获取下一个消息。
在 SET 内部,有一个工作 goroutine,它只做非常简单而高效的事情,它做的事情如下。
检查 SET 的接受消息,它会收到 3 类消息:
对于第 1 种消息是这样处理的,从客户端拿到摇红包请求消息,试图从 SET 的红包队列里获取一个红包,如果拿到了就把红包信息返回给客户端,否则构造一个没有摇到的消息,返回给对应的客户端。
对于第 2 种消息,只需简单地从队列里拿走消息,转发给后端的聊天服务队列即可,其他服务会把消息转发出去。
对于第 3 种消息,SET 只需要根据消息里的用户 id,找到 SET 里保留的用户连接对象,发回去就可以了。
对于红包产生服务,它的工作很简单,只需要按照顺序轮流在每个 SET 的红包产生队列里放置红包对象就可以了。
这样可以保证每个 SET 里都是公平的,其次它的工作强度很低,可以保证业务稳定。
参考链接:
https://github.com/xiaojiaqi/10billionhongbaos
实践
实践的过程分为三个阶段:
阶段 1
分别启动服务器端和监控端,然后逐一启动 17 台客户端,让它们建立起 100 万的链接。在服务器端,利用 ss 命令统计出每个客户端和服务器建立了多少连接。
命令如下:
Alias ss2=Ss –ant | grep 1025 | grep EST | awk –F: “{print $8}” | sort | uniq –c’
结果如下:
阶段 2
利用客户端的 HTTP 接口,将所有的客户端 QPS 调整到 3 万,让客户端发出 3W QPS 强度的请求。
运行如下命令:
观察网络监控和监控端反馈,发现 QPS 达到预期数据,网络监控截图:
在服务器端启动一个产生红包的服务,这个服务会以 200 个每秒的速度下发红包,总共 4 万个。
此时观察客户端在监控上的日志,会发现基本上以 200 个每秒的速度获取到红包。
等到所有红包下发完成后,再启动一个发红包的服务,这个服务系统会生成 2 万个红包,每秒也是 200 个,每个红包随机指定 3 位用户,并向这 3 个用户发出消息,客户端会自动来拿红包,最后所有的红包都被拿走。
阶段 3
利用客户端的 HTTP 接口,将所有的客户端 QPS 调整到 6 万,让客户端发出 6W QPS 强度的请求。
如法炮制,在服务器端,启动一个产生红包的服务,这个服务会以 200 个每秒的速度下发红包,总共 4 万个。
此时观察客户端在监控上的日志,会发现基本上以 200 个每秒的速度获取到红包。
等到所有红包下发完成后,再启动一个发红包的服务,这个服务系统会生成 2 万个红包,每秒也是 200 个,每个红包随机指定 3 位用户,并向这 3 个用户发出消息,客户端会自动来拿红包,最后所有的红包都被拿走。
最后,实践完成。
分析数据
在实践过程中,服务器和客户端都将自己内部的计数器记录发往监控端,成为了日志。
我们利用简单 Python 脚本和 gnuplt 绘图工具,将实践的过程可视化,由此来验证运行过程。
第一张是客户端的 QPS 发送数据:
这张图的横坐标是时间,单位是秒,纵坐标是 QPS,表示这时刻所有客户端发送的请求的 QPS。
图的第一区间,几个小的峰值,是 100 万客户端建立连接的, 图的第二区间是 3 万 QPS 区间,我们可以看到数据比较稳定地保持在 3 万这个区间。最后是 6 万 QPS 区间。
但是从整张图可以看到 QPS 不是完美地保持在我们希望的直线上。
这主要是以下几个原因造成的:
①当非常多 goroutine 同时运行的时候,依靠 sleep 定时并不准确,发生了偏移。
我觉得这是 Golang 本身调度导致的。当然如果 CPU 比较强劲,这个现象会消失。
②因为网络的影响,客户端在发起连接时,可能发生延迟,导致在前 1 秒没有完成连接。
③服务器负载较大时,1000M 网络已经出现了丢包现象,可以通过 ifconfig 命令观察到这个现象,所以会有 QPS 的波动。
第二张是服务器处理的 QPS 图:
和客户端相对应,服务器也存在 3 个区间,和客户端的情况很接近。但是我们看到了在大概 22:57 分,系统的处理能力就有一个明显的下降,随后又提高的尖状,这说明代码还需要优化。
整体观察可以发现,在 3 万 QPS 区间,服务器的 QPS 比较稳定,在 6 万 QSP 时候,服务器的处理就不稳定了。我相信这和我的代码有关,如果继续优化的话,还应该能有更好的效果。
将两张图合并起来:
基本是吻合的,这也证明系统是符合预期设计的。
这是红包生成数量的状态变化图:
非常稳定。
这是客户端每秒获取的摇红包状态:
可以发现 3 万 QPS 区间,客户端每秒获取的红包数基本在 200 左右,在 6 万 QPS 的时候,以及出现剧烈的抖动,不能保证在 200 这个数值了。
我觉得主要是 6 万 QPS 时候,网络的抖动加剧了,造成了红包数目也在抖动。
最后是 Golang 自带的 pprof 信息,其中有 GC 时间超过了 10ms, 考虑到这是一个 7 年前的硬件,而且非独占模式,所以还是可以接受。
总结
按照设计目标,我们模拟和设计了一个支持 100 万用户,并且每秒至少可以支持 3 万 QPS,最多 6 万 QPS 的系统,简单模拟了微信的摇红包和发红包的过程,可以说达到了预期的目的。
如果 600 台主机每台主机可以支持 6 万 QPS,只需要 7 分钟就可以完成 100 亿次摇红包请求。
虽然这个原型简单地完成了预设的业务,但是它和真正的服务会有哪些差别呢?
我罗列了一下:
参考资料:
https://github.com/xiaojiaqi/C1000kPracticeGuide
https://github.com/xiaojiaqi/fakewechat/wiki/Stress-Testing-in-the-Cloud
https://github.com/xiaojiaqi/fakewechat/wiki/Design
http://techblog.cloudperf.net/2016/05/2-million-packets-per-second-on-public.html
http://huoding.com/2013/10/30/296
https://gobyexample.com/non-blocking-channel-operations
作者:xiaojiaqi
来源:Github
读:本文整理自高可用架构与数列科技联合举办的技术沙龙,数列科技资深架构师徐汉彬的主题演讲。围绕“峰值流量下的高并发实践”,主要介绍了其在腾讯QQ会员活动平台的高可用架构实践。以下为演讲摘录。
今天分享的主题的是《面向大规模流量活动的高可用架构实践》,在开始之前先做个简单的自我介绍,我叫徐汉彬,在进入数列科技之前负责过QQ会员活动运营平台,把这个平台从日PV百万级别做到10亿级别,在应对大流量活动这一块积累了一定的经验,今天就这个主题方向跟大家做一个探讨。
分享的内容主要分为三个部分:
1.大流量活动的系统扩容评估方法
2.系统高可用架构设计实践
3.大规模流量活动的实践案例
大流量活动有多种形式,除了我们常见的电商大促(双11、618等),近几年还兴起了一种新形式——直播卖货。一个知名主播在比较短的时间里,引导粉丝大量下单,这是一种典型的大流量场景,对系统的稳定性发出较高挑战。
另外一种比较常见的活动形式是营销活动,例如春节红包、周年庆。
活动的流量来源,包括内部资源、外部付费购买的广告资源和第三方合作导流。公司在活动上投入了大量的资金,参与用户众多,如果活动中途出现问题,不仅对产品口碑的影响非常负面,而且会有金钱损失,还涉及到与第三方合作失败的问题。
举个例子,假设你的活动跟春晚合作,春晚到了某个环节让大家拿起手机现场扫码,这时系统挂了,扫码失败,这种情形就非常尴尬。遇到这种情况,第一个找你的可能不是你的领导,而是外部的第三方合作商,由此可见,关键时刻的系统高可用有多重要。
大流量活动面临的挑战主要分为三个部分。
第一个挑战是流量评估难,扩容的量级并不是张口就来,如果你跟运维说要扩充10倍容量,他一定会反问你为什么,你要拿出扩容的合理依据。
第二个挑战是架构扩容难,即使我们评估出了比较准确的流量峰值,又该怎么进行系统扩容呢?现代IT系统架构的复杂度越来越高,尤其是现在流行的微服务架构,它的节点数越来越多,服务之间的调用关系非常复杂,链路的梳理本身也是一大难点。
第三个挑战是怎么进行高可用实施。我们把流量评估和链路梳理扩容都做好了,活动在大流量到来的那天就没有问题了吗?当然不是,所以第三个问题就是怎么进行高可用实施。
想要解决上述挑战,绕不开业务和系统的双重复杂度问题。
微服务架构的复杂性,加之业务的复杂性,使得整个系统错综复杂、难以被人类理解。即使是公司的架构师、业务研发同学也很难讲清楚系统整个链路的每一个细节和服务之间的调用关系,因为此时的系统已经是一张庞大又相互交织的的网络了。
要解决流量评估的问题就得进行精细的链路梳理,梳理的第一步就是画架构简图,把每个架构大的模块画出来,再根据架构简图进行业务功能链路拆解。
部分链路
链路图梳理完成后,我们就可以开始预估扩容量了,这里涉及到三个重要的指标:推广量、环节转化率、单UV的请求总数。
第一个指标推广量,一般情况下会以每秒广告的曝光量计算。将不同广告渠道的曝光量加起来就能得到预估的推广量级了。
还有一种方式是计算APP应用高峰每秒用户的登录数,这个数值约等于推广的每秒曝光量。
一般预测的每秒推广量都在系统现有容量的10倍以上,按这个推广量去扩容,系统基本没有问题,但会它会造成比较严重的资源浪费。
这时则需要用第二个参数来辅佐我们进行更细致的评估,它叫做环节转化率。以红包活动为例,用户看见红包活动,但不一定会点击进入页面,进入页面也不一定会领取红包,每一个环节都有环节转化率。
预估环节转化率一般有两种方法,一种是依据过往的经验数据进行估算;另一种就是提前演习,提前给部分用户推送活动,快速准确地收集到每一个环节转化率,有条件的公司一般会采用这种方式。
还有一个参数是我们需要特别注意的,就是单UV的请求总数,为什么要特别关注呢?
因为用户进入一个活动页面,他可能会查询个人信息、查看活动记录,通常不止一个请求动作,所以你在计算后端压力时不能只算用户进入活动的每秒峰值,还要算上其他请求动作。假设用户平均有4个请求动作,那你的流量就要乘以4,它有一个放大效应。
通过前面3个指标我们就能计算出后端会承受多少流量压力,进而得出扩容的预估值。最后把扩容容量设置为预估值的3倍,这个3倍并不是凭空臆想,而是从过往大量的活动扩容经验中总结得来的规律,活动当天的峰值通常是常规均值的3倍。
具体怎么计算咱们来举个例子,假设我们是100/S的曝光量,只有60%用户进入了领取页面,这其中又只有50%点击了领取按钮,那后端收到的请求是30/S,根据单UV的请求总数来说,整个后端最少要支撑120/S的压力,加上3倍原则那么后端最终的扩容也就是360/S。领取页面的流量峰值则为180/S,这时你带着数据去找运维扩容就有理有据了。
某活动容量评估得到结果是9.6W/S,根据三倍原则,整个业务链路要扩容到30W/S,但是,在实操扩容过程中会发现部分应用很难扩容。举个例子,像Web server这种很容易做平行扩容,只要机器足够就可以扩容上去,但有些接口日常也就2000-3000/S的QPS,要扩到10万QPS基本就是不可能的,也没有那么多的资源和精力。这就涉及到扩容的具体实践了,也是我们接下来要说的系统高可用架构设计的实践内容。
通常来说,我们系统高可用架构实践有三大扩容要素:全链路QPS、机器带宽、存储大小。
全链路QPS最容易被大家理解,我们也最关注,就不做过多的展开。
机器带宽问题,流量越大越容易遇到。假设CGI请求达到10W/S,通常它的请求存储不是一次,当时我们的常规业务请求存储高达7-8次,包括查询活动配置、查询用户参与记录、查询其他关联信息等。这个10W/S就意味存储端需要承受大几十万每秒甚至百万每秒的量,如果一个存储占1KB或者大几百KB,在这个量级下存储数据就相当庞大了,使用百兆级别网卡显然就会遇到网络带宽瓶颈问题。
接下来说说存储大小,这里说的存储大小通常不是指硬盘的存储大小,而是指内存,它也比较容易遇到瓶颈。大多数公司有使用Redis类的Key-value存储,也有部分公司使用自研的Key-value存储,通常写入的数据会先写入内存,再通过定时淘汰机制,同步到本地的SSD或者磁盘。在大流量场景下,内存很容易被写满,如果没有事前评估,活动当天几百G的内存会瞬间被写满。
还有一个不得不提的内容就是静态资源,它是我们网页请求的图片、JavaScript和CSS样式,通常它的瓶颈不在系统本身。一般情况下,如果不考虑带宽的限制,在一台配置很普通的机器上搭建一个Nginx来压测静态资源的请求性能,可以轻松达到数千QPS。但是,如果考虑到静态资源的大小,加上单个用户打开一个页面就会请求很多静态资源的实际情况,请求的静态资源的大小很较容易就超过1M了。这时第一个撑不住的就是机器的出口带宽,而不是静态资源服务器本身的性能。
针对静态资源问题,我们有常用的应对方法——离线包推送机制。在活动开始前几天就把静态资源推送到活跃用户的的手机里,这样活动当天九成以上的流量都是本地的,他根本没有发起网络请求,以此来解决CDN的请求压力,解决带宽问题。
完成扩容只能说在理论上没问题,接下来说说高可用架构建设的关键要点。概括起来就是几个点:过载保护、柔性可用、容灾建设、轻重分离、监控体系、数据对账。
监控体系很重要,我们需要探知这个系统处于什么状态,并且出现问题时需要一些方案去应对它。
前面的分享提到过一个问题,有些接口日常也就2000-3000/S的量,没有那么多的资源和精力扩到10万/s, 那怎么办呢?
关于系统链路架构优化,我们常用的方式有三种,第一种是异步化,这个好理解,暂时没有这个能力执行完,就放到消息队列里慢慢消化。第二种是内存级的缓存,把需要访问的数据提前放到内存级的Cache里。第三种是服务降级,这个比较常用,就不做过多介绍了。通过这些方法就可以把链路的性能提升起来。
关于过载保护它的的核心目标是部分不可用至少比彻底不可重要强,主要的实现手段是进行分层流量控制。这些层级包含推广层、前端层、CGI层和后端服务层。针对推广层,只能在最坏的情况使用,因为它要对广告进行下架处理,不到万不得已,公司也不愿意采用这个方式,它也会影响活动的业务效果。针对前端层,可以实现随机弹出倒计时,限制用户1分钟内不能发起新的网络请求,有助于削平流量峰值。其他流量控制层的实现大同小异,不做过多的展开。
关于部署,我们应该把重要的核心的一些操作给保护起来,例如,在上述案例中,比较重要的是发货,它不应该被其他操作影响。如果查询操作不可用,用户再刷新一次页面就好了,但如果发货不到账,用户会直接投诉,所以上述案例就把发货操作拆出来独立部署了一套异步发货集群。
柔性可用我们应该怎么实现呢?
一般有两个方向,第一种是设置超短的超时时间,例如,给安全接口设置超时时间为30毫秒,假设那天安全接口真的挂了,30毫秒对于一个百毫秒级别的请求来说,用户也不太能感知到,活动的体验还是好的。另外一种,就是直接不等网络回包的方式,例如UDP服务。
在容灾建设中,我们要大胆提出假设,假设各个核心的服务和存储都可能挂掉,根据假设去制定对应的容灾和解决方案。比如应对机房停电、网络故障,我们可以做跨机房跨网络部署,这样即使电信光纤被挖断,服务还能保持基本正常。另外要做好应急预案,把所有关键节点故障的假设对应的处理方案全部做成开关模式,避免在活动当天还要去跑日志和写处理脚本。
针对监控与对账,我们必须建立多维度的监控体系,在流量峰值的压力下部分监控可能会出现问题,多维度的监控能帮助我们探知系统的真实状态,有助于我们采取正确的应对措施。
关于对账能力,假如发货失败了,当天值班的同学需要看跑线上日志和写补发脚本,那么半个小时、一个小时就过去了。值班同学通常都比较忙,所以最好的方式就是提开发好,当天如果发现问题,它就能自动去检测失败的日志并且进行补发。
前面讲了比较多关于大流量活动的架构准备工作,这一部分我们讲讲具体的实践案例。
第一个案例是某年某业务的春节红包活动,尽管前期做了非常度多的准备,活动上线时还是出现了一系列问题,但好在都在我们的预案之内,算是有惊无险。
事后我们也进行了反思回顾,出现那么多问题是为什么?首先就是没有遵循3倍扩容原则,再比如说链路梳理没有到位,下面就是我们的一些总结内容。
根据我们的过往经验,最危险的活动反而不是大型活动,因为为了确保大活动的顺利开展,公司会抽调很多骨干参与进来,即使出现问题通常也是小问题。而中小型活动的流量不会太大,没有什么威胁。最容易出问题的恰恰是那些中大型活动,接下来详细讲讲另一个中大型活动案例。
在某游戏的年度活动项目中,我们做了一些评估和准备工作,但不可能对待每个活动都像对待春节红包活动那样。当时我们派了2个人看了一下,各个线上模块团队负责压测各自的模块,都反馈没问题,活动就上线了。活动当天凌晨我被电话叫醒,系统出问题了,当时有很多用户已经无法参加活动了。
当时的Web系统是基于PHP和Apache,采用Apache的多进程模式(perfork)。一个后端服务响应时间一般在几十毫秒,一个worker进程1秒钟应该可以处理十多个请求,但到了高峰时期,在大流量的压力下,后端服务的响应时间从几十毫秒飙到了几百毫秒甚至是1秒。这个时候1个wrker进程1秒钟只能处理1个请求,无法及时处理最终导致请求堆积。我们趁着玩家在凌晨的休息时间去做了不少补救工作,包括降级及其他的动作,经过一个通宵的努力,用户可以正常进入活动了,但还没有完全解决。第二天下午我们又到公司继续,48小时连轴转重新发版后终于解决了问题,安稳度过了那次活动危机。这种大中型的活动最容易出问题,因为通常我们不会给与足够的关注度。
总结一下大流量活动前期需要做的一些总体的经验和流程,首先是相对合理的评估&梳理方案,再进行架构上的优化和调整,最后就是整理紧急预案。
我连续参加过三年春节红包活动活动,每一年都提前大概一个多月召集核心骨干来出具方案,每年都做很多准备,可每年都有一些小问题。
反思为什么投入大量人力物力资源,系统还是出问题?
究其本质,我觉得主要是三个方面:第一很多时候测试环境、甚至性能环境无法代表真实的生产环境;第二,各个局部高可用不代表整体高可用;第三是系统的成长性,复杂的业务系统在持续迭代、膨胀,今天没性能问题,不代表明天没问题。
想让生产环境的性能获得保证,不出问题,从这个点出发我们有一个明确的探索方向——常态化的生产环境性能测试。
大量的准备工作都是为了保证线上环境能够达到一定的性能指标,所以最好的方式就是直接在生产环境去做最真实的性能测试。比如选在凌晨两三点钟没有什么业务流量的时候执行性能测试,看系统能不能达到我的目标性能。
那想要真正做到在生产环境实施性能压测有哪些关键点呢?
主要有三点,测试流量识别、测试流量标识的传递以及最重要的测试流量隔离。做生产环境压测避免不了涉及一些写入请求,如果把大量虚假的数据写入生产环境数据库肯定不合适,后续还要去做数据清理。所以只要前面提到的三个关键点能够解决,在线性能测试就能实现。
这是我们基于JAVA做的一套性能测试平台,因为我们可以在JAVA有中间字节码这一层做增强,通过agent探针在不侵入用户业务代码情况下去做一些控制。正式流量保持不变,我们会对压测的流量做一些控制。举个例子,比如说系统有一个mysql数据库,我们就会在线上建一套影子数据库,跟原来数据库一样,只是数据可能少一点或是空的(只有表结构)。当有流量进来时agent就会进行识别,识别出压测流量时,agent会把连接的数据库替换成影子数据库。无论是消息队列还是Cache存储都可以用类似的方式来实现。
另外我们还做了一个东西叫挡板,它是干嘛的呢?假设有个第三方的短信接口,业务流量去调用这个接口是可以的,但测试流量直接去调用肯定是不行的,因为第三方不可能配合你做一个影子发短信的系统。挡板的作用就是通过agent来实现一个mock,在调用第三方接口时直接返回,防止测试流量调用第三方接口时对生产数据产生影响。
这是数列的生产环境全链路性能测试的方案,在此基础上我们还研发了链路自动梳理的功能。对于复杂业务以及复杂系统,它内含很多个微服务节点和业务节点,没有人能完全搞清楚整个链路的所有的环节。我们可以通过agent探针,利用技术手段搞清系统链路流向,协助进行链路梳理,与业务相结合就能梳理出业务调用的链路。结合E2E巡检平台不仅能够知道这条链路的性能如何,还能定位到具体环节的具体性能瓶颈,方便及时准确地进行性能调优,梳理业务链路视图,最终实现系统的高可用目标。
*请认真填写需求信息,我们会在24小时内与您取得联系。