主頁 > 軟體設計 > 架構設計手冊

架構設計手冊

2021-10-10 07:58:34 軟體設計

架構設計參考手冊

  • 系統設計的一些原則
    • 在設計系統時,應該多思考墨菲定律
    • 在系統劃分時,也要思考康威定律
    • 高并發原則
    • 高可用原則
    • 業務設計原則
    • 總結
  • 負載均衡與反向代理
    • Nginx負載均衡演算法
    • 失敗重試
    • 健康檢查
    • 備份上游服務器
    • 不可用上游服務器
  • 隔離
    • 執行緒隔離
    • 行程隔離
    • 集群隔離
    • 機房隔離
    • 讀寫隔離
    • 動靜隔離
    • 爬蟲隔離
    • 熱點隔離
    • 資源隔離
    • 使用Hystrix實作隔離
  • 限流詳解
    • 限流演算法
    • 應用級限流
    • 分布式限流
    • 接入層限流
  • 降級
    • 降級預案
    • 自動開關降級
    • 人工開關降級
  • 超時與重試機制
    • 代理層超時與重試
    • web容器超時
    • 資料庫 | NoSql連接超時
    • 業務超時
  • 回滾機制
    • 事務回滾
    • 代碼回滾
    • 部署版本回滾
    • 資料版本回滾
    • 靜態資源版本回滾
  • 壓測與預案
    • 系統壓測
  • 應用級快取
    • 快取命中率
    • 快取回收策略
  • 多級快取
  • 連接池執行緒池
  • 佇列
    • 應用場景
    • 任務佇列
    • 訊息佇列
    • 請求佇列
    • 資料總線佇列

系統設計的一些原則

在設計系統時,應該多思考墨菲定律

  • 任何事情都沒有表面看起來那么簡單
  • 所有的事情都會比你預計的時間?
  • 可能會出錯的事一定會出錯
  • 如果你擔心某種情況發生,那么它就更有可能發生

在系統劃分時,也要思考康威定律

  • 系統架構是公司組織架構的反映
  • 應該按照業務倍訓進行系統拆分/組織架構劃分,實作倍訓/高內聚/低耦合,減少溝通成本
  • 如果溝通出現問題,那么就應該考慮進行系統和組織架構的調整
  • 在合適時機進行系統拆分,不要一開始就把系統/服務拆得非常細,雖然倍訓,但是每個人維護的系統多,維護成本高

高并發原則

  • 無狀態

    如果設計的應該是無狀態的,那么應用比較容易進行水平擴展,實際生產環境可能是這樣的:應用無狀態,組態檔有狀態,比如,不同的機房需要讀取不同的資料源,此時,就需要通過組態檔或配置中心指定,

  • 拆分

    在系統設計初期,是做一個大而全的系統還是按功能模塊拆分系統,這個需要根據環境進行權衡,

  • 服務化

    總結為:行程內服務—>單價遠程服務—>集群手動注冊服務—>自動注冊和發現服務—>服務的分組/隔離/路由—>服務治理 如限流/黑白明白,服務降級

  • 訊息佇列

    訊息佇列是用來解耦一些不需要同步呼叫的服務或者訂閱一些自己系統的變化,使 用訊息佇列可以實作服務解耦(一對多消費)、異步處理、流量削峰/緩沖等,但是訂 閱者太多,那么訂閱單個訊息佇列就會成為瓶頸,此時需要考慮對訊息佇列進行多個鏡 像復制,

    使用訊息佇列時,需要注冊生產訊息失敗,以及訊息重復接收時的場景,有些訊息 佇列產品會提供生產重試功能,在達到指定重試次數還未生產成功時,會對外通知生產 失敗,這對于不能容忍生產失敗的業務場景來說,一定要做好后續的資料處理作業,比 如持久化資料同時要增加日志、報警等,或者在生產失敗后發送http請求來保證成功, 還有訊息重復問題,特別是一些分布式訊息佇列,出于對性能和開銷的考慮,在一些場 景下會發送訊息重復接收,需要在代碼層面進行防重處理,

  • 資料異構

    資料異構:訂單分庫分表一般按照訂單ID進行分,如果要查詢某個用戶的訂單串列,則需要聚 合多個表的資料才能回傳,這樣會導致訂單表的讀性能很低,此時需要對訂單表進行異 構,異構一套用戶訂單表,按照用戶ID進行分庫分表,另外,還需要考慮對歷史訂單數 據進行歸檔處理,以提升服務的性能和穩定性,而有些資料異構的意義不大,如庫存架 構,可以考慮異步加載,或者合并并發請求,

    資料倍訓:資料倍訓如用戶的聊天記錄,因為資料來源太多,影響服務穩定性的因素就非常多了,因此,最好的辦法是把使用到的資料進行異構存盤,形成資料倍訓,基本步驟如下:
    1: 資料異構:通過MQ機制接收資料的變更,然后原子化存盤到合適的存盤引擎,如 redis,Elasticsearch等,

    2:資料聚合:這步是可選的,資料異構的目的是把資料從多個資料源拿過來,資料聚 合的目的是把這些資料做個聚合,這樣前端可以一次請求拿到所有資料,此步驟一般存 儲到KV存盤中

    3:前端通過一次或少量幾次請求拿到所需要的資料,
    這種方式的好處就是資料的倍訓,任何依賴的系統出問題了,還是能正常作業,只是更新會有積壓,單是不影響前端展示,

    資料倍訓和資料異構其實是一個概念,目的都是實作資料的自我控制,當其他系統 出現問題時不影響自己的系統,或者自己出問題時不影響其他系統,一般通過MQ來實 現資料分發,

  • 快取銀彈

    快取對讀服務來說,是扛流量的銀彈,可總結為下表:

    在這里插入圖片描述

高可用原則

  • 降級

    對于一個高可用服務,很重要的一個設計就是降級開關,在設計降級開關時,主要依據如下思路:

    1:開關集中化管理:通過推送機制把開關推送到各個應用,
    在這里插入圖片描述

    2:可降級的多級讀服務:比如服務呼叫降級為只讀本地快取、只讀NoSql快取 、只讀 默認降級資料
    在這里插入圖片描述
    3:開關前置化: 如架構是Nginx—>Apache,可以將開關前置到Nginx接入層,在Nginx 層做開關,請求流量匯源后端應用或者只是一小部分流量回源

    4:業務降級:當高并發流量來襲,保證核心業務是正常的,并保障資料最終一致性即 可,這樣就把一些同步呼叫改成異步呼叫,優先處理高優先級資料或特殊特征的資料,合 理分配進入系統的流量,以保障系統可用,

  • 限流

    限流的目的是防止惡意請求流量,惡意攻擊,或者防止流量超出系統峰值,思路如下:

    1:惡意請求只訪問到cache
    2:對于穿透到后端應用的流量可用考慮使用Nginx的limit模塊處理
    3:對于惡意IP可以使用nginx deny進行屏蔽

    原則是限制流量穿透到后端薄弱的應用層

業務設計原則

  • 防重設計

    例如,結算需要考慮重復提交,還有扣減庫存時需要防止重復扣減庫存,解決方案可以考慮防重key、防重表,

  • 冪等設計

    在交易系統,經常會用到訊息,而現有訊息中間件基本不保證不發生重復訊息的訊息,因此,需要業務系統在重復訊息消費時進行冪等處理,還有在使用第三方支付時,第三方支付會進行異步回呼,也要考慮回呼的冪等處理,

  • 流程可定義

  • .狀態與狀態機

  • 后臺系統操作可反饋

  • 后臺系統審批化

  • 檔案和注釋

  • 備份

總結

一個系統的設計,不僅需要考慮實作業務功能,還要保證系統高并發、高可用等,在系 統容量規劃(流量、容量等)、SLA制定(吞吐量、回應時間、可用性、降級方案等)、 壓測方案(線上、test等)、監控報警(機器負載、回應時間、可用率等)、應急預案(容 災、降級、限流、隔離、切流量、可回滾)等方面,也要有一些原則來進行設計,

在這里插入圖片描述
在這里插入圖片描述

負載均衡與反向代理

當我們的應用單實體不能支撐用戶請求時,此時就需要擴容,從一臺服務器擴容到兩 臺,幾十臺,上百臺,甚至更多,然后用戶訪問是通過一個域名的方式訪問,在請求時, 瀏覽器首先會查詢DNS服務器獲取對應IP,然后通過此IP訪問對應服務,

因此一種方式是將域名決議到多個IP,但是存在一個簡單的問題,假設某臺服務重啟或 者出現故障,DNS會有一定的快取時間,故障切換時間?,而且沒有對后端服務進行心跳 檢查和失敗重試的機制,

因此,外網DNS應該用來實作GSLB(全域負載均衡)進行流量調度,如將用戶分配到離他最近的服務器上以提升體驗,而且當某一區域的機房出現問題時(如斷網),可以通過 DNS指向其他區域的IP來是服務可用,

對于內外DNS,可以實作簡單的輪詢負載均衡,但是,還是會有一定快取時間并且沒有失敗重試機制,因此我們可以使用HaProxy和Nginx,

而且對于一般應用來說,有Nginx就可以了,但Nginx一般用戶7層負載均衡,其吞吐量 是有一定限制的,為了提升整體吞吐量,會再DNS和Nginx之間引入接入層,如使用 LVS(軟體負載均衡)、F5(硬體負載均衡器)可以做4層負載均衡,即首先DNS決議到 LVX/F5,回傳LVS/F5轉發給Nginx,再由Nginx轉發給后端Server,

在這里插入圖片描述

Nginx負載均衡演算法

負載均衡用來解決用戶請求到來時如何選擇upstream server進行處理,默認采用round-robin(輪詢),同時支持其他幾種演算法,

  • round-robin:輪詢,默認負均衡演算法,即以輪詢的方式將請求轉發到上游服務器,通過配合weight配置可以實作基于權重的輪詢,
  • ip_hash:根據客戶IP進行負載,即相同的IP負載均衡到同一個server,
  • hash key:對某一個key進行哈希或者使用一致性哈希演算法進行負載均衡,使用hash算 法存在的問題是,當添加/洗掉一臺服務器時,將導致很多key被重新負載均衡到不同的服 務器(從而導致后端可能出現問題);因此建議考慮使用一致性哈希演算法,這樣當添加/刪 除一臺服務器時,只有少數key將被重新負載均衡到不同的服務器,
  • 哈希演算法:此處是根據請求uri進行負載均衡,可以使用Nginx變數,因此可以實作復 雜的演算法
  • least_conn:將請求負載均衡到最少活躍連接的上游服務器,如果配置的服務器較少, 則將轉而使用基于權重的輪詢演算法

失敗重試

主要有兩部分配置:upstream server 和proxy_pass

 
upstream api{
server 172.31.72.157:80 max_fails=2 fial_timeout=10s weight=1;
server 172.31.72.155:80 max_fails=2 fial_timeout=10s weight=1; 
}

通過配置上游服務器的max_fails和fial_timeout,來指定每個上游服務器,當fail_timeout 時間內失敗了max_fails次請求,則認為該上游服務器不可用/不存活,然后將摘掉該上游服 務器,fail_timeout時間后會再次將該服務器加入到存活上游服務器串列進行重試,

健康檢查

Nginx對上游服務器的健康檢查默認采用的是惰性策略,Nginx商業版提供了 health_check進行主動健康檢查,當然也可以集成nginx_upstream_check_module模塊來進 行主動健康檢查,

nginx_upstream_check_module支持TCP心跳和HTTP心跳來實作健康檢查

TCP心跳檢查

 
upstream api{
server 172.31.72.157:80 max_fails=2 fial_timeout=10s weight=1;
server 172.31.72.155:80 max_fails=2 fial_timeout=10s weight=1;
check interval=3000 rise=1 fall=3 timeout=2000 type=tcp; 
}
  • interval:檢測間隔時間,此處配置每3s檢測一次
  • fall:檢測失敗多少次后,上游服務器被標識為不存活
  • rise:檢測成功多少次后,上游服務被標識為存活,并可以處理請求
  • timeout:檢查請求超時時間

HTTP心跳檢查

   
upstream api{
server 172.31.72.157:80 max_fails=2 fial_timeout=10s weight=1;
server 172.31.72.155:80 max_fails=2 fial_timeout=10s weight=1; check interval=3000 rise=1 fall=3 timeout=2000 type=htpp;
check_http_send "GET /check HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx | http_3xx; 
}

HTTP心跳檢查有如下兩個引數需要額外配置

  • check_http_send:檢查時發的HTTP請求內容

  • check_http_expect_alive:當上游服務器回傳匹配的回應狀態碼時,則認為上游服務器存活

    需要注意,檢查間隔時間不能太短,否則可能因為心跳檢查包太多造成上游服務器掛掉,同時要設定合理的超時時間,

備份上游服務器

upstream api{
server 172.31.72.157:80 weight=1;
server 172.31.72.152:80 weight=2 backup; 
}

將172.31.72.152服務器80埠的上游服務器配置為備上游服務,當所有主上游服務器都 不存活時,請求會轉發給備上游服務器,

不可用上游服務器

 
upstream api{
server 172.31.72.157:80 weight=1;
server 172.31.72.152:80 weight=2 down; 
}

將172.31.72.152服務器80埠的上游服務器配置為永久不可用,當測驗或者機器出現故障 時,暫時通過該配置臨時摘掉機器,

隔離

隔離是指將系統或資源分割開,系統隔離是為了在系統發生故障時,能限定傳播范圍和影響范圍,即發生故障后不會出現滾雪球效應,從而保證只有出問題的服務不可用,其他服務還是可用的,資源隔離通過隔離來減少資源競爭,保障服務間的相互不影響和可用性,

常規的隔離手段有執行緒隔離、行程隔離、集群隔離、機房隔離、讀寫隔離、快慢隔離、 動靜隔離、爬蟲隔離等,出現系統問題時,可以考慮負載均衡路由、自動/手段切換分組或 者降級等收到來保障可用性,

執行緒隔離

執行緒隔離主要是指執行緒池隔離,在實際使用時,我們會把請求分類,然后交給不同的執行緒池處理,當一種業務的請求處理發送問題時,不會將故障擴散到其他執行緒池,從而保證其他服務可用,

行程隔離

一般一個系統剛開始構建,一般是先進行從零到一,不會一開始就進行系統拆分,這樣 就會開發出一個大而全的系統,系統的一個模塊/功能出現問題,整個系統就不可用了,首 先,相到的解決方案是通過部署多個實體,通過負載均衡進行路由轉發,但是這種情況無 法避免某個模塊因BUG而導致整個系統不可用的?險,因此,這種方案只是一個過渡,好 的解決方案是通過將系統拆分為多個子系統來實作物理隔離,通過行程隔離使得某一個子 系統出現問題時不會影響到其他子系統,微服務架構模式就是解決行程隔離的方式之一,

集群隔離

隨著系統的發展,單實體服務無法滿足需求,此時需要服務化技術,通過部署多個服務形成服務集群,來提升系統容量,

機房隔離

隨著對系統可用性的要求,會進行多機房部署,每個機房的服務都有自己的服務分組, 本機房的服務應該只呼叫本機房服務,不進行跨機房呼叫,其中,一個機房服務發送問題 時,可用通過DNS/負載均衡將請求全部切到另一個機房,或者考慮服務能自動重試其他機 房的服務,從而提升系統可用性,

讀寫隔離

通過主從模式將讀和寫分離,讀服務只向從機讀取資料,當主機出現問題,從機還是可 用的,從而不影響用戶訪問,而當從機出現問題時,可用直接讀取主機,或者讀取其他從 機,一般來說 mysql主從,redis主從都是可以實作,

動靜隔離

當用戶訪問一個?面時,如果js/css/image等靜態資源和動態資源在一個機器中,很可能因為訪問量太大導致帶寬被打滿,從而出現不可用,

因此,應該將動態內容和靜態資源分類,一般應該將靜態資源放到oss物件存盤上,開啟 CDN快取,

爬蟲隔離

在實際業務中,會有爬蟲來抓取我們的?面,爬蟲和正常流量的比例能達到5:1,甚至更 高,一些系統就是因為爬蟲訪問量太大而導致服務不可用,一種解決辦法是通過限流解 決,另一種解決辦法是在負載均衡層面將爬蟲路由到單獨集群,從而保證正常流量可用, 爬蟲流量盡量可用,

熱點隔離

秒殺,搶購屬于非常合適的熱點例子,對于這種熱點,是能提前知道的,所以可以將秒 殺和搶購做成獨立系統或服務進行隔離,從而保證秒殺/搶購流程出現問題時不影響主流程,

還存在一些熱點,可能是因為活動或突發事件引起的,對于讀熱點,可以使用多級快取 來搞定,而寫熱點一般通過快取+訊息佇列模式削峰,

資源隔離

最常?的資源,如磁盤、CPU、網路,這些資源都會存在競爭問題,

使用Hystrix實作隔離

Hystrix是Netflix開源的一款容錯框架,包含常用的容錯方法:執行緒池隔離、信號量隔 離、熔斷、降級回退,在高并發訪問下,系統所依賴的服務的穩定性對系統的影響非常 大,依賴有很多不可控的因素,比如網路連接變慢,資源突然繁忙,暫時不可用,服務脫機等,我們要構建穩定、可靠的分布式系統,就必須要有這樣一套容錯方法,

限流詳解

在開發高并發系統時,有很多方法來保護系統,如快取,降級,限流等,快取的目的是提升系統訪問速度和增大系統處理能力,可謂是扛高并發流量的銀彈,而降級是當服務出 問題或者影響到核心流程的性能,需要暫時屏蔽掉,待高峰過去或者問題解決后在打開的 場景,而有些場景并不能用快取和降級來解決,比如稀缺資源(秒殺、搶購)、寫服務 (如評論,下單)、頻繁的復雜查詢等,因此,需要一種手段來限制這些場景下的并發/請 求量,這種手段就是限流,

限流的目的是通過對并發訪問/請求進行限速或者一個時間視窗內的請求進行限速來保護系統,一旦達到限制速率則可以拒絕服務、排隊或等待、降級,在壓測時我們能找出每個 系統的處理峰值,然后通過設定峰值閥值,來防止當系統過載時,通過拒絕處理過載的請求來保障系統可用,另外,也應根據系統的吞吐量、回應時間、可用率來動態調整限流閥值,

一般開發高并發系統常?的限流有:限制總并發數(比如資料庫連接池、執行緒池)、限制瞬發時并發數(如Nginx的limit_conn模塊,用來限制瞬時并發連接數)、限制時間視窗 內的平均速率(如Nginx的limit_req模塊,用來限制每秒的平均速率),以及限制遠程介面 呼叫速率、限制MQ的消費速率等,另外,還可以根據網路連接數、網路流量、CPU或記憶體負載等來限流,

先有快取這個銀彈,后有限流來應對高并發流量,在處理高并發問題上可以說是如?添翼,不用擔心瞬間流量而導致系統掛掉或雪崩,最終做到有損服務而不是整個服務停掉,限流需要評估好,不可亂用,否則正常流量會出現一些奇怪的問題,而導致用戶抱怨,

在實際應用時,也不要太糾結演算法問題,因為一些限流演算法實作是一樣的,只是描述不一樣,具體使用哪種限流技術,還是要根據實際場景來選擇,不要盲目去找最佳模式,最終解決了問題就好,

限流演算法

常?的限流演算法有:令牌桶、漏桶,計數器也可以用來進行粗暴限流實作,

  • 令牌桶演算法

    令牌桶演算法,是一個存放固定容量令牌的桶,按照固定速率往桶里添加令牌,令牌桶演算法的描述如下:
    設限制2r/s,則按照500毫秒的固定速率往桶中添加令牌
    桶中最多存放b個令牌,當桶滿時,新添加的令牌被丟棄或拒絕
    當一個n個位元組大小的資料包到達,將從桶中洗掉n個令牌,接著資料包被發送到網路上
    如果桶中的令牌不足n個,則不會洗掉令牌,且該資料包將被限流(要么丟棄,要么 在緩沖區等待)
  • 漏桶作為計量工具時,可以用于流量整形和流量控制,漏桶演算法的描述如下:
    一個固定容量的漏桶,按照常量固定速率流出水滴
    如果桶是空的,則不需要流出水滴
    可以以任意速率流入水滴到漏桶
    如果流入水滴超出了桶的容量,則流入的水滴溢位了(被丟棄),而漏桶容量是不變的

應用級限流

  • 限流總并發/連接/請求數

    一個應用系統,一定會員極限并發/請求數,即總有一個TPS/QPS閥值,如果超了閥值,則系統就會不回應用戶請求或回應速度非常慢,因此最好進行過載保護,防止大量請求涌入擊垮系統,

  • 限流總資源數

    如果有的資源是稀缺資源(如資料庫連接、執行緒),而且可能有多個系統會去使用 它,那么需要加以限制,可以使用池化技術來限制總資源數,如連接池,執行緒池,假設分 配個某個應用的資料庫連接是100,那么該應用最多可以使用100個資源,超出可以等待或者拋例外,

  • 限流某個介面的總并發數/請求數

    如果介面可能會有突發訪問情況,但又擔心訪問量太大造成崩潰,那么這個時候就需要限制這個介面的總并發數/請求數了,因為粒度比較細,可以為每個介面設定相應的閥值,

  • 限流某個介面的時間窗請求數

    即一個時間視窗內的請求數,如想限制某個介面/服務每秒/每分鐘/每天的請求數/呼叫 量,如一些基礎服務會被很多其他系統呼叫,比如用戶的搜索服務會被其他的服務呼叫,但是更新量比較大有可能將基礎服務打掛,這時,我們要對每秒/每分鐘的呼叫量 進行限速,

  • 平滑限流某個介面的請求數

    之前的限流方式都不能很好的應對突發請求,即瞬間請求可能都被允許,從而導致 一些問題,因此,在一些場景中需要對突發請求進行整形,整形為平均速率請求處理 (比如5r/s,則每隔200毫秒處理一個請求,平滑了速率),這個時候有兩種演算法滿足 我們的場景:令牌桶和漏桶演算法,

分布式限流

分布式限流最關鍵的是要將限流服務做成原子化,而解決方案可以使用Redis+Lua或者 Nginx+Lua技術進行實作,通過這倆中技術可以實作高并發和高性能,

接入層限流

接入層通常指請求流量的入口,該層主要的目的有:負載均衡、非法請求過濾、請求聚 合、快取、降級、限流、A/B測驗、服務質量監控等,

對應Nginx接入層限流可以使用Nginx自帶的兩個模塊:連接數限流模塊 ngx_http_limit_conn_module和漏桶演算法實作的請求限流模塊ngx_http_limit_req_module來實作,

降級

降級的最終目的是保證核心服務可用,即使是有損的,而且有些服務是無法降級的(如聊天,支付),降級也需要根據系統的吞吐量、回應時間、可用率等條件進行手工降級或自動降級,

降級預案

在進行降級之前要對系統進行梳理,看看系統是不是可以棄?保帥,從而梳理出哪些必須誓死保護,哪些可降級,比如,可以參考日志級別設定預案,

  • 一般:比如,有些服務偶爾因為網路抖動或者服務正在上線而超時,可以自動降級,
  • 警告:有些服務在一段時間內成功率有波動(如在95~100%之間),可以自動降級或人工降級,并發送警告,
  • 錯誤:可用率低于90%,或者資料庫連接池用完了,或者訪問量突然劇增達到系統能 承受的最大閥值,此時可以根據情況自動降級或者人工降級,
  • 嚴重錯誤:因為特殊原因資料出現錯誤,此時需要緊急人工降級,
  • 降級按照是否自動化可分為:自動開關降級和人工開關降級,
  • 降級按照功能可分為:讀服務降級和寫服務降級
  • 降級按照處于的系統層次可分為:多級降級
  • 降級的功能點主要從服務器端鏈路考慮,即根據用戶訪問的服務呼叫鏈路來梳理哪里需要降級:
    ?面降級:在大的促銷或者其他特殊情況下,某些?面占用了一些稀缺資源,在緊急 情況下可以對其整個降級,以達到棄?保帥的目的
    ?面片段降級:比如?面中,某個展示內容因為資料錯誤,此時需要對其進行降級
    ?面異步請求降:某些?面上的資訊訪問速度緩慢,可以進行異步請求,進行降級
    服務功能降級:一些不重要的服務,加載速度又比較慢,這些服務在例外情況下可以直接不獲取,降級即可
    讀降級:比如多級快取,如果后端服務有問題,則可以降級為只讀快取,這種情況適 用于對讀一致性要求不高的場景
    寫降級:比如,用戶聊天,我們可以只進行存盤快取,然后異步同步資料至DB即可

自動開關降級

自動降級是根據系統負載、資源使用情況、SLA等指標進行降級

  • 超時降級

    當訪問的資料庫/http服務/遠程呼叫回應慢或者?時間回應慢,且該服務不是核心服務 的話,可以在超時后自動降級,

  • 統計失敗次數降級

    有時依賴一些不穩定的api,比如,呼叫微信or阿里云介面,當失敗次數達到一定閥值自動降級(即熔斷),然后通過異步執行緒檢測服務是否恢復了,恢復則取消降級

  • 故障降級

    比如,呼叫某個服務掛掉了(如網路故障、RPC服務拋出例外、HTTP狀態碼異 常),則可以直接降級,降級后的處理方案有:默認值(比如資料庫掛了,回傳默認的 資料),兜底資料、快取,

  • 限流降級

    當春節或者十一假期我們去12306購買火?票,因為訪問量太大導致系統崩潰,此 時,就會使用限流來限制訪問量,當達到閥值時,后續請求會被降級,降級后的處理方 案就是:排隊,或者直接告知無票,

人工開關降級

在特殊情況下,通過監控發現一些服務存在問題,此時就需要暫時將這項服務摘掉,

  • 讀服務降級

    對于讀服務降級一般采用的策略有:暫時切換讀(降級到讀取快取,降級到走靜態 化)、暫時屏蔽讀(屏蔽讀入口、屏蔽某個讀服務),

  • 寫服務降級

    寫服務在大多數場景下是不可降級的,不過可以通過一些迂回策略來解決問題,比如,將同步操作切換為異步操作,或者限制寫的頻率,

  • 多級降級

    快取離用戶越近越高效,而降級是離用戶越近越對系統保護得好,因為業務的復雜性導 致越到后端QPS/TPS越低,

    ?面JS降級開::主要控制?面功能的降級,在?面中,通過JS腳本部署功能降級開 關,在適當時機開啟/關閉開關

    接入層降級開關:主要控制請求入庫的降級,請求進入后,會首先進入接入層,在接 入層可以配置功能降級開發,根據時間情況進行自動/人工降級,

    應用層降級開發:主要控制業務的降級,在應用總配置回應的功能開關,根據實際業 務情況進行自動/人工降級

超時與重試機制

在實際開發中,很多故障是因為沒有設定超時或者設定的不合適而造成的,這些故障都是因為沒有設定超時而造成的,如果應用不設定超時,則可能會導致回應慢,慢請求導致 的連鎖反應,甚至造成應用的雪崩,有些中間件與框架在超時后會進行重試,讀服務非常 適合重試,但是寫服務大多不能設定重試(如下單,發送訊息,支付等,如果寫服務是冪 等的,則允許重試),但是重試的次數太多或導致多倍的請求流量,就像模擬了DDoS攻 擊,后果可能是災難,因此重試的機制一定要設定合理,并且應該和熔斷、快速失敗機制配合,

代理層超時與重試

對于代理層以Nginx來介紹:

Nginx主要有4類超時設定:客戶端超時設定、DNS決議超時設定、代理超時設定,如果使用ngx_lua,則還有Lua相關超時設定

  • 客戶端超時設定

    client_header_timeout:設定讀取客戶端請求頭超時時間,默認為60s,如果在超時 時間內,客戶端沒發送任何東?,nginx回傳HTTP狀態碼408(“Request timed out”)

    client_body_timeout:設定讀取客戶端內容提請求超時時間,默認為60s,.如果客 戶端在指定時間內沒有發送任何內容,Nginx 回傳 HTTP 408(Request Timed Out),

    send_timeout:設定發送回應到客戶端時間,默認為60s,在兩次客戶端讀取操作之 間,如果在這段時間內,客戶端沒有讀取任何資料,Nginx就會關閉連接,

    keepalive_timeout:設定客戶端分配HTTP鏈接超時時間,服務器將在這個時間過 后關閉鏈接,我們將它設定低些可以讓Nginx持續作業的時間更?,默認為75s,

  • DNS決議超時設定

    resolver_timeout:設定DNS決議超時時間,默認為30s,

web容器超時

比如php的容器是php-fpm,那么可以在php-fpm中配置超時設定:

  • fastcgi_connect_timeout:指定同FastCGI服務器的連接超時時間,這個值不能超過75秒
  • fastcgi_read_timeout:指定接收FastCGI應答的超時時間,這個值是已經完成倆次握手后 介紹FastCGI應答的超時時間,

資料庫 | NoSql連接超時

在連接資料庫,NoSql時,我們會設定資料庫的連接超時時間,

業務超時

業務超時分為2類:

  • 任務型:比如12306購買了火?票,需要在指定時間內完成支付,否則火?票將被取消,
  • 服務呼叫型:在呼叫某個服務時會設定一個超時時間,

回滾機制

回滾是指當程式or資料庫出錯時,將程式或資料恢復到最近一個正確的版本的行為,最 常?的回滾如:事務回滾,代碼回滾,部署版本回滾,資料庫版本回滾,靜態資源版本回滾,

事務回滾

在某些需要保持資料一致的情況下,我們會使用資料庫的事務,從而保證資料的一致性,該事務要么全部執行成功,要么全部執行失敗,進行回滾,

代碼回滾

在開發中,我們會將代碼提交到代碼倉庫,進行版本管理,比如 代碼版本控制工具git, 比如當前版本出現問題,那么可以回滾代碼到指定的版本,

部署版本回滾

每次發布上線,都會有上線版本,如果本次上線版本有問題,則切換到上一版本,

資料版本回滾

設計版本化資料結構時,有2種方式:全量和增量,全量化版本指即使只變更了一個字 段也將整體記錄進行歷史版本化,保存的資料量比較多,但是回滾方便,而增量指記錄保 存變化的欄位,保存的資料量較少,但是回滾起來很麻煩,需要回溯,

靜態資源版本回滾

在前端開發中,靜態資源版本也是經常變更,如JS/CSS,而每次發布上線時,都會備份 之前版本,從而保證版本可回滾,

壓測與預案

系統壓測

壓測一般就是性能壓力測驗,用來評估系統的穩定性和性能,通過壓測資料進行系統容量評估,從而決定是否需要進行擴容或縮容,

壓測之前要有壓測方案,常?的壓測是:介面壓測、并發量、壓測策略(突發、逐步加 壓、并發量)、壓測指標(機器負載、QPS/TPS、回應時間),然后出壓測報告{壓測方 案、機器負載、QPS/TPS、回應時間(平均、最小、最大)、成功率、相關引數(nginx參 數、php-fpm引數)等},最后根據壓測報告分析的結果進行系統優化和容災,

應用級快取

快取就是讓資料更接近用戶,目的是讓訪問速度更快,作業機制是先從快取中讀取資料,如果沒有,在從db中讀取資料,并同步至快取中,

快取命中率

快取命中率是從快取中讀取資料的次數與總讀取次數的比率,命中率越高越好,快取命 中率=從快取讀取次數 / (總讀取次數「快取中讀取次數+從db中讀取次數」),這是一個非 常重要的監控指標,如果做快取,則應通過監控這個指標來看快取是否作業良好,

快取回收策略

  • 基于空間

    基于空間值快取設定了存盤空間,例如設定100MB,當達到存盤上線,按照一定策略移除資料

  • 基于容量

    基于容量值快取設定了最大大小,當快取的條目超過了最大大小時,按照一定策略移除就資料

  • 基于事件

    TTL(Time To Live):存活期,即快取資料的一個有效時間,一般創建快取的時候會設 置一個快取過期時間

    TTI(Time to Idle):空閑期,即快取資料多久沒有被訪問后移除快取的時間,

多級快取

所謂多級快取,是指在整個系統架構的不同系統層級進行資料快取,以提升訪問效率,這也是應用最廣的方案之一,
在這里插入圖片描述

連接池執行緒池

在系統開發程序中,我們經常會用到池化技術,如物件池、連接池、執行緒池等,通過池 化來減少一下消耗,以提升性能,物件池通過復用物件來減少創建物件,垃圾回收的開 銷,但是池不能太大,太大會影響GC時的掃碼時間,連接池如資料庫連接池,redis連接池,http連接池,通過復用TCP連接來減少創建和釋放連接的時間來提升性能,執行緒池也是 類似,通過復用執行緒提升性能,

佇列

應用場景

  • 異步處理

    使用佇列的一個主要原因是進行異步處理,比如用戶注冊成功后,需要發送注冊成功 郵件,贈送卡券等;通過異步處理提升主流程回應速度,而非主流程/非重要處理可以集中 處理,這樣還可以將任務聚合批量處理,因此可以使用訊息佇列/任務佇列來進行異步處理,

  • 系統解耦

    一個完善系統是需要根據不同語言的特性來做不同的應用處理,使用訊息佇列/任務佇列可以進行系統上解耦,

  • 資料同步

    比如,想把MySql的資料同步至redis,或者讓機房之間的資料同步,或者主從資料同步 等,此時可以使用databus、canal、otter等,資料資料總線佇列進行資料同步的好處是 可以保證資料修改的有序性,

  • 流量削峰

    系統瓶頸一般在資料庫上,比如下單,扣減庫存等,此時可以考慮使用佇列將變更請求暫時放入佇列,通過快取+佇列暫存的方式將資料庫流量削峰,

任務佇列

使用任務佇列可以將一些不需要與主執行緒同步執行的任務扔到任務佇列進行異步處理, 比如 go語言中channel就可以實作一個個任務佇列,比如socket聊天,當用戶A給用戶B發 送訊息時, 后端接收到用戶A發送的訊息,需要下發給用戶B,并告知用戶A發送成功,此時 就可以將訊息放入到channel中異步處理,告知用戶A發送訊息成功,使用goroutine從 channel中有序的獲取資料,執行操作,下發到用戶B,

訊息佇列

通常使用開源系統,Kafak、Nsq、redis等,使用訊息佇列存盤各業務資料,其他系統根 據需要訂閱即可,常?的訂閱模式是:點對點(即一個訊息只有一個消費者)、發布訂閱 (一個訊息可以有多個消費者),

請求佇列

請求佇列是指在web環境下對用戶請求進行排隊,從而進行一下特殊控制:流量控制、 請求分級、請求隔離,

資料總線佇列

一般訊息佇列中的訊息都是業務維度的簡單資料,如用戶更改了基礎資訊,如果要進行 資料維度的同步,使用訊息佇列方式很難只進行變更部分的推送并保證資料的有序性,例 如資料庫的欄位發生了變化,或者將一個機房的資料同步至另一個機房,資料維度的同 步,此時需要是用資料總線佇列,如阿里的Canal、LinkedIn的databus,使用資料總線佇列 的好處是,可以保證資料的有序性,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/307206.html

標籤:其他

上一篇:康威定律:產品必然是其組織溝通結構的縮影

下一篇:Nignx優化與防盜鏈

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more