歡迎你們前往騰訊雲技術社區,獲取更多騰訊海量技術實踐乾貨哦~
前端
做者: 林喜東
人與人之間最重要的是信任,但程序的世界裏,可能信任越少越好;我愈加以爲越是高性能高可用的系統裏,不信任原則會體現得更加淋漓盡致。 爲了少走彎路,寫下這篇文章留給本身參考,其中一些是本身踩過的一些坑;一些是接手他人系統時觸過的雷;還有一些是從別人分享的經驗學習得來;能力有限,先記下本身的一些體會,錯誤的地方再慢慢改正。程序員
編程,是一件容易的事,也是一件不容易的事。說它容易,是由於掌握一些基本的數據類型和條件語句,就能夠實現複雜的邏輯;說它不容易,是由於高性能高可用的代碼,須要瞭解的知識有不少不少;編程的世界,也跟掃雷遊戲的世界同樣,充滿雷區,十面埋伏,一不當心,隨時均可能踩雷,隨時均可能Game Over。算法
而玩過掃雷的人都知道,避免踩雷的最好方法,就是提早識別雷區並作標記(設防)避免踩踏。sql
鑑於此,編程的世界裏,從輸入到輸出一樣須要到處設防,步步爲營。編程
(1)對空指針的檢查後端
不僅是輸入,只有是使用到指針的地方,都應該先判斷指針是否爲NULL,而內存釋放後,應當將指針設置爲NULL。安全
【真實案例】:註冊系統某段邏輯,正常使用狀況下,都有對指針作檢查,在某個錯誤分支,打印日誌時,沒檢查就使用了該字符串;結果可正常運行,但當訪問某個依賴模塊超時走到改分支,觸發bug,致使coredump。網絡
(2)對數據長度的檢查xss
使用字符串或某段buf,特別是memcpy/strcpy時,須要儘可能對數據長度作下檢查和截斷。性能
【真實案例】:接手oauth系統後運行數月表現良好,忽然有一天,發生了coredump,經查,是某個業務不按規定請求包中填寫了超長長度,致使memcpy時發生段錯誤,根本緣由,仍是沒有作好長度檢查。
(3)對數據內容的檢查
某些場景下,沒有對數據內容作檢查就直接使用,可能致使意想不到的結果。
【案例】:sql 注入和 xss 攻擊都是利用了服務端沒有對數據內容作檢查的漏洞。
變動的影響通常體如今輸出,有時候輸出的結果並不能簡單的判斷是否正常,如輸出是加密信息,或者輸出的內容過於複雜。
因此,對於每次變動
(1)修改代碼時,採用不信任編碼,正確的不必定是「對」的,再小的修改也應確認其對後續邏輯的影響,有些修正可能改變原來錯誤時的輸出,而輸出的改變,就會影響到依賴該改變字段的業務。
(2)發佈前,應該對涉及到的場景進行測試和驗證,測試能夠有效的發現潛在的問題,這是衆所周知的。
(3)發佈過程,應該採用灰度發佈策略,由於測試並不是老是能發現問題,灰度發佈,能夠減小事故影響的範圍。常見灰度發佈的策略有機器灰度、IP灰度、用戶灰度、按比例灰度等,各有優缺點,須要根據具體場景選擇,甚至能夠同時採用多種的組合。
(4)發佈後,全面監控是有效發現問題的一種方法。由於測試環境和正式環境可能存在不一致的地方,也可能測試不夠完整,致使上線後有問題,因此需採起措施補救
A:如使用Monitor監控請求量、成功量、失敗量、關鍵節點等
B:使用DLP告警監控成功率
C:發佈完,在正式環境測試一遍
【案例】oauth系統某次修改後編譯時,發現有個修改不相關的局部變量未初始化的告警,出於習慣對變量進行了初始化(初始化值和編譯器默認賦值不同),而包頭某個字段採用了該未初始化的變量,但在測試用例中未能體現,監控也沒細化到每一個字段的值,致使測試正常,監控正常;但前端業務齊齊互動使用了該包頭字段,致使發佈後影響該業務。
通常的系統,都會有上下游的存在,正以下圖所示
而上下游的整個鏈路中,每一個點都是不能保證絕對可靠的,任何一個點均可能隨時發生故障,讓你措手不及。
所以,不能信任整個鏈路中的任何一個點,需進行設防。
主要措施以下:
(1)服務監控
前面所述的請求量、成功量、失敗量、關鍵節點、成功率的監控,都是對服務環節的單點監控。
在此基礎上,能夠加上自動化測試,自動化測試能夠模擬應用場景,實現對於流程的監控。
(2)進程秒起
人可能在程序世界裏是不可靠的因素(大牛除外),前面的措施,可能是依賴人來保證的;因此,coredump仍是有可能發生的,這時,進程秒起的實現,就能夠有效減小coredump的影響,繼續對外提供服務。
可採用柔性可用策略,對於根據模塊的不可或缺性,區分關鍵路徑和非關鍵路徑,並採起不一樣的策略
(1)對於非關鍵路徑,採用柔性放過策略
當訪問非關鍵路徑超時時,簡單的可採起有限制(必定數量、必定比重)的重試,結果超時則跳過該邏輯,進行下一步;複雜一點的統計一下超時的比例,當比例太高時,則跳過該邏輯,進行下一步
(2)對於關鍵路徑,提供弱化服務的柔性策略
關鍵路徑是不可或缺的服務,不能跳過;某些場景,能夠根據目的,在關鍵路徑嚴重不可用時,提供弱化版的服務。舉例如派票系統訪問票據存儲信息嚴重不可用時,可提供不依賴於存儲的純算法票據,爲彌補安全性的確實,可採起縮短票據有效期等措施。
(1)對請求來源的不信任
有利可圖的地方,就會有黑產時刻盯着,僞造各類請求,對此,可採起以下措施
A:權限控制
如ip鑑權、模塊鑑權、白名單、用戶登陸態校驗等
B:安全審計
權限控制僅能打擊一下非正常流程的請求,但壞人常常可以成功模擬用戶正常使用的場景;因此,對於一些重要場景,須要加入安全策略,打擊如IP、號碼等信息彙集,頻率過快等機器行爲,請求重放、劫持等請求)
(2)對請求量的不信任
前端的請求,不老是平穩的;有活動時,會暴漲;前端業務故障恢復後,也可能暴漲;前端遭到惡意攻擊時,也可能暴漲;一旦請求量超過系統負載,將會發生雪崩,最終致使整個服務不可用,對此種種突發狀況,後端服務須要有應對措施
A:頻率限制,控制各個業務的最大請求量(業務根據正常請求峯值的2-3倍申請,該值可修改),避免因一個業務暴漲影響全部業務的狀況發生。
B:過載保護,雖然有頻率限制,但業務過多時,依然有可能某個時間點,全部的請求超過了系統負載,或者到某個IDC,某臺機器的請求超過負載,爲避免這種狀況下發生雪崩,將超過必定時間的請求丟棄,僅處理部分有效的請求,使得系統對外表現爲部分可用,而非徹底不可用。
機器故障時有發生,若是服務存在單點問題,故障時,則服務將徹底不可用,而依賴人工的恢復是不可預期的,對此,可經過如下措施解決
(1)容災部署
即至少有兩臺以上的機器能夠隨時對外提供服務。
(2)心跳探測
用於監控機器是否可用,當機器不可用時,若涉及到主備機器的,應作好主備機器的自動切換;若不涉及到主備的,禁用故障機器對外提供服務便可。
現實生活中,整個機房不可用也是有發生過的,如2015年的天津濱海新區爆炸事故,致使騰訊在天津的多個機房不能對外提供正常服務,對此採起的措施有:
(1)異地部署
不一樣IDC、不一樣城市、不一樣國家等部署,可用避免整個機房不可用時,有其餘機房的機器能夠對外提供服務
(2)容量冗餘
對於相似QQ登錄這種入口型的系統,必須保持兩倍以上的冗餘;如此,能夠保證當有一個機房故障時,全部請求遷移到其餘機房不會引起系統過載。
雖然咱們愈來愈離不開電力,但電力卻不能保證一直在爲咱們提供服務。斷電時,其影響和機器故障、機房故障相似,機器會關機,數據會丟失,因此,須要對數據進行備份。
(1)磁盤備份
來電後,機器重啓,能夠從磁盤中恢復數據,但可能會有部分數據丟失。
(2)遠程備份
機器磁盤壞了,磁盤的數據會丟失,使用對於重要系統,相關數據應當考慮採用遠程備份。
(1)不一樣地方,網絡時延不同
通常來講,本地就近的機器,時延要好於異地的機器, 因此,比較簡單的作法就是近尋址,如CMLB。
也有部分狀況,是異地服務的時延要好於本地服務的時延,因此,若是要作到較好的最優路徑尋址,就須要先作網絡探測,如Q調
(2)常有網絡有波動或不可用狀況
和機器故障同樣處理,應當作到自動禁用;但網絡故障和機器故障又不同,常常存在某臺機器不可用,但別的機器能夠訪問的狀況,這時就不能在服務端禁用機器了,而應當採用本地回包統計策略,自動禁用服務差機器;同時需配合定時探測禁用機器策略,自動恢復可正常提供服務機器。
人的因素在運營的世界裏實際上是不穩定的因素(大牛除外),因此,不能對人的操做有過多的信任。
(1)操做備份
每一步操做都有記錄,便於發生問題時的回溯,重要的操做須要review,避免我的考慮不周致使事故。
(2)效果確認
實際環境每每和測試環境是存在一些差別,全部在正式環境作變動後,應經過視圖review和驗證來確認是否符合預期。
(3)變動可回滾
操做前需對舊程序、舊配置等作好備份,以便發生故障時,及時恢復服務。
(4)自動化部署
機器的部署,可能有一堆複雜的流程,如各類權限申請,各類客戶端安裝等,僅靠文檔流程操做加上測試驗證時不夠的,可能某次部署漏了某個步驟而測試又沒測到,上線後就可能發生事故若能全部流程實現自動化,則可有效避免這類問題。
(5)一致性檢查
現網的發佈可能因某個節點沒同步致使漏發,也就是不一樣的機器服務不同;對此,有版本號的,可經過版本號監控發現;沒版本號的,則需藉助進程、配置等的一致性檢查來發現問題。
備註:以上提到的不信任策略,有的不能簡單的單條使用,須要結合其餘的措施一塊兒使用的。
好了,先寫這麼多。最重要的仍是那句話,程序的世界裏,應該堅持不信任原則,到處設防。
程序員的江湖:從黑木崖到回龍觀
手工完成自建遷移_from RDS to CDB
理解 JDK 中的 MethodHandle
此文已由做者受權騰訊雲技術社區發佈,轉載請註明文章出處
原文連接:cloud.tencent.com/community/a…