对于每一个客户的问题,不管大小,都需要跟进追踪到底,以获得最佳的答案。

一个问题一个坑,留了坑,前路必将荆棘丛生;填了坑,前路即是坦途。这是神策人的做事态度和行事准则,也帮助我树立了积极的人生观。

如果同行也正在经受类似问题的困扰,希望同行可以通过这篇文章,在排查过程中能够获得一点启发。

刷量?客户反馈异常 IP 发送大量重复数据

从今年 2 月份起,我陆续收到客户反馈:Web JS SDK 短时间内上报了大量重复的数据到神策分析,从而影响了客户的分析、决策和制定运营计划。对于这种情况我们通常称之为 “刷量”。什么是刷量?

图 1 刷量表现—按天

图 2 刷量表现—按分钟

用户所反馈的现象和刷量一致,有几个异常 IP 短时间内密集发送 Web 端重复数据入库。一个 IP 一天发送的重复数据甚至达到了几十万、上百万条,这显然不是一个正常用户产生的行为数据。

我们查看了刷量时的用户行为序列,如下图,可以看到事件是重复循环触发的,时间间隔在几十毫秒。 

图 3 刷量发生时的用户行为序列

针对此问题的反馈,我们进行了快速排查及提供初步解决方案。 当时的排查思路:

一,会不会是客户代码 bug 导致重复触发事件?

通过协调运维帮忙查询事件日志,证明这些重复事件的 trackid(Web JS SDK 对发送数据生成的随机数,每条采集和发送的数据都会有自己独特的 trackid) 是一样的。从这个方面看,基本排除了是客户代码 bug 导致的,因为即使是代码重复触发的事件,trackid 是不会重复的。

二,会不会是别人恶意获取了神策的数据采集请求和数据体,使用工具或者脚本伪造请求,灌注脏数据到神策分析服务器?

Web JS SDK 采集的数据,默认使用 image 方式发送数据,GET 请求的数据接收地址和数据体都包含在请求的 URL 中,如图所示:

图 4 Web JS SDK 的数据发送

只要复制该 Request URL 直接在浏览器地址栏访问,或者使用脚本访问,就会有一条一模一样的数据入库。这也符合 trackid 重复的情况,而且可以集中产生大量的请求,实现灌注脏数据。在本地使用脚本模拟,也能够复现出来数据刷量的情况。

因此,推测的结论是:有人从集成了 Web JS SDK 的页面上,截取了发送的数据请求,并通过脚本灌注脏数据进入神策分析。

根据这一结论,给客户的方案是:将 Web JS SDK 的数据发送方式从 image 改成 ajax,这样请求就会从 GET 变成 POST,在一定程度上避免将整个请求暴露在 URL 上;将出现过刷量的 IP 增加到后端的防火墙黑名单中。

问题又现!存疑,再深入排查

但是,似乎并没有解决问题。在接下来的一个月,依旧陆续收到刷量的情况反馈。

我每天值班也都胆战心惊,只要有客户反馈刷量的情况,心里都咯噔一下:如果是有人恶意刷量,那么持续刷的动作有点说不通,是否有其他原因导致……问号一直悬在那里,始终无法说服自己。

我们内部组织 Web JS SDK 开发人员来集中开会讨论,当时判断刷量的可能原因:Web JS SDK 的 bug 导致?有人恶意攻击,灌注的脏数据导致?后端服务中的 bug 导致的重复读取数据导致?

为了验证我们的推测,申请了一个客户被刷量的环境查看,判断不是 Web JS SDK 和后端服务的 bug ,目前的方向也只剩下是有人恶意攻击了。Web JS SDK 在前端针对这种情况,没有什么方法阻止,寄希望于后端可以将这样的刷量数据去重。

由于 Web 端的数据入库后,默认使用服务器时间,而服务端的去重逻辑是根据 trackid、time 等一起去重。像这样的刷量数据入库,虽然 trackid 一致,但是 time 相差只有几十毫秒,因此无法去重。为了解决这一问题,可以在后端对于 Web 端数据的去重逻辑中将 time 字段去除,这样就可以对刷量数据进行去重了。

不过,这只是一个临时解决方案,且该方案只针对集群版有效,有一定的局限性。另外,这种方案属于出现了刷量后的被动处理。

“用力啊!”

对于此问题,书记也一直怀疑,每天见我必问:“有进展吗?用力啊!” 由于并没有找到确定的原因,我在网上查到 image 请求死循环的资料,如下图所示: 

图 5 image 请求死循环资料

于是我查看 Web JS SDK 源码,发现已经对 image 请求的 onerror 做了 null 赋值处理,不会出现死循环现象。有点失落,这个方向也是不对的。

场景难以复现,多次转机出现却屡陷僵局

终于,转折出现了。当我与被刷量客户的技术做深入沟通时,有了一个重大发现。

4 月的某天,客户拿到注册用户的手机号,通过技术人员联系到这个用户。发现用户是正常操作,只是使用了某浏览器访问页面。当时,远程客户电脑进行操作,发现如果关闭浏览器后就会停止刷数据,浏览器处于开启状态就会一直刷数据。另外,发现用户的浏览器版本比较老,让其升级到最新的浏览器后,依然能够出现刷数据的情况。同时,在访问页面时页面会有卡顿情况,风扇也转的特别厉害。另外,同一时刻该用户对客户自己页面的一个水印图片访问量也很大,达到了 21.4 万次。但是,对神策的 sa.gif 访问量更多,达到 255.4 万次。

不过当客户的技术在自己电脑上模拟的时候,无法复现这个问题。查看当前稳定版的 M 浏览器内核为 Chrome 78.0.3904.108。通过这个发现,我去查看其他客户的最近刷量数据,均发现其 UA 是 Chrome 78.0.3904.108, 指向 M 浏览器。通过以上线索推论:刷量问题很可能不是人为恶意攻击,而是 M 浏览器访问针对 image 数据请求可能有无限循环的 bug 导致的。

按照客户提供的线索,我反向查看了下:以该内核版本为筛选条件,发现出现刷量的那天,有近 5300 个用户使用该内核版本访问了页面,而出现刷量的情况只有 1~2 个用户。从这方面看,刷量似乎不是必现的。本地使用多台电脑,测试 M 浏览器均没有能够复现,问题似乎又陷入了僵局。

再换一条路,基于 M 浏览器的问题判断,我当天我在浏览器社区留言,希望可以从浏览器的工作人员那里可以获得答复和帮助,如图所示。 

图 6 留贴浏览器社区

工作人员通过 QQ 联系了我,并与我沟通了基本情况。由于他们没有受理过类似问题,希望我提供复现的页面,但是我这边没有复现的页面。因此,这个方向的路也堵住了。

感恩信任!与「客户的用户」的多次远程、面基……

在走投无路时,几经辗转,为复现场景,我再次联系客户的技术人员,希望能够联系到之前两位用户。经过客户的提前沟通,以及一系列的保密协议签署后,最终提供两位用户的联系方式。

起初我几次联系,都没有能够打通电话。而此时,刷量问题愈演愈烈。因为线索只剩下这一条了,我就硬着头皮继续打电话,终于还是拨通了。

在此很感激两位用户的信任。第一位用户帮忙安装了 TeamViewer,并提供了远程。可惜的是这一次没有复现刷量的情况。

不能放弃,继续联系另一位用户。由于是上班时间,另一位用户电脑在家且不方便配合,约了周末在家配合我远程:当打开他电脑上的浏览器并访问客户的页面,用户反馈电脑风扇开始响起来了。我打开任务管理器,发现其 M 浏览器访问客户网页的 CPU 占比很高,如图所示。 

图 7 刷量时的任务管理器

同时从神策分析看,这个时候该机器在进行刷量,如图所示:

图 8 刷量时的监控平台

但是通过控制台,并没有发现大量数据刷量的请求,神策的 sa.gif 发送数据请求都是正常的,如图所示。 

图 9 刷量时的控制台信息

反反复复检查了几遍,没有发现其他异常情况和原因。我只好断了远程,并尝试和用户约了下一次远程查看。同时,试探了一下:如果远程查看还是没有发现问题,是否可以面基,直接由北京的同事操作和查看其电脑(由于我在合肥办公),没想到客户居然真的同意了!

由于也占用了他比较长的时间,我这边给他发了个 100 元红包表示感谢(感谢书记给我报销)。

结束客户的远程之后,和根哥沟通了第一次远程的情况。根哥给了关键性的建议:可以查看下是不是电脑防火墙或者浏览器插件导致的。 因此,我与用户约了周一中午再次远程,该用户将电脑背到公司,通过午休时间给我远程查看。

三行代码解决问题,浏览器也同步修复自身 BUG

中午我没有休息,这次远程,依然复现了问题。我从浏览器插件检查,发现了一个可疑的插件:图片下载插件,这个插件和之前发现的针对 sa.gif 图片请求的刷量有一些重合之处。赶快测试下,果然有了突破。

当我禁止该插件时,CPU 降下来了,同时测试后端数据入库也停止了刷量情况。反复测试后,验证了确实是该插件导致的。

结束远程后,我在本地使用机器测试,也能稳定的复现刷量的情况。在群里我同步了该插件的情况,其他同事也帮忙测试。同时,经过进一步的测试,通过打开插件的控制台,发现了插件的确在重复不断地发送图片请求。

查看该插件,发现是该浏览器的应用市场中的一款常用的图片下载扩展应用。应该是使用 Chrome 内核的时候,同时带过来的,通过查看 Chrome 应用商店也发现了该插件。

在 Chrome 中安装该扩展应用时,也复现了刷量的情况。由于 Chrome 商店国内访问很少,所以少有用户能够直接下载该扩展使用。而 M 浏览器非常方便的提供了该应用的下载和安装,且属于图片下载类扩展的前几名扩展,如图所示:

图 10 图片下载类扩展排名

至此,刷量的原因总算是水落石出了。

同事想爷本地测试也验证了刷量情况,并将插件源码获取到后,发给大家测试。基于想爷提供的源码,我从网上查阅、学习插件开发和调试的方法后,在本地调试插件。开启插件的调试模式,在插件的控制台中,呈现了快速大量的重复 image 请求发送出去。调试插件代码发现,该插件通过浏览器提供的 API 拦截浏览器的 image 请求后,又重新创建一个新的图片请求去下载图片。致命的是,该循环没有加限制条件,这个新的图片请求通过浏览器发送出去后,再次被拦截,又创建一个新的图片请求。

研发大康哥通过调试该插件代码,给出建议,只要补充三行代码就可以解决该问题,如下图所示: 

图 11 插件优化代码

根哥提出了几个解决方案:

  1. 在 SDK 中是否可以检测到该插件,含有该插件的环境将发送方式变更为 ajax 方式;

  2. 联系 M 浏览器,反馈该问题插件,希望其可以安排对插件的检测和下架;

  3. 联系插件作者,反馈问题,希望可以修复掉问题代码,发布新版。

大康哥研究了一下:由于浏览器的限制,在页面中无法查看这类扩展插件的列表。因此,无法在 Web JS SDK 集成时,从页面的环境中查看当前浏览器是否集成了该插件,从而自动将数据的发送方式从 image 更改为 ajax。我这边也从插件声明的变量和静态资源入手,尝试了很多办法,也没有能够在页面的 SDK 上捕捉插件的变量或者静态资源。至此,寄希望于 SDK 主动识别插件的方案走不通了。

大约在 6 月 8 日,我再次联系浏览器工作人员,与之详细反馈了插件情况。工作人员给了我一个 M 浏览器插件组的邮箱,让我将详细情况通过邮件的方式发给该部门,然后在 1 到 2 个工作日会有工作人员联系我。此时,再去 M 浏览器的应用市场,将该插件截图一下作为邮件内容发送出去,却意外发现了一个惊喜,该插件已经做了升级。当前版本从 1.2.3 变成了 2.2.0 版本,同时去 Chrome 应用商店查看,里面该插件已经升级到 2.2.0 了。

安装调试该插件代码,发现已经将 bug 修复(此处与大康哥之前提出的修复代码基本一致),代码如下图所示。 

图 12 新版插件源码

经过测试后,确实不会再出现刷量的情况了。同时,在随后的值班过程中,也发现刷量问题出现的情况大幅减少。

除了解决客户的问题,还能够帮 M 浏览器暴露了插件问题,定位了有插件的用户风扇狂转和 CPU 飙升的问题原因,对我们来说,也是很开心的。

那些费力「不讨好」的事情

在这个解决“刷量”的案例中,牵涉人员众多,包括客户、客户的用户、浏览器工作人员、第三方插件作者,还有神策各地同学,5 方的努力与协作,缺一不可。采用的手段也非常规,比如 SDK 技术顾问给「客户的用户」发红包,再如 SDK 技术顾问通过网络给 M 浏览器工作人员留言……

有外部人评价,我们在单个客户上的付出,有时候会显得“不划算”,毕竟问题的本身不在神策。但对神策来说,这是难而正确的事,客户的员工都看在眼里,我们不辜负客户的信任,客户问题无小事,始终 All In!

类似这种,我们帮客户解决的『非分内』的问题,还有很多:

·某公有云虚拟机性能下降导致神策系统运行慢,某公有云拒认,我们写程序给出证据,某公有云迁移机器解决问题。

·某客户物理机磁盘硬件故障,供应商拒认,我们协助客户证明,后来供应商承认并更换磁盘。

·某客户底层网络 bug 影响神策业务,客户内部部门不认可,我们写程序证明,客户表示 bug 修不了,被迫绕过。

·某公用云虚拟机故障导致指令集不支持,某公有云拒认,我们写程序证明,某公用云解决并上门道歉……

最后附上某位朋友送的一面锦旗。

其实,哪有什么「料 bug 如神」,只不过在每个问题被解决的背后,都付出了超常规的努力。

我在神策做研发 丨 与客户难题“对抗”的百余天相关推荐

  1. 我在神策做研发 | 与客户难题“对抗”的百余天

    对于每一个客户的问题,不管大小,都需要跟进追踪到底,以获得最佳的答案. 一个问题一个坑,留了坑,前路必将荆棘丛生:填了坑,前路即是坦途.这是神策人的做事态度和行事准则,也帮助我树立了积极的人生观. 如 ...

  2. 我在神策做研发丨做冲在前方的第一方队,造中国最好的开源 SDK

    最初担任负责 SDK 方向的产品经理的时候,其实内心是充满疑虑的,最大的疑虑莫过于"SDK 还需要产品经理"?在实践的时候才发现,SDK 就是很需要产品经理,这个是在深入参与 SD ...

  3. 我在神策做研发 | 成长中的成都研发中心

    在这里,他们既见证了团队从初创到迅猛增长,又作为神策的西南军团一路披荆斩棘.这里充实并快乐,热情且刺激,快来和他们一起,品尝神策不一样的成都味道. 好吃的这么多,吃哪家? 王小虾 | 后端研发工程师 ...

  4. 我在神策做研发 | 嘿!这里是合肥研发中心!

    在这里,有相信"做难事,必有所得"的研发工程师,有打破"技术型思维"的产品经理,有被爱与信任包围的职场妈妈,有拿到"工作生活双层财富"的幸运 ...

  5. 我在神策做研发 | 码农变身“建筑师”:安逸中离走,责任中成长

     码农变身"建筑师"  来了神策之后,我才真正喜欢上开发 2018 年,Jason 选择从诺基亚离职.人一旦在安逸.悠闲的环境中呆久了就会丧失一些热情,例如对生活的热情.对工作的斗 ...

  6. 我在京东做研发丨京东物流仓储效率提升AI算法大揭秘

    在京东无人仓内 十几种不同的机器人自动完成订单生产和商品入库.拣选 同时还有操控全局的智能控制系统 实现仓库自动治理.控制.决策 仓储运营效率大大提升 本期,京东云邀请京东物流通用AI算法专家将为你揭 ...

  7. 神策合肥研发中心携手安徽开发者社区,深入交流共促行业发展

    近日,神策数据携手安徽开发者社区,在神策合肥研发中心共同举办了"走进神策"技术交流活动. 坚守"推动安徽软件行业发展"的初心,安徽开发者社区自成立以来,多次通过 ...

  8. PPT 下载 | 神策数据孙文亮:客户全生命周期管理从方法到实践全解析

    在以"场景赋能·驱动有数"为主题的神策 2018 数据驱动大会现场,神策数据技术经理孙文亮发表了名为<客户全生命周期管理从方法到实践>的主题演讲. 温馨提示:点击文末阅 ...

  9. 「技术人生」第10篇:如何做研发效能提升(即指标体系建设过程回顾)

    01 背景 Aliware 纵观软件研发的发展历程,如果说"业务需求开发"是核心主线的话,那么研发效能建设就是这一核心主线之外最大的一条支线.每个历史阶段的研发效能所面对的主要矛盾 ...

最新文章

  1. 构造post_用requests构造简单请求
  2. 折腾的人生......
  3. Windows下进程间通信及数据共享
  4. UVa 10642 - Can You Solve It?
  5. Python学习day12(生成器,列表/生成器推导式)
  6. (创建模式 上)设计模式——工厂、抽象工厂 C++/Python3实现
  7. 找出数组中两个只出现了一次的数
  8. unity 日志级别_【Unity】通用的Debugger日志模块
  9. 数学怪兽-法国数学家庞加莱
  10. Windows10安装VMware(图文教程)
  11. 信息量、信息熵、交叉熵、KL散度、JS散度、Wasserstein距离
  12. 细说IIR滤波器和FIR滤波器的区别
  13. (一)初识Echarts之柱状图
  14. RHEL7CentOS7 (精简操作指令)
  15. QuickTime Component实例
  16. 启动mysql错误解决方案
  17. Android Build 获取手机信息
  18. 求一个数的最小素因子外加快速分解质因子
  19. Day10 堆排序、模拟堆 trie树(字典树) 并查集
  20. 【书影观后感 三】1587—雪后的大明

热门文章

  1. python高斯滤波和降噪_高斯滤波原理及python实现
  2. python编码-python中处理中文编码问题
  3. mplus 软件_Mplus 8.3 Combo Version 多元统计分析软件(Win)
  4. c malloc 头文件_C 数据类型
  5. redis list操作_大厂面试高频Redis,记不住的多操作几次吧
  6. 计算机怎样选定硬盘,如何给电脑分盘
  7. php ci框架 模板输出,CodeIgniter模板引擎使用实例
  8. java第二次测试笔试题_微软第二次笔试第一题java代码 已AC
  9. vim ctrlp找到文件后,如何在新窗口或者新标签中打开
  10. np.random.seed的有效期及固定的种子会有固定的顺序