多年前,又是週六客服打電話過來,平臺官網不能訪問,app完全無法開啟,客戶在QQ群和微信群中各種反饋,說平臺是不是跑路了?客服的多條400熱線完全被打爆,電話已經接不過來…
前言
一直以來總是想以什麼方式去記錄下自己在互金行業的這段經歷,趁著自己還記得清楚,還能找到一些資料原型,一方面可以分享出來供大家參考,但是更重要就是多年以後我可以根據這些文章回憶起來自己的那段激情歲月。
想了很久但一直沒有實施,後來覺得應該從架構的角度來梳理一篇文章,就寫《從零到百億網際網路金融架構發展史》這篇文章;最後認為只有實戰出來的東西以及解決問題的過程,才是工作中最寶貴的經驗,應該把它分享出來,在梳理的過程中覺得有三起事故比較有代表性就整理出了下面這三篇文章,本篇文章從整體來回憶一下一路走過來所經歷過的救火故事。
作為一個網際網路金融平臺,涉及到使用者資金,任何的服務(資金)差錯使用者都是不可容忍的,使用者不懂什麼是資料庫,不知道什麼網路不通,就是一會看不到錢在app裡面展示都會覺得不安。在已經有很多P2P公司跑路的前提下,使用者個個已經被鍛鍊成為福爾摩斯偵探,每天開啟app檢視收益,監控著平臺一切,甚至半夜升級斷網十分鐘,也會被使用者察覺,直接就發到群裡面,更有甚者直接在QQ群或者微信群中你們的技術行不行!
我們常說的網際網路工作經驗,一方面是開發經驗,但其實更重要的是處理問題的能力。那麼處理問題的能力怎麼來呢,就是不斷的去解決問題,不斷的去總結經驗,其中處理生產環境中問題的經驗更甚,因為在處理生產環境中對個人的壓力和臨危應變的能力要求最高,你不但需要面臨千萬個使用者反饋,客服不時得催促而且旁邊可能就站了N個領導在看著你,一副你行不行的樣子要求立刻馬上解決問題!這個時候你的操作就非常重要,稍有不慎便會引發二次生產事故。
說了這麼多,只是想說明,生產事故對技術綜合能力要求頗高,更是鍛鍊處理問題能力最佳時機!下面給大家介紹我們從零開發到現在百億交易量所遇到的幾次關鍵事故,有大有小挑出一些比較有代表性的事件來分享。
併發滿標
公司系統剛上線的時候,其實沒有經歷過什麼大量使用者併發的考驗,結果公司做了一個大的推廣,湧入了一批使用者來搶標,共1000萬的標的幾乎都在10秒之內搞定,大概會有上萬左右的使用者會同時去搶標,平均每秒大概有千人左右的併發,滿標控制這塊沒有經過大的併發測試,上來之後就被打垮了,導致得結果是什麼呢,1000萬的標的,有可能到一千零幾萬滿標,也有可能會九百多萬就滿標,也就說要不就是多了一些,要不就是少了一些,就滿標了。
這就會很尷尬,因為借款使用者就借款一千萬整,那麼多出來的錢既不能給使用者退回了,因為使用者好不容易才搶上了,無端退了使用者也鬧;少了也是問題,使用者借款一千萬,少了幾十萬也不行,如果短得少了可以想辦法找一些有錢的客戶直接給買了,多了就必須重新放出來讓使用者投資,非常影響士氣,這個問題困擾了我們有一段時間。
購買標的流程圖,不知道大家是否能根據此圖發現問題呢?
超募
為何會產生超募?在最早前的版本中沒有使用樂觀鎖來控制,如果在最後購買的使用者一單出現併發,就會出現超募,比如最後剩餘30000份的購買份額,因為併發量特別大,可能同時會有十幾個使用者拿到了剩餘30000份餘額的可購買額度,有的買1000份、有的買上3000份、有的買上20000份都會驅動滿標,所以最後導致了超募。
針對這個問題,主要是引入了memcached樂觀鎖的概念(底層主要是cas
、gets
兩個命令),在發標的時候存入標的總份額,當使用者購買的時候首先去鎖定使用者購買的份額,因為樂觀鎖的原因,如果同時有兩個使用者拿到份額的時候保證只有一個最後可以更新成功(鎖定份額),(鎖定份額)失敗直接返回,這樣就保證了在入口的時候就直接遮蔽了部分併發的請求。
少募
為何產生少募?少募是可能1000萬的標的突然到980萬就給滿標了,這是因為在超募情況下我們完善了程式碼,使用者一進來首先就是鎖定購買份額,只有鎖定購買份額才能進行下面的流程,如果鎖定購買份額失敗直接返回,這樣雖然保證了在1000萬份額在購買初期必須每一個使用者只能鎖定一份,但是在高併發的情況下,因為購買流程中有十幾個分支,每一個分支失敗就會退回鎖定的份額,這樣就會導致這樣的現象,就是可能是併發一上來,馬上就滿標了,過了一會進度就回退回來了。
少募主要是因為分支失敗回退導致的,一方面我們分析了容易導致回退熱點,因為在使用者搶標的時候會給使用者實時的展示標的進度,在很早的版本中直接就是存入到一個標的進度表裡面,並且採用了樂觀鎖,如果併發一高就頻繁的更新失敗導致回退,因此優化了標的進度這塊,直接去掉了標的進度表,實時根據查詢來展示標的進度(可以有延遲,有快取);另一方面在回退份額的時候在次判斷試下memcached的份額和標的的狀態,如果份額不為零並且標的狀態是滿標,馬上自動更新狀態保證後續使用者可以立即購買再次驅動滿標。
做了以上的兩種優化後,我們還遇到了其它的一些小問題,在不斷的優化過程中,終於穩定下來;在後期版本中將考慮使用MQ佇列或者redis佇列來處理搶標更合理對使用者也更公平一些。
黑客攻擊
2015年應該是網際網路行業受黑客攻擊最多的一年吧,各互金公司都深受其害,其中我就記得網貸之家有一段時間被黑客攻擊的太厲害,連續幾天網站都無法開啟。當然了我們也未能倖免,什麼DDOS攻擊、SQL隱碼攻擊、尋找系統漏洞等都幾乎都經歷過了,有的黑客還比較好,應該是出於善意或者展示自己,將漏洞放到烏雲上面或者漏洞盒子裡面讓廠商來修復。但更多的是一些黑產完全就是威脅、敲詐想撈一筆錢,先看看下面這位吧:
這個傢伙潛伏到我們公司的客戶群裡面,冒充我們的客戶代表將頭像和資料替換成一樣,然後給群裡所有的客服讓他們傳送我們內部的後臺地址,想通過這種方式來尋找突破口,當然了這個算是裡面的小菜鳥吧。
DDOS攻擊
DDOS攻擊我們也是遇到了很多次,確實也沒有比較好辦法,最後都是通過一些笨辦法來儘量的避免,先說說我們的經歷吧。有一次我正在敲程式碼,客服QQ又閃爍了起來,還沒來得及開啟檢視資訊,客服的經理電話就直接打了過來,我立刻就有一種不祥的預感,說官網打不開了,後臺也登入不了。
掛了電話,我在本機進行了測試果然不行,立刻準備登入VPN檢視伺服器各項指標,結果登入不上去,馬上上樓找運維經理,他也登入不上,剛準備給機房打電話的時候,機房來電話了,說我們的一個IP正經歷著1G多的流量訪問,問我們是否正在做什麼活動,剛話沒有說完就說流量已經到5G,不到一分鐘之後流量已經到達18G之多。因為我們的機房和集團公用了一個寬頻入口,結果陸續的集團上面反饋他們的網站、服務也都出現了問題,機房方面害怕引起更大的衝擊,直接把我們官網對外的IP封掉,集團的其它業務也才慢慢都恢復了過來,我們也緊急的更換了外網IP,重新切換了域名解析才恢復。
事後我們根據apache分析了日誌,流量來自N多個不同的IP地址根本無法應對,也正式因為這次攻擊也才讓我們領導重視了起來,將我們公司的機房網路層和公司集團徹底分離,這樣的話不管那方受到大流量攻擊都不會相互影響,我們也想了一些笨辦法,因為上次我們更換了外網IP之後攻擊也就停止了,那麼我們認為肯定是針對我們外網來攻擊的,所有我們就多準備了6個外網IP,當監控到對某一個外網進行攻擊的時候馬上切換到另一個外網地址,就這樣跟他們玩,可以起到非常有限的一點作用,如果黑客真的想跟我們玩,這個辦法就像是小孩子捉迷藏。
週年慶的DDOS攻擊
還有一次我們正在做週年慶活動,突然有人在QQ群裡面給我們客服說了一句,叫你們的技術負責人來找我,然後我們的網站就掛了,我還保留了當時的一個截圖如下:
完了之後客服就來找我,然後按照往常的策略處理完之後,我根據客服給我的QQ號碼加上了那個人,開口就來嚇我,我依稀記當年的對話如下:
黑客:你是平臺的技術負責人嗎?
我:算是吧
黑客:你信不信我可以讓你們官網在5秒之內掛掉?
我:…(沉默,還真害怕又把官網搞掛了)
黑客:你們的官網漏洞很大
我:如果有好的建議請您賜教
黑客:你們的伺服器是不是什麼防護軟體都沒有裝?
我:…(繼續沉默,這會在想不會是那個安全廠商來推廣產品的吧,當然我們基礎的防護肯定有)
黑客:我們有非常多的肉雞,想攻擊誰,幾秒之內肯定搞定
我:…
黑客:我們已經給很多網際網路金融行業做了滲透測試,花點錢幫買你們平安,保證以後不會在出事情
我:…
黑客:免費的策略也有很多,比如360、百度雲的安全產品可以免費低檔10G左右的流量……(中間省略)
黑客:我說了這多,你們也是不是給包煙錢,表示表示。
……
後來也和領導進行了商議,堅決不能給他們錢,不能助漲這種囂張氣焰,實在不行就報警!
曝光一下當年使用的假QQ號,剛查了下變了個頭像和描述,如下:
後來我一直在想為什麼DDOS攻擊總是喜歡根據外網IP來攻擊呢,慢慢好像是理解了如果針對域名來攻擊的話,那不就是攻擊到域名商的伺服器了嗎,一般域名商比較強大,黑客不太搞的定,也確實沒有必要。當然記的前一段時間,某著名域名服務商被攻擊,導致國外twitter等著名的網際網路公司訪問不斷到達半天以上,還是很嚴重的。但是對於我們這些小公司,倒不至於搞這麼大的動作。
到底如何正確的防止DDOS攻擊:
- 第一種方案,隱藏伺服器外網地址,伺服器前端加CDN中轉,免費的有百度雲加速、360網站衛士、加速樂、安全寶等,如果資金充裕的話,可以購買高防的盾機,用於隱藏伺服器真實IP,域名解析使用CDN的IP,所有解析的子域名都使用CDN的IP地址。此外,伺服器上部署的其他域名也不能使用真實IP解析,全部都使用CDN來解析。
- 第二種方案,買一些安全產品來進行流量清洗,主要是阿里雲、騰訊雲這種大廠商提供的一種服務。
- 第三種方案,有很多的防火牆產品聲稱可以防止Ddos攻擊,但是我個人使用感覺效果非常有限。
SQL隱碼攻擊
我們的官網使用的是PHP開發,因為框架比較老舊的原因,存在著一些SQL隱碼攻擊的點,我們發現了一些進行了修補,沒想到還是被一些黑客找到了突破點,這塊還是比較感謝這些黑客的在漏洞盒子上面提交了bug(如下圖),最後我們根據提示進行了緊急修復,後來我們也在WAF防火牆配置了一些攔截SQL隱碼攻擊的策略,起到雙保險的作用。
我一直在想為什麼PHP一般比較容易出現SQL隱碼攻擊呢,而Java較少的暴漏出來SQL漏洞的情況,我估摸著有兩方面的原因:第一,PHP一般會在前端使用的較多,受攻擊的機會更多一些,Java一般做為後端服務攻擊的可能性會比較少;第二,PHP框架較多而且很多早期的框架並沒有特別考慮SQL隱碼攻擊的情況,Java大量普及了mybaits\hibernate這種orm框架,框架本身對常見的SQL隱碼攻擊有防止的功能,但不是說mybaits/hibernate框架就沒有被sql注入的可能,大部分場景下是OK的。另外引數化查詢可以有效的避免SQL隱碼攻擊。
通過一段時間的學習,我發黑客一般先使用工具對網站做整體的掃描類似Acunetix,在根據掃描出來的漏洞做個大概的分析,但是比較深入的漏洞都需要根據網站的業務在進行調整,比如sql注入會根據頁面的查詢使用sqlmap等工具來進一步的滲透。當然我對這方面還是外行,描述的可能不夠清晰。
其它攻擊
其它方面的攻擊,主要是在業務方面,比如我們當初有一個很小的失誤,有一個程式設計師在H5的小網頁中將傳送簡訊驗證碼返回了前端,最後被haker發現了,利用這個漏洞可以給任意的使用者重置登入密碼;簡訊攻擊,現在的網站幾乎都有傳送簡訊或者簡訊驗證碼的功能,如果前端不做校驗,haker會隨便寫一個for迴圈來發簡訊,一般系統的簡訊會進行全方位的防控,比如:1、前端加驗證(字元驗證碼,有的是拖拽的動畫);2、後端根據使用者或者IP加限制,比如使用者一分鐘只可以傳送一條簡訊,忘記密碼的簡訊一天只能傳送10條、一個IP地址限制每天只能傳送100條簡訊等。
BUG
重複派息
15年的某一天看到一個新聞說是陸金所的一個使用者發現自己銀行裡面突然多了很多錢,沒過多久又被扣走了,然後收到陸金所那邊的解釋,說是給使用者還本派息的時候程式出現了問題導致還本派息兩次,當他們程式設計師發現了此問題後緊急進行了處理,使用者當然鬧了呀,就上了新聞,當然陸金所通道能力確實比較強可以直接從使用者卡里面扣,當大家都興致勃勃的談論這個話題的時候,我卻有一股淡淡的憂傷,為什麼呢?因為這個錯誤我們也犯過,具體說就是我搞的,大家可不知道當時的心裡壓力有多大!
事情是這樣子的,我們使用的第三方支付的扣款介面不是特別的穩定,於是我們前期就對接了兩種不通的扣款介面,平時前端投資的時候走一個介面,後端派息或者還本的時候走另外的一個介面,在初期的時候扣款介面不穩定,因此在給使用者跑批的時候經常會有個別使用者失敗,需要手動給失敗的使用者二次派息。做為一個有志向的程式設計師當然覺得這種方式是低效的,於是將程式改造了一下,在後端派息的時候當第一種扣款失敗的時候,自動再次呼叫第二種扣款介面進行扣款,當時想著這種方式挺好的,各個環境測試也沒有問題,上線之後監控過一段時間也執行穩定。
當我感覺一切都很美妙的時候,事故就來了,突然有一天客服反饋說有的使用者說自己收到的利息感覺不對,好像是多了(真的是太感謝這個使用者了),我登入後臺看了一下派息的流水複核了一遍,果然利息被重複派了,一股冷水從頭而下,把當天所有的使用者派息記錄和到期記錄都進行了檢查,影響了70多個使用者,導致多派息了6萬多元,幸虧只是派息出了問題,如果是到期的話金額會翻N倍,其中70多個人裡面有幾個進行了提現、幾個進行了再次投資,絕大部分使用者在我們發現的時候還不知情,金額也沒有動。
怎麼處理呢,當然不能直接就動使用者的錢了,給每個重複派息的使用者打電話,說明原因贈送小禮物,請求諒解後我們把重複派過的利息在次調回來。大部分使用者進行了核對之後都還是比較配合的,但是肯定有一些使用者不幹了,當然也不能怪客戶,都是我的原因,有的客戶需要上門賠禮道歉,有的客戶需要公司出具證明材料,我們的老闆親自給客戶打了N個電話被客戶罵了N遍,我心裡壓力可想而知,其中有一個客戶特別難纏,各種威脅說既然到了我的賬戶裡面肯定是我的,你們的失誤不應該讓他來承擔,折騰了很久,還是不能怪客戶。可能會說有的網際網路公司經常出現這種問題後就送給客戶了,哎,我們是小公司呀!這個噱頭玩不起。
到底是什麼原因呢,事後進行了覆盤也給領導做了彙報,平時都是首先進行派息的定時任務,過一個小時之後進行到期的定時任務,當天的派息標的比較多,跑了一個半小時,就導致了派息和到期的兩個定時任務同時進行,轉賬有了併發,第三方支付的介面不穩定給我們返回的失敗,其實有的是成功的,就導致了我們進行了二次的扣款嘗試引發了此問題。這個事情給我帶來了非常大的教訓,對於金融扣款的這種事情一定需要謹慎,哪怕付款引發報警之後在人工處理,也不能盲目重試可能引發雪崩效應。
雜七雜八
還有就是其它一些零碎的問題了,記的有一次對使用者的登入過程進行優化,導致有一塊判斷少了一個括號結果使用者在那兩個小時內,只要輸入賬戶,任意密碼就可以登入了,幸好及時發現這個問題,正是這個問題才導致了我們正式確立了規範的上線流程,為以後的上線制度建定了基礎。
還有一次我們在模擬使用者投資一種標的時候,留了一個入口通過http就可以呼叫,測試也沒有問題,有一天正好給領導演示呢,就在次用http請求的方式在瀏覽器執行了一下,前端就會看到自動投標的過程,因為生產的資料有點多,投標的過程有點長,我們為了加快進度,找了好幾個人同時來執行這http請求,導致最後出現了問題,最後發現寫測試指令碼的這個同事根本就沒有考慮併發的情況,才導致出現了問題。
也做了很多的活動,記得做一個網貸之家的一個活動的時候,活動上線比較緊張,我們團隊曾經連續工作超過30個小時(一天一夜再一天),當天晚上我2點左右寫完程式,測試從2兩點測試到早上9點,最終確認沒有任何問題,才進行投產。半夜公司沒有暖氣,我們實在凍的不行了,就在辦公室跑步,從這頭跑到那頭,第二天上線之後,又害怕出現問題,監控了一天,確認沒有任何問題,才到下午正常下班回家,那時候真是激情滿滿呀。
說到做活動肯定少了羊毛黨,說哪一家互金公司沒有遇到過羊毛黨那很少見,而且現在的羊毛黨規模簡直逆天了,我們使用者裡面就有一個羊毛黨在兩三天之內邀請了六七千位使用者,如果說邀請一個使用者送1元,那這個使用者就可以搞幾千塊一次,而且有很多專業的網站、QQ群、微信公共賬號都是他們的聚集地,那天那個平臺有活動門清,他們寫的淘羊毛操作手冊有時候比我們官網的幫助文件還清晰,所以做活動的時候要考慮特別周全,各種限制,有封定、有預案、講誠信,只要是符合我們活動規則的堅決按照流程走。
還有一個有趣的事情,app推送,一次我在公交車上就看到xx盒子app彈出hhhhh的推送,這個事情我們也搞過,因為在除錯的時候生產和測試就差了一個引數,有時候開發人員不注意就把生產引數部署到uat環境了,測試一傳送就跑到生產了,這方面只能嚴格流產管理來防止了。
其實還很多問題:mongodb叢集和mysql的同步出現的一些狀況、後臺大量資料查詢下的sql優化、golang使用mapreduce碰到的問題… 限於篇幅這裡就不一一清晰的描述了。
其實每次的出現問題都是對團隊一次非常好的鍛鍊機會,通過發現問題,定位問題,解決問題,再次回過頭來反思這些問題;重新梳理整個環節, 舉一反三避免下次再次出現類似的問題。正是因為經歷這些種種的困難、考驗才讓團隊變的更強大更穩定,也更體現了流程的重要性,更是避免再次發生類似問題。
總結
古代對將軍的要求是,心有萬馬奔騰而過,而面平靜如湖水可照鏡,在網際網路行業對大牛的要求也同如此,特別是技術的負責人,在面對生產事故的時候,一定首先是安撫同事,靜下下心來找到問題本質在去解決,而不是不斷去施加壓力催促解決,重壓之下很多心裡承受能力稍弱的隊友,更加慌亂而不利於解決問題或者引發二次事故。
在看淘寶雙十一視訊中,有一段特別受到感觸,在雙十一初期,雖然技術團隊做了很多的準備,但是在零點過後流量瞬間湧入,服務被打垮,部分使用者投訴重新整理不出網頁,緊接著隔壁同事也都反饋網站打不開,在大家都在慌亂中,xx一拍桌子大喊一聲,大家都別動,三分鐘之後再說,過了幾分鐘之後服務慢慢部分恢復了正常。後來回憶說,當時雖然服務癱瘓,但是監控還是有部分得業務成功,說明系統並沒有被壓垮,而此時的任何操作都有可能引發更大的問題,從此之後此人一戰成名,成為阿里大將。
網際網路平臺發展大抵都會經歷三個階段:
- 1、上線初期,此階段問題最為繁多,生產事故不斷,系統快速迭代優化。有人說為什麼不測試到完全沒有問題在投產嗎?說實話在網際網路行業這個很難,第一小公司很難做到生產環境和測試環境一致,成本太高;時間緊迫,一般都是很短的時間內要求上線,上線之後在快速迭代。另外網際網路本就是一個快速試錯的行業,錯過半年時間可能風口早過;
- 2、發展期,此階段主要業務模式已經得到驗證,系統出現問題的頻繁度較少,低階錯誤減少,但此時是使用者量和交易量不斷爆發的時候,對系統效能、高併發的要求又上來了,所以此時出現的問題大多都是效能的問題;
- 3、成熟期,發展期過後系統相對比較平穩,使用者量和交易量都已經慢慢穩定下來,生產問題越來越少,出現問題幾乎都是細小的bug,這個階段也是公司最忽略技術得階段,恰好我們公司就處於這個階段,在這個階段就需要靜下心裡,組織架構升級,補齊在初期和發展起所欠的技術債務,做好公司在升下一個量級的技術準備。
所有的這些問題幾乎都集中在14年底到15年初的這個階段,15年後半年開始到現在平臺慢慢穩定了下來,到現在幾乎沒有再出現過類似的問題,也因為幾乎都是兩年前的事情,有很多記的不是特別清楚了,寫的比較粗糙望見諒。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式