只因為漏寫了一行代碼,macOS 錄屏工具 Screen Studio 的開發者 Adam Pietrasiak 意外燒掉了 8000 美元的流量費,連帶著還讓部分用戶斷了網。一個看起來微不足道的自動更新改動,最后變成了一場技術災難。這不僅是一場“翻車事故”,也給所有開發者敲響了警鐘:凡是跟網絡、成本沾邊的代碼,真的一點都馬虎不得。
這篇名為《One line of code that did cost $8,000》的文章雖然寫于 2023 年,最近卻在 Hacker News 上被翻了出來,再次引發開發者圈熱議。
來源:https://pietrasiak.com/one-line-of-code-that-did-cost-dollar8000
作者 | Adam Pietrasiak
編譯 | 屠敏
出品 | CSDN(ID:CSDNnews)
由于一個 Bug,macOS 錄屏應用 Screen Studio 的自動更新機制出了問題:每隔 5 分鐘就會讓每位用戶重復下載一次更新文件。這個更新包有 250MB,大量重復下載導致請求次數飆升至 900 萬次,最終生成了超過 2PB(約 200 萬 GB)的 Google Cloud 流量。
當時的流量波動如下圖所示,雖然這個截圖本身看起來沒什么大不了,但背后的流量規模可不容小覷:在一個多月的時間里,Screen Studio 的服務端持續跑出至少 100 Mib/s 的帶寬,有時甚至逼近 1 GiB/s——而且是每一秒都在大規模傳輸數據。
這個 Bug 簡單得令人痛心,甚至可以說愚蠢至極。
簡單來看,Screen Studio 是一款運行在 macOS 上的本地屏幕錄制應用。出于常規需求,身為開發者的 Adam Pietrasiak 為它設計了一個自動更新機制,讓用戶可以方便地獲取最新版本。
更新邏輯其實也很簡單:應用會每五分鐘檢查一次更新,或者在用戶啟動時主動檢查。一旦檢測到有新版本,就會下載更新文件,并暫停五分鐘一輪的檢查循環,直到用戶完成安裝并重啟應用為止。
悲劇性的重構
最初,Screen Studio 的自動更新機制還有個小問題:一旦檢測到新版本,應用會立刻彈窗提醒用戶更新。但這在用戶錄屏時出現彈窗將會非常擾人——畢竟誰也不希望錄到一半被窗口打斷。
為了改善這一體驗,Adam Pietrasiak 決定對更新邏輯進行了重構。不過,就是在這次重構中,出了個代價慘重的疏忽:他漏掉了一行關鍵代碼——在更新文件已經下載后,應該停止后續的定時檢查。
忘記這行代碼的后果就是:應用每五分鐘就會重新下載一次同一個 250MB 的更新包。
悲劇性的運行環境:后臺運行數周
問題在于,事實證明有成千上萬的用戶把 Screen Studio 這款應用長期掛在后臺運行,即使他們并沒有主動使用。
這間接地導致 Bug 的影響被大大放大——這些客戶端每隔五分鐘就自動下載一次 250MB 的更新文件,而且是持續了好幾個星期。
來做個簡單的計算:
每五分鐘一次的頻率,一天大約會執行 288 次下載。
每個更新文件約為 250MB,也就是每天每位用戶產生約 72GB 的下載量。
這一 bug 持續了一個多月,而開發者 Adam Pietrasiak 完全沒有察覺到。
該應用大約有一千個這樣的客戶端實例始終在后臺運行。
250MB × 288 次/天 × 30 天 × 1000 用戶
換算之后就是——2,000,000GB
或 2,000 TB
或 2PB 的流量

雪上加霜的是,Adam Pietrasiak 當時并沒有在 Google Cloud 上設置任何流量或賬單預警機制——畢竟,過去每月的賬單從未超過 300 美元,也就沒太放在心上。
而流量監控呢?也沒人主動去看,因為“以前從來沒出過問題”。
那這場事故最后是怎么被發現的呢?并不是通過技術手段,而是因為 Adam Pietrasiak 的信用卡因為超過了其設定的限額而被銀行拒付了(所幸他事先設了限額,否則后果可能更慘)。
對用戶的影響
這不僅對我們來說是場災難,對一些用戶來說更是嚴重的問題。
對于一部分用戶來說,它甚至成了現實生活中的麻煩:由于更新文件是從用戶設備端發起的下載,超大流量實際上是“從他們自己的網絡里跑出去”的。
有位用戶住在郊區,結果因為異常高頻的網絡使用,被當地的運營商直接斷了網,甚至取消了服務合同——更糟糕的是,那一片區域沒有別的可選網絡提供商。
得知此事后,Adam 表示將對事件負責,并承擔由此產生的全部費用。幸運的是,那位用戶最終還是與運營商協商解決了問題,沒有造成進一步損失。
盡管如此,對開發者和用戶來說,這都是一次糟糕的經歷。Adam 后來說,作為一名設計師,他一直非常在意用戶體驗——但這次的事故,不只是糟糕體驗,甚至一度對用戶造成了實際傷害。
總結教訓
基于此,Adam Pietrasiak 自己也總結了一些經驗,也希望能給其他開發者提個醒:
始終為云服務設置費用預警;
寫自動更新邏輯時要極其小心;
任何可能帶來成本的代碼都要格外謹慎;
設計可由服務器遠程觸發的特殊信號機制,比如“強制更新且不提示用戶”;
定期檢查你的云服務狀態。
最后
隨著 Adam Pietrasiak 把這次事故分享出來,也引發了不少開發者的討論。
有網友指出,這次事件的損失可能遠不止賬單上寫的 8000 美元。比如用戶用的是流量,像移動熱點,很可能因此悄悄多花了不少錢,卻完全不知道是應用的問題。
也有人認為,像自動更新器這種容易出問題、又特別關鍵的功能,其實沒必要硬著頭皮自己做。用個成熟、靠譜的第三方方案,反而更省事、安全。畢竟,一旦 App 出了嚴重 Bug,更新機制就成了唯一的補救通道,設計得不靠譜,后果可能比想象中嚴重得多。網友 jmull 指出,「像“每五分鐘檢查一次更新”這種設計,就挺離譜的,說明他們可能根本沒認真設計這個系統。」
還有開發者將其歸咎為沒有代碼審查。用戶 donatj 表示,「我一直對代碼評審非常嚴格。有一次,一個經理隨口說我應該多留點問題給 QA 處理,語氣差不多是“最壞能出什么問題?”我當時脫口而出:“我們全都丟掉工作。”我們永遠離“因為一行糟糕的代碼丟掉工作”只差一步。我抓到初級甚至資深開發者寫出可能泄露用戶隱私信息(PII)的代碼的次數,簡直數不清。在大多數系統中,一不小心就可能惹上法律麻煩,這實在太容易了。」
這次事件雖然是個意外,但對很多人來說,也是一個值得認真思考的教訓。無論是系統設計、代碼審核,還是日常監控和應急預案,做得細一點、穩一點,總歸是有好處的。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.