我只想做好一件白衬衫 -- 小米推送服务监控手记

最近读陈年先生的文章"凑热闹的公司都会烟消云散",读了十几遍,意犹未尽,感慨颇深。

我来小米三年了,三年前我会滔滔不绝的跟别人讲,如何带领几十个人,建立一套多么完善的质量保证体系,如何用制度让所有人都遵守软件开发的流程和秩序,等等云云;还要告诉大家,某某大公司都是这样干的,某某外企比这个干的还大,借以佐证我的思想是何等的正确和伟大。

现在想想,那时的我,SB!

2014年,我很平静的度过了,做了一年多的推送服务,写年终总结的时候,恰逢读到陈年先生的那篇文章,于是我想我一年做了这么多事情,有哪件事情可以拿出来炫耀,就像那件白衬衣呢?

于是我把所有做过的事情都列出来,然后一个一个划掉,这个事情做得太糙,这个事情做的太乱,这个,嗯,很一般;当你划掉几十件事情的时候,你的心就凉了,拔凉拔凉的;陈年先生在半层楼里放了所有的产品,却没有一个可以拿出手给雷总看的时候,也许就是这种感觉吧。

想了几天之后,我终于想到一件小事情,也许这件事情太平凡了,以至于成为了不过大脑的生活习惯;直到昨天跟某两个互联网大公司的服务器工程师吹牛的时候,我才发现,当我把这个牛吹完的时候,他们看我的眼神中似乎有了一丝异样的光芒。

我们花了一年多的时间只做了一套服务的监控,大的改版超过了10次,N多次的代码重构,推倒重写,各种尝试,各种跳坑,解决各种瓶颈,看各种密密麻麻的log,分析各种情况,处理各种异常,等等云云

其实监控原理很简单,在测试机上跑一组case,调一下线上服务的api,判断一下服务返回的结果对不对,对了就pass,错了就报警,就这么简单,没什么难的。但是我们前前后后做了一年多。。。直到今天,改动还在继续。

1.最初的方案是这样的,E2E的测试,用一个手机接到测试机器上,然后用脚本定时驱动安卓程序,向手机里安装一个推送客户端sdk demo,然后跑android的case,给客户端发消息,看客户端是否能收到,如果收到就从手机里读出来判断正确与否。这个代码很快就写好了,测试通过,嗯不错,开始跑吧。跑了一个晚上就傻眼了,由于手机通过wifi连接网络,各种网络不稳定所导致的误报,直接让报警不断,失去了报警的意义。怎么办?换一套环境

2.既然wifi环境不好,那就直接在网络接口接一个路由器,这个路由器只提供这一台手机的网络连接,这个总该稳定了吧。跑了两个晚上,嗯,误报是少点,但是总误报数量占的比例还是很大,报警搞得大家都很紧张,怎么办?再换一套方案。

3.使用android虚拟机,这个东西直接跑到测试机器上,完全不需要wifi,这总可以了吧?实践了几天,哭了,一个是虚拟机内存占用之恐怖,连续跑几天你试一试,另外性能也有问题,读取服务器的返回值是很慢的,需要长时间的sleep,最后就是不稳定,各种不稳定。

4.取交集,手机跑case网络是瓶颈,模拟器跑case稳定是瓶颈,能不能两个一起跑,如果同一条case都fail,才报警,只有一个fail,不报警。这个方案不错吧,取了一个交集;真到写代码的时候就完蛋了,两个监控一个跑的快,一个跑的慢,你还得写一个控制程序去定期分析两边的log,乱的一塌糊涂。

抛弃android吧,我们监控的是服务,干嘛要带上客户端,尽管E2E的监控更让人感觉靠谱吧,但是这不是最根本的东西

5.直接连服务器,客户端的原理是通过push demo调用push client sdk,client sdk最终是需要调用smack包来完成xmpp消息传输的;服务端工程师做E2E测试的时候,会通过一个中间层直接调用smack连接服务器;ok有方案了,把服务端工程师用到的中间层改改,然后套用客户端smack,再模拟客户端发出的请求,最上层接上test case,就应该能工作了;不久,这个移花接木的东西开始跑了,效果还不错,明显误报少了很多,很好,把前面那些不靠谱的监控全都干掉,把这货换上,然后张灯结彩,准备喝庆功酒,但是跑了几周,问题来了,长连接不像短连接,不成功就retry,长连接一旦断了,重新bind是有问题的,并且如何检测连接是否断掉呢?

6.最初的怀疑是smack不稳定,因为看到了smack的call stack,问题应该出在smack上,smack是第三方类库,用于xmpp的连接,但是我们使用的xmpp不是标准的xmpp协议,是经过我们改造过的xmpp,smack于是也被改造过了;查了一下maven库,上面有好几个smack的版本,换个别的用用,问问消息组的同事,各种尝试之后的结论是,这不是版本问题,别的版本不支持push服务,怎么办?改造smack吧

7.先找到smack的源代码,然后各种看,各种debug,然后整理了一下smack的行为规律:a.如果网络断了,smack发消息前,自己会检测到网络断了,然后发一个<present>强制断开网络连接;b.如果客户端等待收服务的消息,那就会超时,smack感知不到网络断开了。中间层是没法对重新bind做处理的;那就只能改smack,在收发消息的时候,先检查网络情况,如果断了就重新bind,代码改完了,找android的大牛军哥去看,没出5分钟就被拍回来了,这种改动会影响到连接的状态,这个太底层,最好别动。。。这次尝试又失败了,默默的在中间层加了一些重新bind的处理逻辑,效果也不是很好

8.重新回到原点,重新一个一个log去分析,慢慢的会发现,网络不稳定是一回事;中间层的不稳定,开始慢慢的浮出水面,中间层有大约20多个package,代码里有各种继承各种重写,很多静态的变量你如果不debug,根本都不知道哪里改变的,有时候改变一点点东西,上层的case就跑不起来。怎么办?凉拌,重写吧,按照自己的需求。这个花掉了几周时间,在某一个后半夜,所有case都可以在重写的中间层上跑起来了,那一刻根本没有什么兴奋,只想回家睡觉。重写后的只有2个package,大约7-8个文件,是的,上层的case其实用到的就这点。试着跑了几周,这个世界清净了,监控明显稳定多了,但是新的瓶颈又出现了。

9.中间层稳定了,就发现上层的case写的好挫,各种不靠谱,重写吧。。。又是几周,靠谱点了。

10.又遇到问题了,一次我们看监控很正常,但是某一个开发者说他们的app收不到push了。这次事故调查的结论是服务端对这个app的配置有问题。这次事故导致的是我们不再用单一的测试账号跑case,改用各个app的账号跑case,建立新的appinfo的列表,然后一个app一个app的跑。

11.又遇到问题了,当时我们有100左右的xmq,我们遇到了这样一个问题,由于当时的升级技术问题,导致了某次升级之后,有两个xmq的服务有问题,但是监控是随机落到各个xmq上,当时在很长的时间里并没有报警;这是一次事故,怎么让以后不出现这个问题呢?我们做了paritition监控,让每次的case都只落到一个xmq上,轮询所有的xmq;上线,跑了几个月,确实也发现了一些问题。

12.随着xmq的数量越来越多,轮询的时间越来越长,新的问题就产生了,如何快速知道某个xmq有问题了呢?我们考虑了多线程处理,两个方案,一个是自己写多线程的代码,另一个是使用多线程run case的工具;两个方案都做了几周,遇到了很多问题,最主要的是这是长连接,sleep会对所有线程有影响,如果某一条等消息时间过长,也会导致其它线程的case挂掉,这是跟短连接所不一样的;另一个是log如何处理,多线程的工具会把所有log打到一起,包括call stack,出了问题分析起来非常困难;最后就是稳定性,多线程受到网络的影响更重;最终我们没有采取多线程的方案。

13.case的区分度,多线程不行了,那就让case跑的更快,那么就可以更快的遍历所有的xmq;于是新的方案就产生了,首先分为p0,p1,p2的级别,p0白天跑,是用户最常用的功能,先保证这些功能不挂,p1晚上跑,这些是用户不是太常用的功能,晚点发现问题影响度相对小些,p2是剩下所有case,由于全跑下来时间太长,就几个小时跑一遍。另外一个维度是partition的监控按照xmq的顺序遍历,app的case随机落到xmq上,用以区分。

14.再次出现问题,用户看推送的统计报表的时候反应,我们昨天没有发topic消息,为什么报表显示有topic呢?查了一下,那是监控账号发的信息。啊,这次从监控上搞不定了。求助了服务器的开发,他们给监控提供了Extra字段,如果设置成test字段,统计报表就会过滤掉测试的消息数据,避免了用户的抱怨。

15.以前的xmq是用erlang语言写的,后来想换成了java语言,由于影响很重,大家都很谨慎;我们尝试了把xmq下发包中每一个字段都检查一遍,这时监控的问题就看出来了,以前只检查了一些关键的字段,没有全都检查;所以case都pass了,但是xmq下发的包,用户使用的时候,还是有问题的,因为你搞不清用户到底会用哪个字段,于是在灰度升级中就发现了测试的漏洞,前前后后折腾了好久,xmq下发的包一层包一层,拆了好几天。最后java xmq都上完线了,case中的各种检查也都加上了,xmq发出来的包结构也搞清楚了。

16.log的处理,报警邮件发出来,需要快速的定位,log的结构是否清晰,关键内容都显示,不重要的内容都删去,说起来容易,做起来不简单。三个人定义了log的格式标准,然后分分case,改吧,这个又改了一阵子

17.sd的机房满了,没有地方增加新的机器,服务端又没有多机房的方案,这时候消息会有各种延迟,监控一直在报警;开发很着急,硬件没有了,就只能改软件代码,让服务性能更好,于是引入一些bug,监控又报警;那段日子相当痛苦,我们唯一能做的就是增加sleep时间,关闭一些验证,只对重要字段验证,有些api没有返回包,都不在check。后来多机房方案出来了,迁移服务到lg,监控再连lg的服务,再报警,再处理,这个反复折腾了几周才搞定。

18.迁移到了lg,网络发生了变化,新的问题又产生了,大量网络问题导致的fail又卷土重来,这次我们放弃了五彩城机房的监控机器,在zc申请了新的监控机器,运维的兄弟在底层网络做了处理,让zc连lg接近于在lg直连,跑了一阵子,效果不错

19.随着case越来越多,监控种类越来越多,如何定时启动这些监控是个问题,最初是crontab,这个方法简单易行,但是服务挂掉你也不知道;后来使用了jenkins,这个东西麻烦的地方在于部署和自己没有办法发出报警邮件,也不能对历史的数据进行分析,而这些是我们需要的;权衡再三,我们的监控系统需要一个控制服务,这个服务应该定时run不同的监控,收集log,存数据库,发报警邮件和米聊,定期做数据分析,监控运行的过程中出了异常,应该有报警。立元断断续续的花了近2个月,在工作的间隙和业余时间写了这个控制服务,现在每天早晨会有头一天的几份数据分析报告发出来,根据这些统计数据,还是能看出服务的一些问题的。

20.经历了上面种种改造,现在监控已经逐步稳定下来了,服务的功能问题会很快的报出来,现在最大的问题还是网络问题,最近的一次定位有2点,a.可能是zc到lg的网络问题,b.FE-GW的前端可能有些问题。于是我们又增加了bind监控,遍历连接所有的xmq。对监控的改造还在继续。。。

上面只是举一些例子,事实上,遇到的问题要比这些多的多。

监控的敏感性和误报率是一组天生的矛盾,敏感性越高,误报率也越高;敏感性越低,误报率也越低;我们需要找到其中的平衡点,这才是最难的地方。

如果你问我现在的推送监控怎么样了,我不敢说它做的有多好,只是我晚上能安心的睡觉了。

最后我想说一下做监控这件事情的感受,

1.监控不是一个人的事情,这个工程关联很多团队,可能需要客户端开发,服务器开发,运维工程师和测试工程师,甚至其它团队共同协作才能找到问题的根源,才能解决很多问题。就像每一个团队就是一组齿轮,大家都把自己的那部分打磨好了,放到一起才能协同转动,最终拼接成一个精确的瑞士钟表。

2.科学界的一个不成文的定论是,基础研究聪明人是做不来的,只有天性笨拙一点的人,坚持每天做下去,做了20年30年,最终才能证明某些东西。监控是很基础的东西,不可能一蹴而就,今天晚上打冲锋,明天早晨就能实现共产主义;真的需要一些人踏下心来,认认真真的做上一年两年,也许才能做出点什么。

3.做监控是件小事情,做好监控是件大事情;大小取决于你看事物的颗粒度,看得越细致,事情就越多,做的事情就越大;看的越粗糙,事情就越小,做的事情就越小。这世界上没有什么高大上的东西,只是别人踩过的坑比你多了几个数量级,于是人家就形成了技术壁垒,这是你抄不来的,只有自己走一遍,一次次的从坑里爬出来,才会感受深刻。

4.面试中,我们经常看到面试人说自己在很短时间内,做了多少多少事情;却很少见到有人说,这些年我只做了一件事情。我想起了小野二郎,米其林三星大厨,今年90岁了,据说捏了近60年的寿司,被世人称之为寿司之神,米其林指南对他捏的寿司评价是:值得花一辈子排队等待的美味。人家花一生做一件事情,我们花一年做一件事情好不好?然后给面试官讲讲这件事情的细节,看看他的反应,嗯,应该很有意思。

今年是2015年了,我也在想今年做点什么小事?如果你想做一件很小的事情,我们可以聊一聊;如果你想做天大的事情,哥,我智商低,比我脑袋大的天,我想不明白。我只想做好一件白衬衫。?

时间: 2024-10-17 09:13:10

我只想做好一件白衬衫 -- 小米推送服务监控手记的相关文章

Android端小米推送Demo解析和实现方法

前言 最近这几个月都是在准备找工作和找工作中,付出了很多,总算是有点收获,所以都没有怎么整理笔记.到了最近才有空把自己的笔记整理一下发上来,分享一下我的学习经验. 推送 由于最近项目要用到Android的消息推送,关于Android推送的解决方案有很多种,有C2DM,轮询, SMS,MQTT协议,XMPP协议和第三方平台,经过我们对项目需求的考虑之后我们选择了第三方平台推送的小米推送,下面就是小米推送的实现方法. 实现准备 想要用小米推送首先要去小米开发者平台注册申请开发者账号,经过1到3天的审

小米海量数据推送服务技术的功能实现讲解

小米海量数据推送服务技术的功能实现讲解 11.11大促之后,随着移动端业务量的急剧提升,像小米推送这样的基础服务也经受了巨大的考验.11月12日,小米的项目总监汪轩然在微博上宣布,"小米推送服务共发出9.65亿条消息,平均每分钟发送67万条.更值得一提的是,后台监控显示,推送服务后台系统在全天运作非常平稳,没有任何卡顿拥堵现象,让各种促销.返利.订单更新消息第一时间触达用户." 汪轩然,2007年毕业于清华大学计算机系,后加入微软亚洲工程院,曾参与WP7上的浏览器的开发.2010年7月

Android消息推送:手把手教你集成小米推送

前言 在Android开发中,消息推送功能的使用非常常见. 为了降低开发成本,使用第三方推送是现今较为流行的解决方案. 今天,我将手把手教大家如何在你的应用里集成小米推送 该文档基于小米推送官方Demo,并给出简易推送Demo 看该文档前,请先阅读我写的另外两篇文章: 史上最全解析Android消息推送解决方案 Android推送:第三方消息推送平台详细解析 目录 1. 官方Demo解析 首先,我们先对小米官方的推送Demo进行解析. 请先到官网下载官方Demo和SDK说明文档 1.1 Demo

李想:赌上全部身家第三次创业,只想做好电动车

[博客园]由于第三次创业实在太需要钱了,于是我停掉了所有的投资,包含股票投资.天使投资等,全部押注和投资我们自己.今后创业者就别再给我发商业计划书了,我既没钱,也没精力干别的事情了,就不浪费大家的时间了.”——汽车之家创始人 李想 组建电动车团队的理念 今年,我(汽车之家)和老对手李斌(易车)共同参与创办了两家电动车企业:蔚来汽车.车和家.李斌主导蔚来汽车,打造提供高品质产品和服务的电动车品牌,以目前已有的产品来看,与TESLA较为接近.我来主导车和家,打造小而美的电动交通工具,市面上尚无可参考

使用PopupWin控件实现消息推送功能

最近项目需要,急需实现消息推送功能,陆陆续续的也试用了好多办法,比如用JavaScript来实现啊,效果都不咋好,最后找了PopupWin这个,看着效果都还不错,就开始使用了. 1.准备工作,先去网上下载"EeekSoft.Web.PopupWin.dll".放到你项目根目录下面,添加引用. 2.在前台页面添加 <%@ Register TagPrefix="cc1" Namespace="EeekSoft.Web" Assembly=&q

调用小米推送api时报证书签名无效

Feb 20, 2017 4:10:07 PM com.xiaomi.xmpush.server.Sender sendMessageWARNING: IOException posting to XmPushjavax.net.ssl.SSLException: Server key at sun.security.ssl.Handshaker.throwSSLException(Handshaker.java:1274) at sun.security.ssl.ClientHandshake

python - 小米推送使用

1. 小米文档及SDK下载 1.文档介绍 https://dev.mi.com/console/doc/detail?pId=863 sdk说明: 2.开发者需要登录开发者网站(申请AppID, AppKey, AppSecret). 3.访问开发者网站下载SDK. 地址:http://admin.xmpush.xiaomi.com/zh_CN/mipush/downpage 4. 创建应用 http://admin.xmpush.xiaomi.com/zh_CN/app/nav 2.业务场景

从推送看小米的野心

推送是服务端主动给手机端发送消息,现在基本上每个商业级别的应用都会用到推送.苹果在推送这方面算是做得最棒的,所有的推送都通过苹果服务器,从而让手机端变得更加省电.小米推送也跟苹果类似,所有推送都会通过小米来推送,而且即使app退出,也可以收到推送. 从技术上来讲,推送固然可以采用开源的OpenFire+Asmack,当然也可以在服务中开启Socket链接来实现.但现实远非想想的那么顺利. 就拿miui来说,miui从底层对app自动重启做了优化,只要应用被一键清理后,就再也不会偷偷的自动重启了,

只想把技术做好,维持一份可观的收入,就精专一门;有创业想法,就全栈

做全栈开发(前端和后端)好还是全端开发(前端和Android应用开发)好?哪个前景和钱景发现比较好,对以后的发展! 1. 有创业想法,就全栈.只想把技术做好,维持一份可观的收入,就精专一门 2. 全栈对自己的优势不大吗?好多公司都不认同,特别是HR,普遍的观点是,会的多,就很难专精. 3. 大公司是一个靠分工增加工作效率的机构,无论你全栈,还是全端,对公司来说都只用你的一部分技能.但是薪资可是要比一般的人高一些,所以很多HR都忽悠你说全会的就没法专精.先全栈,后全端.别信那些HR忽悠. 4. 有