《看運維如何拯救一個百億互金平臺》要點:
本文介紹了看運維如何拯救一個百億互金平臺,希望對您有用。如果有疑問,可以聯系我們。
多年前,又是周六客服打電話過來,平臺官網不能訪問,app完全無法打開,客戶在QQ群和微信群中各種反饋,說平臺是不是跑路了?客服的多條400熱線完全被打爆,電話已經接不過來…
一直以來總是想以什么方式去記錄下自己在互聯網金融行業的這段經歷,趁著自己還記得清楚,還能找到一些資料原型,一方面可以分享出來供大家參考,但是更重要就是多年以后可以根據這些文章回憶起自己的那段激情歲月.
想了很久但一直沒有實施,后來覺得應該從架構的角度來梳理一篇文章,就寫了《從零到百億互聯網金融架構發展史》(http://t.cn/RMSnjub)這篇文章;
最后認為只有實戰出來的東西和解決問題的過程,才是工作中最寶貴的經驗,應該把它分享出來,在梳理的過程中覺得有三起事故比較有代表性就整理出了下面這三篇文章,本篇文章從整體來回憶一下一路走過來所經歷過的救火故事.
作為一個互聯網金融平臺,涉及到用戶資金,任何的服務(資金)差錯用戶都是不可容忍的,用戶不懂什么是數據庫,不管你什么網絡不通,哪怕只是一小會兒,看不到錢在 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 攻擊我們也遇到了很多次,確實沒有比較好的辦法,最后都是通過一些笨辦法來盡量避免的,先說說我們的經歷吧.
有一次我正在敲代碼,客服 QQ 又閃爍了起來,還沒來得及打開查看,客服的經理就直接打電話過來了,我立刻一種不祥的預感,他說官網打不開了,后臺也登錄不了.
掛了電話,我在本機進行了測試,果然不行,立刻準備登錄 VPN 查看服務器各項指標,結果登錄不上去,馬上上樓找運維經理,他也登錄不上,剛準備給機房打電話的時候,機房來電話了,說我們的一個 IP 正經歷著 1G 多的流量訪問,問我們是否正在做什么活動,話沒說完,就又說流量已經到 5G,不到一分鐘之后流量已經到達 18G 之多.
因為我們的機房和集團公用了一個入口,結果集團上面陸續反饋他們的網站、服務也都出現了問題,機房方面害怕引起更大的沖擊,直接把我們官網對外的IP封掉了,集團的其它業務才慢慢恢復了過來,我們也緊急更換了外網IP,重新切換了域名解析后才恢復.
事后我們根據 Apache 分析了日志,流量來自N多個不同的IP地址根本無法應對,也是因為這次攻擊,我們領導重視了起來,將我們公司的機房網絡層和公司集團徹底分離.這樣不管哪一方受到大流量攻擊都不會相互影響.
當然我們也想了一些笨辦法,因為上次我們更換了外網 IP 之后攻擊也就停止了.那么我們認為肯定是針對我們外網來的,所有我們就準備了多個外網 IP,當監控到某一個外網IP被攻擊時,馬上切換到另一個外網IP,這樣可以起到非常有限的一點作用,因為如果黑客真的想跟我們玩,這個辦法就像是小孩子捉迷藏.
還有一次我們正在做周年慶活動,突然有人在 QQ 群里面給我們客服說:叫你們的技術負責人來找我.然后我們的網站就掛了,我還保留了當時的一個截圖如下:
黑客:你是平臺的技術負責人嗎?
我:算是吧
黑客:你信不信我可以讓你們官網在5秒之內掛掉?
我:…(沉默,還真害怕又把官網搞掛了)
黑客:你們的官網漏洞很大
我:如果有好的建議請您賜教
黑客:你們的服務器是不是什么防護軟件都沒有裝?
我:…(繼續沉默,這會在想不會是那個安全廠商來推廣產品的吧,當然我們基礎的防護肯定有)
黑客:我們有非常多的肉雞,想攻擊誰,幾秒之內肯定搞定
我:…
黑客:我們已經給很多互聯網金融行業做了滲透測試,花點錢幫你們擺平,保證以后不會再出事情
我:…
黑客:免費的策略也有很多,比如 360、百度云的安全產品可以免費抵擋10G 左右的流量……(中間省略)
黑客:我說了這多,你們是不是給包煙錢,表示表示?
……
后來也和領導進行了商議,堅決不能給他們錢,不能助長這種囂張氣焰,實在不行就報警!
曝光一下當年使用的假 QQ 號,剛查了下變了個頭像和描述,如下:
后來我一直在想:為什么 DDOS 攻擊總是喜歡根據外網 IP 來攻擊呢?后來慢慢有些理解了,如果針對域名來攻擊的話,那不就是攻擊到域名商的服務器了嗎?而一般域名商比較強大,黑客不太搞的定,也確實沒有必要.
當然記的前一段時間,某著名域名服務商被攻擊,導致國外 Twitter 等著名的互聯網公司訪問中斷達半天以上,還是很嚴重的.但是對于我們這樣的小公司,倒不至于搞這么大的動作.
那到底如何正確的防止 DDOS 攻擊?根據我的個人經驗總結了幾條:
- 第一種方案:隱藏服務器外網地址,服務器前端加 CDN 中轉,免費的有百度云加速、360網站衛士、加速樂、安全寶等,如果資金充裕的話,可以購買高防盾機,用于隱藏服務器真實 IP,域名解析使用 CDN 的 IP,所有解析的子域名都使用 CDN 的 IP 地址.
此外,服務器上部署的其他域名也不能使用真實IP解析,全部都使用CDN來解析;- 第二種方案,買一些安全產品來進行流量清洗,主要是阿里云、騰訊云這種大廠商提供的服務.
- 第三種方案,有很多的防火墻產品聲稱可以防止 DDOS 攻擊,但是我個人使用感覺效果非常有限.
我們的官網使用的是 PHP 開發,因為框架比較老舊的原因,存在著一些 SQL 注入的點,我們發現后進行了修補,沒想到還是被一些黑客找到了突破點.
這里要感謝這些黑客在漏洞盒子上提交的 Bug (如下圖),最后我們根據提示進行了緊急修復,后來我們也在 WAF 防火墻配置了一些攔截 SQL 注入的策略,起到雙保險的作用.
我一直在想為什么 PHP 一般比較容易出現 SQL 注入,而 Java 較少呢?我估摸著有兩方面的原因:
通過一段時間的學習,我發現,黑客一般先使用工具對網站做整體的掃描,類似 Acunetix,再根據掃描出來的漏洞做個大概的分析,但是比較深入的漏洞都需要根據網站的業務再進行調整,比如 SQL 注入會根據頁面的查詢使用 sqlmap 等工具來進一步的滲透.當然我對這方面還是外行,描述的不夠清晰.
其它方面的攻擊,主要是在業務方面,比如我們當初有一個很小的失誤,有一個程序員在 H5 的網頁中將發送短信驗證碼返回了前端,最后被黑客發現了,利用這個漏洞可以給任意的用戶重置登錄密碼;
短信攻擊,現在的網站幾乎都有發送短信或者短信驗證碼的功能,如果前端不做校驗,黑客會隨便寫一個 for 循環來發短信,一般系統的短信會進行全方位的防控,比如:
2015年的某一天看到一個新聞說是陸金所的一個用戶發現自己銀行里面突然多了很多錢,沒過多久又被扣走了,然后收到陸金所那邊的解釋,說是給用戶還本派息的時候程序出現了問題導致還本派息兩次.
當他們程序員發現了此問題后緊急進行了處理,用戶當然鬧了,也上了新聞,當然陸金所通道能力確實比較強可以直接從用戶卡里面扣,當大家都興致勃勃的談論這個話題的時候,我卻有一股淡淡的憂傷,為什么呢?
因為這個錯誤我們也犯過,具體說就是我搞的,大家不知道我當時的心里壓力有多大!
事情是這樣子的:我們使用的第三方支付的扣款接口不是特別的穩定,于是我們前期就對接了兩種不同的扣款接口,平時前端投資的時候走一個接口,后端派息或者還本的時候走另外的一個接口,在初期的時候扣款接口不穩定,因此在給用戶派息的時候經常會有個別用戶失敗,需要手動給失敗的用戶二次派息.
做為一個有志向的程序員當然覺得這種方式是低效的,于是將程序改造了一下,在后端派息的時候當第一種扣款失敗的時候,自動再次調用第二種扣款接口進行扣款,當時想著這種方式挺好的,各個環境測試也沒有問題,上線之后監控過一段時間也運行穩定.
當感覺一切都很美妙的時候,事故就來了,突然有一天,客服反饋說,有的用戶說自己收到的利息感覺不對,好像是多了(真的是太感謝這個用戶了),我登錄后臺看了一下派息的流水,復核了一遍,果然利息被重復派了,感覺一盆冷水從頭而下.
我把當天所有的用戶派息記錄和到期記錄都進行了檢查,發現影響了70多個用戶,導致多派息了6萬多元,幸虧只是派息出了問題,如果是到期的話,金額會翻N倍,其中70多個人里面有幾個進行了提現、幾個進行了再次投資,絕大部分用戶在我們發現的時候還不知情,金額也沒有動.
怎么處理呢,當然不能直接就動用戶的錢了,只能給每個重復派息的用戶打電話,說明原因并贈送小禮物,請求諒解后,我們把重復派過的利息再次調回來.
大部分用戶進行了核對之后都還是比較配合的,當然肯定有一些用戶不干了,但你也不能怪客戶,因為都是我的原因.有的客戶需要上門賠禮道歉,有的客戶需要公司出具證明材料,我們的老板還親自給客戶打了N個電話,被客戶罵了N遍,我心里壓力可想而知.
其中有一個客戶特別難纏,各種威脅,說既然到了我的賬戶里面,肯定是我的,你們的失誤不應該讓我來承擔,折騰了很久,還是不能怪客戶.
你可能會說有的互聯網公司經常出現這種問題后就送給客戶了,哎,可是我們是小公司呀!這個噱頭玩不起.
到底是什么原因呢,事后進行了復盤也給領導做了匯報:平時都是首先進行派息的定時任務,過一個小時之后進行到期的定時任務,當天的派息標的比較多,跑了一個半小時,就導致了派息和到期的兩個定時任務同時進行,轉賬有了并發,第三方支付的接口不穩定,給我們返回失敗,其實有的是成功的,就導致了我們進行了二次的扣款嘗試,引發了此問題.
這個事情給我帶來了非常大的教訓,對于金融扣款的這種事情一定需要謹慎,哪怕付款引發報警之后再人工處理,也不能盲目重試,極有可能引發雪崩效應.
還有就是其它一些零碎的問題了,記的有一次對用戶的登錄過程進行優化,導致有一塊判斷少了一個括號,結果用戶在那兩個小時內,只要輸入賬戶,任意密碼就可以登錄了,幸好及時發現這個問題,正是這個問題才導致了我們正式確立了規范的上線流程,為以后的上線制度奠定了基礎.
還有一次我們在模擬用戶投資一種標的時候,留了一個入口通過 http 就可以調用,測試也沒有問題,有一天正好給領導演示呢,就再次用 http 請求的方式在瀏覽器執行了一下,前端就會看到自動投標的過程.
因為生產的數據有點多,投標的過程有點長,我們為了加快進度,找了好幾個人同時來執行這個 http 請求,導致最后出現了問題,最后發現寫測試腳本的這個同事根本就沒有考慮并發的情況,才導致出現了問題.
也做了很多的活動,記得做一個網貸之家的一個活動的時候,活動上線比較緊張,我們團隊曾經連續工作超過30個小時(一天一夜再一天),當天晚上我2點左右寫完程序,測試從2兩點測試到早上9點,最終確認沒有任何問題,才進行投產.
半夜公司沒有暖氣,我們實在凍的不行了,就在辦公室跑步,從這頭跑到那頭,第二天上線之后,又害怕出現問題,監控了一天,確認沒有任何問題,才到下午正常下班回家,那時候真是激情滿滿呀.
說到做活動肯定少不了羊毛黨,哪一家互金公司沒有遇到過羊毛黨?而且現在的羊毛黨規模簡直逆天了,我們用戶里面就有一個羊毛黨在兩三天之內邀請了六七千位用戶,如果邀請一個用戶送1元,那這個用戶就可以搞幾千塊一次.
而且有很多專業的網站、QQ群、微信公共賬號都是他們的聚集地,那天那個平臺有活動門清,他們寫的淘羊毛操作手冊有時候比我們官網的幫助文檔還清晰,所以做活動的時候要考慮特別周全,各種限制,有封定、有預案、講誠信,只要是符合我們活動規則的堅決按照流程走.
還有一個有趣的事情,是App 推送,一次我在公交車上就看到某盒子 App 彈出 XXX 的推送,這個事情我們也搞過,因為在調試的時候生產和測試就差了一個參數,有時候開發人員不注意就把生產參數部署到 uat 環境了,測試一發送就跑到生產了,這方面只能嚴格流程管理來防止了.
其實還很多問題:mongodb 集群和 mysql 的同步出現的狀況、后臺大量數據查詢下的 sql 優化、golang 使用 mapreduce 碰到的問題… 限于篇幅這里就不一一描述了.
其實每次出現問題都是對團隊一次非常好的鍛煉機會,通過發現問題,定位問題,解決問題,再次回過頭來反思這些問題,重新梳理整個環節, 舉一反三避免下次再次出現類似的問題.
正是因為經歷這種種的困難、考驗才讓團隊變的更強大、更穩定,也更體現了流程的重要性,更避免了再次發生類似問題.
古代對將軍的要求是,心有萬馬奔騰,面如湖水平靜,在互聯網行業,對領導的要求也如此,特別是技術負責人,在面對生產事故的時候,一定是先安撫同事,靜下心來找到問題本質,再去解決,而不應該不斷去施加壓力催促,重壓之下很多心里承受能力稍弱的隊友,會更加慌亂,不但不利于解決問題,還可能引發二次事故.
在看淘寶雙十一視頻中,有一段感受特別深,在雙十一初期,雖然技術團隊做了很多的準備,但是在零點過后流量瞬間涌入,服務被打垮,部分用戶投訴刷新不出網頁,緊接著隔壁同事也都反饋網站打不開,在大家都在慌亂中,XX一拍桌子大喊一聲,大家都別動,三分鐘之后再說,過了幾分鐘之后服務慢慢恢復了正常.
后來回憶說,當時雖然服務癱瘓,但是監控到有部分業務成功,說明系統并沒有被壓垮,而此時的任何操作都有可能引發更大的問題,從此之后此人一戰成名,成為阿里大將.
互聯網平臺發展大抵都會經歷三個階段:
第一,小公司很難做到生產環境和測試環境一致,成本太高;
第二,時間緊迫,一般都是很短的時間內要求上線,上線之后再快速迭代;
第三,互聯網本就是一個快速試錯的行業,錯過半年時間可能風口早過;
所有的這些問題幾乎都集中在14年底到15年初的這個階段,15年后半年開始到現在,平臺慢慢穩定了下來,到現在幾乎沒有再出現過類似的問題,也因為幾乎都是兩年前的事情,有很多記的不是特別清楚了,寫的比較粗糙望見諒.
本文轉載于:http://www.ityouknow.com/
作者:純潔的微笑
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4335.html