我在神策做研发 丨 与客户难题“对抗”的百余天
對于每一個(gè)客戶的問題,不管大小,都需要跟進(jìn)追蹤到底,以獲得最佳的答案。
一個(gè)問題一個(gè)坑,留了坑,前路必將荊棘叢生;填了坑,前路即是坦途。這是神策人的做事態(tài)度和行事準(zhǔn)則,也幫助我樹立了積極的人生觀。
如果同行也正在經(jīng)受類似問題的困擾,希望同行可以通過這篇文章,在排查過程中能夠獲得一點(diǎn)啟發(fā)。
刷量?客戶反饋異常 IP 發(fā)送大量重復(fù)數(shù)據(jù)
從今年 2 月份起,我陸續(xù)收到客戶反饋:Web JS SDK 短時(shí)間內(nèi)上報(bào)了大量重復(fù)的數(shù)據(jù)到神策分析,從而影響了客戶的分析、決策和制定運(yùn)營計(jì)劃。對于這種情況我們通常稱之為 “刷量”。什么是刷量?
?
圖 1 刷量表現(xiàn)—按天
圖 2 刷量表現(xiàn)—按分鐘
用戶所反饋的現(xiàn)象和刷量一致,有幾個(gè)異常 IP 短時(shí)間內(nèi)密集發(fā)送 Web 端重復(fù)數(shù)據(jù)入庫。一個(gè) IP 一天發(fā)送的重復(fù)數(shù)據(jù)甚至達(dá)到了幾十萬、上百萬條,這顯然不是一個(gè)正常用戶產(chǎn)生的行為數(shù)據(jù)。
我們查看了刷量時(shí)的用戶行為序列,如下圖,可以看到事件是重復(fù)循環(huán)觸發(fā)的,時(shí)間間隔在幾十毫秒。?
圖 3 刷量發(fā)生時(shí)的用戶行為序列
針對此問題的反饋,我們進(jìn)行了快速排查及提供初步解決方案。 當(dāng)時(shí)的排查思路:
一,會(huì)不會(huì)是客戶代碼 bug 導(dǎo)致重復(fù)觸發(fā)事件?
通過協(xié)調(diào)運(yùn)維幫忙查詢事件日志,證明這些重復(fù)事件的?trackid(Web JS SDK 對發(fā)送數(shù)據(jù)生成的隨機(jī)數(shù),每條采集和發(fā)送的數(shù)據(jù)都會(huì)有自己獨(dú)特的?trackid) 是一樣的。從這個(gè)方面看,基本排除了是客戶代碼 bug 導(dǎo)致的,因?yàn)榧词故谴a重復(fù)觸發(fā)的事件,trackid 是不會(huì)重復(fù)的。
二,會(huì)不會(huì)是別人惡意獲取了神策的數(shù)據(jù)采集請求和數(shù)據(jù)體,使用工具或者腳本偽造請求,灌注臟數(shù)據(jù)到神策分析服務(wù)器?
Web JS SDK 采集的數(shù)據(jù),默認(rèn)使用 image 方式發(fā)送數(shù)據(jù),GET 請求的數(shù)據(jù)接收地址和數(shù)據(jù)體都包含在請求的 URL 中,如圖所示:
圖 4 Web JS SDK 的數(shù)據(jù)發(fā)送
只要復(fù)制該 Request URL 直接在瀏覽器地址欄訪問,或者使用腳本訪問,就會(huì)有一條一模一樣的數(shù)據(jù)入庫。這也符合?trackid 重復(fù)的情況,而且可以集中產(chǎn)生大量的請求,實(shí)現(xiàn)灌注臟數(shù)據(jù)。在本地使用腳本模擬,也能夠復(fù)現(xiàn)出來數(shù)據(jù)刷量的情況。
因此,推測的結(jié)論是:有人從集成了 Web JS SDK 的頁面上,截取了發(fā)送的數(shù)據(jù)請求,并通過腳本灌注臟數(shù)據(jù)進(jìn)入神策分析。
根據(jù)這一結(jié)論,給客戶的方案是:將 Web JS SDK 的數(shù)據(jù)發(fā)送方式從 image 改成 ajax,這樣請求就會(huì)從 GET 變成 POST,在一定程度上避免將整個(gè)請求暴露在 URL 上;將出現(xiàn)過刷量的 IP 增加到后端的防火墻黑名單中。
問題又現(xiàn)!存疑,再深入排查
但是,似乎并沒有解決問題。在接下來的一個(gè)月,依舊陸續(xù)收到刷量的情況反饋。
我每天值班也都膽戰(zhàn)心驚,只要有客戶反饋刷量的情況,心里都咯噔一下:如果是有人惡意刷量,那么持續(xù)刷的動(dòng)作有點(diǎn)說不通,是否有其他原因?qū)е隆瓎柼栆恢睉以谀抢?#xff0c;始終無法說服自己。
我們內(nèi)部組織 Web JS SDK 開發(fā)人員來集中開會(huì)討論,當(dāng)時(shí)判斷刷量的可能原因:Web JS SDK 的 bug 導(dǎo)致?有人惡意攻擊,灌注的臟數(shù)據(jù)導(dǎo)致?后端服務(wù)中的 bug 導(dǎo)致的重復(fù)讀取數(shù)據(jù)導(dǎo)致?
為了驗(yàn)證我們的推測,申請了一個(gè)客戶被刷量的環(huán)境查看,判斷不是 Web JS SDK 和后端服務(wù)的 bug ,目前的方向也只剩下是有人惡意攻擊了。Web JS SDK 在前端針對這種情況,沒有什么方法阻止,寄希望于后端可以將這樣的刷量數(shù)據(jù)去重。
由于 Web 端的數(shù)據(jù)入庫后,默認(rèn)使用服務(wù)器時(shí)間,而服務(wù)端的去重邏輯是根據(jù) trackid、time 等一起去重。像這樣的刷量數(shù)據(jù)入庫,雖然 trackid 一致,但是 time 相差只有幾十毫秒,因此無法去重。為了解決這一問題,可以在后端對于 Web 端數(shù)據(jù)的去重邏輯中將 time 字段去除,這樣就可以對刷量數(shù)據(jù)進(jìn)行去重了。
不過,這只是一個(gè)臨時(shí)解決方案,且該方案只針對集群版有效,有一定的局限性。另外,這種方案屬于出現(xiàn)了刷量后的被動(dòng)處理。
“用力啊!”
對于此問題,書記也一直懷疑,每天見我必問:“有進(jìn)展嗎?用力啊!” 由于并沒有找到確定的原因,我在網(wǎng)上查到 image 請求死循環(huán)的資料,如下圖所示:?
圖 5 image 請求死循環(huán)資料
于是我查看 Web JS SDK 源碼,發(fā)現(xiàn)已經(jīng)對 image 請求的 onerror 做了 null 賦值處理,不會(huì)出現(xiàn)死循環(huán)現(xiàn)象。有點(diǎn)失落,這個(gè)方向也是不對的。
場景難以復(fù)現(xiàn),多次轉(zhuǎn)機(jī)出現(xiàn)卻屢陷僵局
終于,轉(zhuǎn)折出現(xiàn)了。當(dāng)我與被刷量客戶的技術(shù)做深入溝通時(shí),有了一個(gè)重大發(fā)現(xiàn)。
4 月的某天,客戶拿到注冊用戶的手機(jī)號,通過技術(shù)人員聯(lián)系到這個(gè)用戶。發(fā)現(xiàn)用戶是正常操作,只是使用了某瀏覽器訪問頁面。當(dāng)時(shí),遠(yuǎn)程客戶電腦進(jìn)行操作,發(fā)現(xiàn)如果關(guān)閉瀏覽器后就會(huì)停止刷數(shù)據(jù),瀏覽器處于開啟狀態(tài)就會(huì)一直刷數(shù)據(jù)。另外,發(fā)現(xiàn)用戶的瀏覽器版本比較老,讓其升級到最新的瀏覽器后,依然能夠出現(xiàn)刷數(shù)據(jù)的情況。同時(shí),在訪問頁面時(shí)頁面會(huì)有卡頓情況,風(fēng)扇也轉(zhuǎn)的特別厲害。另外,同一時(shí)刻該用戶對客戶自己頁面的一個(gè)水印圖片訪問量也很大,達(dá)到了 21.4 萬次。但是,對神策的 sa.gif 訪問量更多,達(dá)到 255.4 萬次。
不過當(dāng)客戶的技術(shù)在自己電腦上模擬的時(shí)候,無法復(fù)現(xiàn)這個(gè)問題。查看當(dāng)前穩(wěn)定版的 M 瀏覽器內(nèi)核為 Chrome 78.0.3904.108。通過這個(gè)發(fā)現(xiàn),我去查看其他客戶的最近刷量數(shù)據(jù),均發(fā)現(xiàn)其 UA 是 Chrome 78.0.3904.108, 指向 M 瀏覽器。通過以上線索推論:刷量問題很可能不是人為惡意攻擊,而是 M 瀏覽器訪問針對 image 數(shù)據(jù)請求可能有無限循環(huán)的 bug 導(dǎo)致的。
按照客戶提供的線索,我反向查看了下:以該內(nèi)核版本為篩選條件,發(fā)現(xiàn)出現(xiàn)刷量的那天,有近 5300 個(gè)用戶使用該內(nèi)核版本訪問了頁面,而出現(xiàn)刷量的情況只有 1~2 個(gè)用戶。從這方面看,刷量似乎不是必現(xiàn)的。本地使用多臺(tái)電腦,測試 M 瀏覽器均沒有能夠復(fù)現(xiàn),問題似乎又陷入了僵局。
再換一條路,基于 M 瀏覽器的問題判斷,我當(dāng)天我在瀏覽器社區(qū)留言,希望可以從瀏覽器的工作人員那里可以獲得答復(fù)和幫助,如圖所示。?
圖 6 留貼瀏覽器社區(qū)
工作人員通過 QQ 聯(lián)系了我,并與我溝通了基本情況。由于他們沒有受理過類似問題,希望我提供復(fù)現(xiàn)的頁面,但是我這邊沒有復(fù)現(xiàn)的頁面。因此,這個(gè)方向的路也堵住了。
感恩信任!與「客戶的用戶」的多次遠(yuǎn)程、面基……
在走投無路時(shí),幾經(jīng)輾轉(zhuǎn),為復(fù)現(xiàn)場景,我再次聯(lián)系客戶的技術(shù)人員,希望能夠聯(lián)系到之前兩位用戶。經(jīng)過客戶的提前溝通,以及一系列的保密協(xié)議簽署后,最終提供兩位用戶的聯(lián)系方式。
起初我?guī)状温?lián)系,都沒有能夠打通電話。而此時(shí),刷量問題愈演愈烈。因?yàn)榫€索只剩下這一條了,我就硬著頭皮繼續(xù)打電話,終于還是撥通了。
在此很感激兩位用戶的信任。第一位用戶幫忙安裝了 TeamViewer,并提供了遠(yuǎn)程。可惜的是這一次沒有復(fù)現(xiàn)刷量的情況。
不能放棄,繼續(xù)聯(lián)系另一位用戶。由于是上班時(shí)間,另一位用戶電腦在家且不方便配合,約了周末在家配合我遠(yuǎn)程:當(dāng)打開他電腦上的瀏覽器并訪問客戶的頁面,用戶反饋電腦風(fēng)扇開始響起來了。我打開任務(wù)管理器,發(fā)現(xiàn)其 M 瀏覽器訪問客戶網(wǎng)頁的 CPU 占比很高,如圖所示。?
圖 7 刷量時(shí)的任務(wù)管理器
同時(shí)從神策分析看,這個(gè)時(shí)候該機(jī)器在進(jìn)行刷量,如圖所示:
?
圖 8 刷量時(shí)的監(jiān)控平臺(tái)
但是通過控制臺(tái),并沒有發(fā)現(xiàn)大量數(shù)據(jù)刷量的請求,神策的 sa.gif 發(fā)送數(shù)據(jù)請求都是正常的,如圖所示。?
圖 9 刷量時(shí)的控制臺(tái)信息
反反復(fù)復(fù)檢查了幾遍,沒有發(fā)現(xiàn)其他異常情況和原因。我只好斷了遠(yuǎn)程,并嘗試和用戶約了下一次遠(yuǎn)程查看。同時(shí),試探了一下:如果遠(yuǎn)程查看還是沒有發(fā)現(xiàn)問題,是否可以面基,直接由北京的同事操作和查看其電腦(由于我在合肥辦公),沒想到客戶居然真的同意了!
由于也占用了他比較長的時(shí)間,我這邊給他發(fā)了個(gè) 100 元紅包表示感謝(感謝書記給我報(bào)銷)。
結(jié)束客戶的遠(yuǎn)程之后,和根哥溝通了第一次遠(yuǎn)程的情況。根哥給了關(guān)鍵性的建議:可以查看下是不是電腦防火墻或者瀏覽器插件導(dǎo)致的。 因此,我與用戶約了周一中午再次遠(yuǎn)程,該用戶將電腦背到公司,通過午休時(shí)間給我遠(yuǎn)程查看。
三行代碼解決問題,瀏覽器也同步修復(fù)自身 BUG
中午我沒有休息,這次遠(yuǎn)程,依然復(fù)現(xiàn)了問題。我從瀏覽器插件檢查,發(fā)現(xiàn)了一個(gè)可疑的插件:圖片下載插件,這個(gè)插件和之前發(fā)現(xiàn)的針對 sa.gif 圖片請求的刷量有一些重合之處。趕快測試下,果然有了突破。
當(dāng)我禁止該插件時(shí),CPU 降下來了,同時(shí)測試后端數(shù)據(jù)入庫也停止了刷量情況。反復(fù)測試后,驗(yàn)證了確實(shí)是該插件導(dǎo)致的。
結(jié)束遠(yuǎn)程后,我在本地使用機(jī)器測試,也能穩(wěn)定的復(fù)現(xiàn)刷量的情況。在群里我同步了該插件的情況,其他同事也幫忙測試。同時(shí),經(jīng)過進(jìn)一步的測試,通過打開插件的控制臺(tái),發(fā)現(xiàn)了插件的確在重復(fù)不斷地發(fā)送圖片請求。
查看該插件,發(fā)現(xiàn)是該瀏覽器的應(yīng)用市場中的一款常用的圖片下載擴(kuò)展應(yīng)用。應(yīng)該是使用 Chrome 內(nèi)核的時(shí)候,同時(shí)帶過來的,通過查看 Chrome 應(yīng)用商店也發(fā)現(xiàn)了該插件。
在 Chrome 中安裝該擴(kuò)展應(yīng)用時(shí),也復(fù)現(xiàn)了刷量的情況。由于 Chrome 商店國內(nèi)訪問很少,所以少有用戶能夠直接下載該擴(kuò)展使用。而 M 瀏覽器非常方便的提供了該應(yīng)用的下載和安裝,且屬于圖片下載類擴(kuò)展的前幾名擴(kuò)展,如圖所示:
?
圖 10 圖片下載類擴(kuò)展排名
至此,刷量的原因總算是水落石出了。
同事想爺本地測試也驗(yàn)證了刷量情況,并將插件源碼獲取到后,發(fā)給大家測試。基于想爺提供的源碼,我從網(wǎng)上查閱、學(xué)習(xí)插件開發(fā)和調(diào)試的方法后,在本地調(diào)試插件。開啟插件的調(diào)試模式,在插件的控制臺(tái)中,呈現(xiàn)了快速大量的重復(fù) image 請求發(fā)送出去。調(diào)試插件代碼發(fā)現(xiàn),該插件通過瀏覽器提供的 API 攔截瀏覽器的 image 請求后,又重新創(chuàng)建一個(gè)新的圖片請求去下載圖片。致命的是,該循環(huán)沒有加限制條件,這個(gè)新的圖片請求通過瀏覽器發(fā)送出去后,再次被攔截,又創(chuàng)建一個(gè)新的圖片請求。
研發(fā)大康哥通過調(diào)試該插件代碼,給出建議,只要補(bǔ)充三行代碼就可以解決該問題,如下圖所示:?
圖 11 插件優(yōu)化代碼
根哥提出了幾個(gè)解決方案:
在 SDK 中是否可以檢測到該插件,含有該插件的環(huán)境將發(fā)送方式變更為 ajax 方式;
聯(lián)系 M 瀏覽器,反饋該問題插件,希望其可以安排對插件的檢測和下架;
聯(lián)系插件作者,反饋問題,希望可以修復(fù)掉問題代碼,發(fā)布新版。
大康哥研究了一下:由于瀏覽器的限制,在頁面中無法查看這類擴(kuò)展插件的列表。因此,無法在 Web JS SDK 集成時(shí),從頁面的環(huán)境中查看當(dāng)前瀏覽器是否集成了該插件,從而自動(dòng)將數(shù)據(jù)的發(fā)送方式從 image 更改為 ajax。我這邊也從插件聲明的變量和靜態(tài)資源入手,嘗試了很多辦法,也沒有能夠在頁面的 SDK 上捕捉插件的變量或者靜態(tài)資源。至此,寄希望于 SDK 主動(dòng)識(shí)別插件的方案走不通了。
大約在 6 月 8 日,我再次聯(lián)系瀏覽器工作人員,與之詳細(xì)反饋了插件情況。工作人員給了我一個(gè) M 瀏覽器插件組的郵箱,讓我將詳細(xì)情況通過郵件的方式發(fā)給該部門,然后在 1 到 2 個(gè)工作日會(huì)有工作人員聯(lián)系我。此時(shí),再去 M 瀏覽器的應(yīng)用市場,將該插件截圖一下作為郵件內(nèi)容發(fā)送出去,卻意外發(fā)現(xiàn)了一個(gè)驚喜,該插件已經(jīng)做了升級。當(dāng)前版本從 1.2.3 變成了 2.2.0 版本,同時(shí)去 Chrome 應(yīng)用商店查看,里面該插件已經(jīng)升級到 2.2.0 了。
安裝調(diào)試該插件代碼,發(fā)現(xiàn)已經(jīng)將 bug 修復(fù)(此處與大康哥之前提出的修復(fù)代碼基本一致),代碼如下圖所示。?
圖 12 新版插件源碼
經(jīng)過測試后,確實(shí)不會(huì)再出現(xiàn)刷量的情況了。同時(shí),在隨后的值班過程中,也發(fā)現(xiàn)刷量問題出現(xiàn)的情況大幅減少。
除了解決客戶的問題,還能夠幫 M 瀏覽器暴露了插件問題,定位了有插件的用戶風(fēng)扇狂轉(zhuǎn)和 CPU 飆升的問題原因,對我們來說,也是很開心的。
那些費(fèi)力「不討好」的事情
在這個(gè)解決“刷量”的案例中,牽涉人員眾多,包括客戶、客戶的用戶、瀏覽器工作人員、第三方插件作者,還有神策各地同學(xué),5 方的努力與協(xié)作,缺一不可。采用的手段也非常規(guī),比如 SDK 技術(shù)顧問給「客戶的用戶」發(fā)紅包,再如 SDK 技術(shù)顧問通過網(wǎng)絡(luò)給 M 瀏覽器工作人員留言……
有外部人評價(jià),我們在單個(gè)客戶上的付出,有時(shí)候會(huì)顯得“不劃算”,畢竟問題的本身不在神策。但對神策來說,這是難而正確的事,客戶的員工都看在眼里,我們不辜負(fù)客戶的信任,客戶問題無小事,始終 All In!
類似這種,我們幫客戶解決的『非分內(nèi)』的問題,還有很多:
·某公有云虛擬機(jī)性能下降導(dǎo)致神策系統(tǒng)運(yùn)行慢,某公有云拒認(rèn),我們寫程序給出證據(jù),某公有云遷移機(jī)器解決問題。
·某客戶物理機(jī)磁盤硬件故障,供應(yīng)商拒認(rèn),我們協(xié)助客戶證明,后來供應(yīng)商承認(rèn)并更換磁盤。
·某客戶底層網(wǎng)絡(luò) bug 影響神策業(yè)務(wù),客戶內(nèi)部部門不認(rèn)可,我們寫程序證明,客戶表示 bug 修不了,被迫繞過。
·某公用云虛擬機(jī)故障導(dǎo)致指令集不支持,某公有云拒認(rèn),我們寫程序證明,某公用云解決并上門道歉……
最后附上某位朋友送的一面錦旗。
??
其實(shí),哪有什么「料 bug 如神」,只不過在每個(gè)問題被解決的背后,都付出了超常規(guī)的努力。
總結(jié)
以上是生活随笔為你收集整理的我在神策做研发 丨 与客户难题“对抗”的百余天的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 八城联动 丨 神策 2020 数据驱动用
- 下一篇: 神策数据助力海通证券,精耕 4 大场景,