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

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

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

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

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

图 1  刷量表现—按天

图 2  刷量表现—按分钟

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

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

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

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

当时的排查思路:

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

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

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

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

图 4  Web JS SDK 的数据发送

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

因此,推测的结论是:有人从集成了 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 端的数据入库后,默认使用服务器时间,而服务端的去重逻辑是根据  track_id、time 等一起去重。像这样的刷量数据入库,虽然 track_id 一致,但是 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. 我在神策做研发 | 嘿!这里是合肥研发中心!

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

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

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

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

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

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

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

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

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

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

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

  8. 一百人研发团队的难题:研发管理、绩效考核、组织文化和OKR

    什么是研发团队?简单的说,你熟悉的那帮穿格子衬衫,以程序员为核心组成的团队,就是研发团队. 本来,你以为格子男们是很乖很闷骚的那种,管理和协作起来比销售和业务简单很多,而实际情况是.......格子男 ...

  9. 老板让我做研发负责人,谈谈我的想法和认知

    写在前面:今天接了一个研发负责人的角色.虽然还是有很多疑虑和不确定的问题没有聊透彻,但是至少从今天起,要有个思想准备,同时要有在工作方式上做出改变. 对这个岗位和角色,我给自己的心理建设和预期是: 工 ...

最新文章

  1. Idea--使用Idea调试设置
  2. [手机分享]黑莓手机7系列分享之——黑莓7730
  3. 升级SharePoint数据库到SQL Server 2005的一点心得
  4. spring cloud 入门系列七:基于Git存储的分布式配置中心--Spring Cloud Config
  5. 机器学习篇—大厂笔试题
  6. 萌新的Python练习菜鸟100例(九)暂停一秒输出
  7. ubuntu20.04下开发海康威视网络摄像头sdk(二)云台基本控制(位姿控制)
  8. 计算机房网络布线培训方案,网络工程综合布线实训授课计划.doc
  9. 那些年,我们信了课本里的那些鬼话
  10. 【致敬雷神】星星之火,可以燎原
  11. Win7系统安装详细教程步骤
  12. 用户如何制作360度全景图?360度全景图有什么用?
  13. 大二算法期末复习-排序-英文姓名排序
  14. 如何修改SnipeIT的部分设置
  15. 剑指Offer_入门_JZZ_斐波那契数列
  16. 基于java spring框架开发部标1078视频监控平台精华文章索引
  17. 如何能更更好的装逼 (Windows CMD命令大全)
  18. 在 iOS 中对接收到的网络数据(NSData)进行文件读写
  19. VCC、 VDD、VEE、VSS的区别
  20. 渗透攻击exp共享站点(建议收藏❤️)

热门文章

  1. maven 设置打包路径为模块_4、Jenkins持续集成之maven编译
  2. __getitem__的作用
  3. typeError: unhashable type: 'list’问题分析
  4. 遍历dict的items输出tuple类型
  5. 计算机组成原理第二章数据,计算机组成原理第二章数据表示(含答案)
  6. qt icon如何显示gif_收集Qt支持的emoji表情-第五弹
  7. Python日志详解【两篇就够了系列】--第二篇loguru
  8. Java反射之从对象获取值
  9. 2021下半年软考分数线会有变动吗?
  10. 《系统集成项目管理工程师》必背100个知识点-97信息系统生命周期