程序員小失誤,45分鐘搞垮一家美國大公司。(圖片來源:Adobe stock)
如果有人告訴你,45分鐘就能搞垮一家大公司,你可能會覺得有點荒謬。但工程師Doug Seven卻真的親歷過這樣的事情。
8年前,因為一次失敗的部署,騎士資本集團(Knight Capital Group)在僅僅45分鐘內就造成了4.6億美元的虧損。
這是一個真實的故事。
儘管Doug Seven並不是事件的參與者,但他在後來的會議中不斷提及DevOps、代碼配置和持續交付的主題,希望讓開發人員意識到部署的重要性。
究竟是怎麼回事?Doug Seven在博客中分享了這個故事。
故事背景
這個故事的主角是一家名為騎士資本集團(Knight Capital Group)的美國全球金融服務公司,它從事做市、電子執行、機構銷售和交易。
2012年,Knight是美國最大的股票交易商,在紐約證交所和納斯達克的市場份額約為17%。Knight電子交易集團(ETG)平均每日交易量超過33億筆,每日交易額超過210億美元。
種種數據表明,當時公司的運營和財務狀況非常優秀,2012年7月31日,Knight擁有約3.65億美元的資產。
當時,紐約證交所正計畫於2012年8月1日推出一項新的零售流動性計畫。
為了準備這次活動,Knight更新了他們的路由器SMARS。這個路由器負責將訂單發送到市場上執行。SMARS的核心功能之一是接收Knight交易平臺其他組件的訂單(父訂單),然後發送一個或多個子訂單執行。換言之,SMARS將從交易平臺收到大量訂單,並將它們分成多個較小的訂單,以便找到股票數量相匹配的買家或者賣家。父訂單越大,生成的子訂單越多。
在SMARS中,有一段老舊的代碼,名為「Power Peg」,它已經8年沒被用到過了,而此次更新的目的正是要換掉這段代碼。更新的代碼重新調整了用於激活Power Peg功能的舊標誌的功能。
代碼經過了徹底的測試,並且還進行了一系列的驗證。所有的一切都看起來很完美,找不到出錯的理由。
程序員小失誤,45分鐘搞垮一家美國大公司。(圖片來源:Adobe stock)
死灰復燃的舊代碼
2012年7月27日至2012年7月31日期間,Knight的開發人員每天手動將新的軟體部署到公司的8臺伺服器上。
然而,在新代碼的部署過程中,Knight的一名技術人員忘記將新代碼複製到所有8臺SMARS計算機伺服器中——他漏掉了其中一臺伺服器。
沒有第二個技術人員來審查這個部署。
Knight的所有人都沒有意識到,Power Peg代碼並沒有從第8個伺服器上刪除,也沒有添加新的RLP代碼。Knight沒有書面流程要求這樣的審查。
2012年8月1日,在美國東部時間上午9:30,市場開盤。Knight開始代表客戶處理訂單。
具有正確SMARS部署的7臺伺服器開始正確處理這些訂單。然而,發送到第8臺伺服器的命令觸發了可支持的重新利用標誌,並從死地中恢復了舊的Power Peg代碼。
殺手代碼如殭屍般的攻擊
Power Peg代碼用於在執行子訂單時,根據父訂單計算購買或者出售的股份。Power Peg將指示系統在完成父訂單後停止傳送子訂單。
也就是說,Power Peg會跟蹤子訂單,並在父訂單完成後停止它們。
2005年,Knight將這種累計跟蹤功能移到了代碼執行的早期階段,從而從Power Peg中刪除了計數跟蹤。
當激活第8臺伺服器上的Power Peg標誌時,Power Peg功能開始路由子訂單以供執行。但由於沒有根據父訂單跟蹤共享量,造成了一個永無止境的循環。
所有開發和運營團隊都應該從這次事件中吸取教訓。(圖片來源:Adobe stock)
地獄45分鐘
想像一下,如果你有一個系統,它能夠向市場發送自動化的、高速的訂單,且沒有任何跟蹤程序來檢查是否執行了足夠的訂單,會發生什麼?沒有比這更糟糕的事了。
上午9:30開市時,人們很快就知道出了問題。到上午9點31分,華爾街的許多人都清楚發生了一些嚴重的事情。市場上充斥著非正常交易量的股票訂單。
到上午9點32分,華爾街的人們都在想,為什麼訂單還沒有停下來,為什麼沒有人按下任何系統的關閉開關?結果他們發現,並沒有關閉開關。在交易的前45分鐘裡,Knight的交易量佔了總交易量的50%以上,這使得某些股票的市值上漲了10%以上。因此,其他股票因錯誤的交易而貶值。
更糟糕的是,Knight的系統在當天早些時候開始自動發送電子郵件。早在上午8:01,SMAR已經處理了符合上市前交易條件的訂單。郵件消息引用SMARS,並將錯誤識別為「Power Peg disabled」。
在上午8:01到9:30之間,Knight工作人員也收到了97封郵件。可惜的是,這些電子郵件不是作為系統警報設計的,因此沒有人立即查看它們。
在Knight經歷的45分鐘內,他們嘗試了幾種反制措施,試圖阻止錯誤的交易。由於沒有終止開關,所以他們只能在實時交易環境中嘗試診斷問題。
每分鐘,系統上約有800萬股股票被交易。他們無法確定是什麼導致了錯誤的命令,所以他們從正確部署的伺服器上卸載了新代碼。
換句話說,他們刪除了工作代碼,留下了損壞的代碼。
這更加放大了問題。最開始,僅在部署不正確的伺服器上,額外的父命令激活了Power Peg代碼。現在,問題蔓延到了所有伺服器上。最後,他們終於停止了系統,但此時已經進行了45分鐘的交易。
在開盤的前45分鐘,市場收到並處理了212份父訂單。因此,SMARS向市場發送了數以百萬計的子訂單,產生了400萬筆交易,而其中154只股票的交易量超過了3.97億股。這意味著,Knight資本集團在45分鐘內造成了4.6億美元的虧損。
然而,Knight只有3.65億美元的資產。
45分鐘後,美國股市最大的交易商、紐約證交所和納斯達克的主要做市商Knight破產,4個月後被Getco LLC收購。
軟體發布必須可重複、可靠
所有開發和運營團隊都應該從這次事件中吸取教訓。僅僅構建優秀的軟體並對其進行測試是不夠的,你還必須確保它被正確地交付給市場,這樣你的客戶才能獲得你所交付的價值。
部署SMARS的工程師並不是此事唯一的責任人,Knight設置的流程和他們所面臨的風險並不匹配。此外,他們的流程天生就容易出錯。任何時候,如果你的部署過程依賴於人主動閱讀和遵循說明,那麼都將面臨風險。人是會犯錯的。錯誤可能出現在指令中,也可能出現在指令的解釋中,或出現在指令的執行中。
部署需要自動化,並且可重複,儘可能避免潛在的人為錯誤。如果Knight實現了自動化部署系統,將配置、部署和測試全部自動化,那麼這次錯誤本可以避免。