朱曄的互聯網架構實踐心得S1E8:三十種架構設計模式(下)

接上文,繼續剩下的15個模式。
前端

數據管理模式

1六、分片模式:將數據存儲區劃分爲一組水平分區或分片



一直有一個說法就是不到沒路可走的時候不要考慮數據庫分片。有的時候業務量大到單個業務表在通過緩存+隊列削峯等措施以後的平均的TPS超過1萬,單表實在是扛不住,仍是隻能考慮分片手段。node

分片前:算法

· 須要根據數據分佈、壓力狀況、業務邏輯肯定分片的方式,按照條件仍是範圍仍是哈希等等(三個圖展現了三種策略)。數據庫

· 須要進行業務代碼改造,改掉全部不容許的SQL。後端

· 須要肯定用HardCode方式仍是框架方式仍是中間件方式作數據路由。設計模式

分片後:緩存

· 須要有運維工具能夠對這麼多套分片的數據進行統一的加索引等操做。安全

· 最好有數據倉庫能夠彙總全部數據,使得adhoc查詢能夠更方便。服務器

· 最好有輔助工具能夠用來幫助定位數據會在哪一個分片中。網絡

1七、靜態內容託管模式:將靜態內容部署到基於雲的存儲服務,能夠將它們直接傳遞給客戶端

相信互聯網公司90%+確定都使用了這個模式。把靜態資源從動態網站中剝離由Nginx等高性能服務器來處理靜態資源,而後使用三方CDN對靜態資源進行加速,不但減輕了動態網站的負載並且數據在邊緣節點加速讓用戶的訪問跟快,使用單獨的一個或多個子域名作靜態資源還能提升下載資源的並行度提升網頁加載的速度。

使用CDN來進行資源加速通常有主動數據傳送到CDN存儲和在CDN配置回源站拉取兩種方式,文件類通常使用主動推送數據,靜態資源類通常使用回源方式。在使用CDN的時候考慮下面的問題:

· CDN以什麼方式來認定同一個文件的,CDN提供了什麼工具來刷新邊緣節點的緩存?根據不一樣的策略作相應的緩存刷新方案。

· 源站對於相同的文件須要有一致性(最好版本變化後文件名變化),不能今天是這個版本明天是另外一個版本,這樣極可能致使邊緣節點緩存了不一樣版本的文件,致使各類怪問題。

· 使用了CDN後不一樣地區的用戶訪問的都是CDN節點上的數據,一旦出現問題排查比較困難,考慮引入前端的錯誤處理框架來記錄前端出現腳本錯誤時的調用棧,方便定位問題。

1八、索引表模式:爲查詢常常引用的數據存儲區中的字段建立索引

在第三第五兩篇文章中我都提到了索引表的作法。出於下面的緣由,咱們會考慮索引表:

· 雖然咱們的關係型數據庫大多支持主鍵以外的非彙集索引,可是在某些狀況下直接對大表作不少索引性能並很差。

· 作了Sharding後咱們確實沒有辦法以分片鍵以外的維度來查詢數據。

· 但願以空間換時間,直接把某個維度的複合查詢做爲主鍵單獨保存一份數據。

不過須要考慮一點索引只有在數據區分度高的狀況下才能發揮價值,若是90%以上的數據都是相同的值,那麼走索引進行查詢性能會比全表掃還要差一點。

設計和實現模式

1九、前端專用的後端模式:經過使用單獨的接口來分離讀取數據和更新數據的操做

這裏說的是不一樣的前端配以不一樣的專用後端。好比PC網站和APP的後端是兩套程序。這種模式是否適合其實仍是看兩端的後端提供的數據差別有多大,咱們老是但願能夠儘可能統一一套後端,業務邏輯不用重複寫,可是咱們要考慮到PC網站和APP的差別性:

· APP系統的接口交互通常會簽名驗證,有的時候還會加密

· PC系統的流程通常和APP系統不同

· PC一個頁面能顯示的內容會比APP一個界面顯示的更多

· 安全性設計上PC和APP不同,APP不多有圖形驗證碼

考慮到這些差別,咱們是在一個工程內根據來源作適配,仍是獨立兩套工程來作獨立的後端取決於差別度有多大了。

20、計算資源整合模式:將多個任務或操做整合到單個計算單元中

這個模式從資源節省的角度來講咱們的計算單元任務能夠進行一些合併,減小由於資源限制致使沒必要要的開銷。

2一、選舉模式:經過選舉一個實例做爲負責管理其它實例的負責人,來協調分佈式應用程序中的協做任務實例集合執行的操做

對於分佈式服務,咱們趨向於把服務設計爲無狀態能夠任意擴展的,可是在某些業務場景下咱們不得不在服務中選舉出一個Leader(Primary節點,Master節點)來作一些不適合重複作的協調管理工做。這個時候咱們須要有算法來作選舉。

最多見的實現方式是使用Zookeeper來實現,咱們知道ZK的znode有Sequence和NonSequence兩種,前者多個客戶端只有一個可建立成功同名節點,後者建立後會自動加上序列號命名多個客戶端能夠建立多個同名節點,利用這個特性有兩種常見實現方式:

· 非公平實現。多個客戶端同時建立EPHEMERAL+NONSEQUENCE節點。只有一個能夠建立成功,建立成功的就是Leader,其它的Follower須要註冊watch,一旦Leader放棄節點(注意,EPHEMERAL意味着Leader待機後Session結束節點被刪除),再一次重複以前的過程註冊節點搶佔成爲Leader。這個模式實現簡單,問題是在節點數量過多的時候一旦發生從新競選,這個時候可能會有性能問題。

· 公平實現。多個客戶端同時建立EPHEMERAL+SEQUENCE節點。客戶端均可以建立成功節點,客戶端若是判斷本身是最小的節點則爲Leader不然爲Follower。每個Follower都去watch序號比本身小的節點(你們都看前一位)。一旦有Leader節點由於宕機被刪除(仍是EPHEMERAL特性),收到通知的節點會看本身是否是最小的序號,若是是的話成爲Leader。節點宕機後,原先watch宕機節點的客戶端從新watch比本身序號小的有效節點。這個模式實現複雜,可是因爲watch的都只是一個節點因此不會發生像非公平實現的性能問題,並且競選根據節點序號來而不是搶佔式因此顯得Leader的選舉公平有序。

2二、管道和過濾器模式:將須要執行復雜處理的任務分解成能夠重複使用的一系列單獨的元素

在軟件設計模式中過濾器構成的管道這種模式很常見(圖上的業務邏輯就是Handler,以前的那些Task就是Filter,模式上能夠是Filter+Handler也能夠是Filter+Handler+Filter也能夠是Handler+Filter),無論是Spring MVC框架也好,Netty這種網絡框架也好都提供了這樣的設計。每個過濾器單獨完成一個功能,能夠獨立插拔隨意組合配置成一套管道,不但數據處理的整個過程清晰可見還增長了靈活性。

對於架構上也能夠有這樣的模式,在數據源進入到業務邏輯處理以前(或以後,或先後),咱們能夠配置一系列的數據過濾器完成各類數據轉化和處理的任務。Task和Task之間能夠是同步調用,也可使用MQ作必定的可伸縮性設計。還能夠把過濾器的配置信息保存在配置系統中甚至根據上下文動態構建出管道,實現更靈活的前置或後置流程處理。

消息模式

2三、競爭消費者模式:使用多個併發消費者來處理在同一消息通道上接收的消息

這裏說的是消息隊列的消息消費者是一組對等的消費者,經過競爭方式來拉取數據執行。以前提到過這是MQ的最多見的一種模式,通常而言咱們會部署多個消費節點進行負載均衡,在負載較大的時候能夠方便得增長消費者進行消費能力擴容。不過對於這種模式消費者應當是對等的無狀態的,在某個消費者在消費失敗的時候消息從新回到隊列隨後可能會被另外一個消費者進行處理。

2四、重試模式:在應用程序嘗試鏈接到服務或網絡資源遇到預期的臨時故障時,讓程序經過透明地重試之前失敗的操做來處理

重試適用於瞬態故障,以後會提到斷路器模式,兩種模式能夠結合使用。首先說說重試的幾個發起人:

· 讓用戶本身發起,遇到錯誤的時候及時返回錯誤信息,讓用戶本身稍後重試整個業務功能。這種方式不容易產生瞬時的壓力,可是體驗較差。

· 在中間件自動發起,好比在RPC調用的時候遇到服務超時自動進行必定次數的重試,這樣能夠在外部沒有感知的狀況下有必定機率消除錯誤。這個方式要求服務是支持重試的。

· 由業務邏輯手動發起,不一樣的業務邏輯根據需求在代碼中去寫重試的邏輯(固然也能夠經過相似Spring-Retry這種組件來作)。實現繁瑣可是不容易出錯。

· 由補償邏輯發起進行同步轉異步操做,非重要邏輯同步行則行,不行不在主流程重試,由單獨的異步流程進行重試補償。

重試也要考慮幾種策略:

· 次數。最多重試幾回。

· 異常。遇到什麼樣的異常(黑白名單)應該去重試。

· 等待。考慮每次重試是相同的間隔呢仍是有一個延遲的遞增,隨着重試次數增長而增長延時時間。

2五、調度、代理、主管模式:在一組分佈式服務和其它遠程資源之間協調一組操做

這個模式說的是三者的角色:

· 調度負責安排任務,在執行每一個步驟的時候維護任務的狀態,具體業務邏輯由代理負責。

· 代理負責和遠程的服務和資源進行通信,實現錯誤處理和重試。

· 管理者負責監視任務的執行狀態,做爲調度的補充,在合適的時候要求調度進行補償。

三個角色相互配合完成複雜的,具備較多遠程服務參與的任務,確保任務的最終有效執行。在以前架構三馬車一文中說到定時任務的時候提到過一種任務驅動表的模式,說到了一些驅動表的實現細節,其實總體和這個模式是相似的思想。當咱們的一個複雜邏輯有多個步驟構成,每一步都依賴外部服務,這個時候咱們能夠選擇全程MQ+補償方式(樂觀方式),也能夠選擇全程任務驅動的被動模式(悲觀方式),具體選擇取決於更看重可靠性仍是及時性。

彈性模式

2六、艙壁模式:將應用程序的元素隔離到池中,若是其中一個失敗,其它的將繼續運行

資源隔離有好幾個層次,能夠在進程內部作線程池或隊列的隔離,在微服務的服務劃分上考慮隔離出單獨的物理服務,或是在服務器層面經過虛擬化技術或Docker技術進行資源隔離。隔離了就不會相互影響,可是會有成本、性能、管理便利性方面的開銷。實現可以根據需求分析出可能的資源相互影響的點,提早規劃隔離每每能夠避免不少問題的發生。以前有遇到過幾個事故是這樣的:

· 程序內部大量使用了Java8的ParallelStream特性進行並行處理,因爲默認共享了相同的線程池,某一個業務的執行佔滿了線程影響了其它業務的正常進行。

· 消息隊列由於沒有對執行過屢次失敗的死信消息和正常的新消息進行隔離,致使一些業務下線後沒法處理的死消息佔滿了整個隊列,正常消息沒法消費。

· 某個服務提供了相似文件上傳的重量級操做,也提供了數據查詢的輕量級操做,在上傳業務大的時候服務的線程都被IO所佔滿,致使其它查詢操做沒法進行。

2七、斷路器模式:鏈接到遠程服務或資源時, 處理可能須要花費時間來修復的故障

分佈式應用環節多網絡環境複雜,若是遇到依賴服務調用失敗的狀況咱們或許能夠進行重試期待服務立刻能夠恢復,可是在某些時候依賴的服務是完全掛了而不是網絡故障沒法及時恢復,若是不考慮進行熔斷的,可能服務調用方會被服務提供方拖死。這個時候能夠引入斷路器機制,如圖所示斷路器通常採用三態實現,瞬間恢復可能會讓底層服務壓力過大:

· 關閉:出現錯誤的時候增長計數器

· 打開:計數器到達閾值打開斷路器,直接返回錯誤

· 半開:超時後容許必定的請求經過,成功率達到閾值關閉斷路器,操做仍是失敗的話仍是進入打開狀態

實現模式的時候考慮下面注意點:

· 考慮熔斷後怎麼來處理,熔斷後咱們確定拿不到實際的處理結果,這個時候考慮是功能降級仍是採用後備的數據提供方來提供數據

· 緊急的時候須要人工介入,最好在外部提供手動的方式能夠干預斷路器的三態

· 不一樣的業務考慮不一樣的斷路器打開閾值,每個錯誤還能有不一樣的權重,好比對於下游程序返回了太多請求的錯誤,每次錯誤能夠+2提升權重儘量早斷路

· 斷路器應當記錄熔斷時的請求原始信息,在以後必要的時候能夠進行重放或數據修復工做

· 注意設置好外部服務的超時,若是客戶端超時比服務端短,極可能進行錯誤的熔斷

實現上咱們能夠看一下Netflix的Hystrix進行進一步瞭解。

2八、事務補償模式:撤消經過一系列步驟執行的工做,它們一塊兒定義最終一致的操做

這個模式說的是失敗時必須進行撤銷的操做,能夠由一組補償程序來作相應的補償。在這裏我想說的更廣一點,在服務調用的時候,調用失敗有幾種可能:

· 請求客戶端發出可是沒到服務端,業務邏輯沒有執行

· 請求客戶端發出服務端收到也處理成功了,業務邏輯執行了客戶端沒收到結果

· 請求客戶端發出服務端收到但處理失敗了,客戶端沒收到結果

因此在出現服務調用失敗或超時的時候,服務端執行究竟有沒有成功客戶端是不明確的(只有客戶端收到了明確的服務端返回的業務錯誤才真正表明執行失敗),這個時候須要有補償邏輯來同步服務端的執行狀態。若是這樣的補償不可避免並且須要補償的服務特別多,這樣的邏輯逐一來寫是一件很煩的事情,咱們能夠把這個工做封裝成一個補償中間件來處理:

· 全部關鍵服務調用標記爲須要自動補償

· 補償中間件在數據庫記錄服務的調用狀態

· 關鍵服務的提供者提供統一狀態查詢接口,消費者提供統一的補償回調接口(來處理成功和失敗的狀況)

· 補償中間件根據數據庫的記錄調用服務提供方的狀態查詢和服務消費方的補償回調接口進行補償

這樣,咱們在服務調用的時候就不須要考慮補償邏輯的實現,只要實現這個標準便可。

安全模式

2九、代客密鑰模式:使用向客戶端提供對特定資源或服務的有限直接訪問權限的令牌或密鑰

這個模式說的是,在訪問敏感資源的時候,咱們能夠沒必要讓應用程序在其中做爲一個代理轉一層作權限控制,而是生成一個密鑰,讓用戶直接拿着密鑰到資源池換數據。

一些CDN在提供資源上傳下載服務的時候通常都會提供相似的安全策略,須要實現生成Token才能去使用下載和上傳服務,避免了CDN數據被非法利用做爲圖牀的可能。

實現上比較簡單,應用程序和資源提供方約定好Token的生成算法,對資源+請求資源的時間+密鑰聯合在一塊兒作簽名,資源提供方若是校驗到簽名不正確或Token過時或資源不匹配都將拒絕服務。

30、聯合身份模式:將認證委託給外部身份提供者

這個模式說的是將身份驗證委託給專門的程序或模塊來作。使用專門的模塊來統一負責登陸受權不只僅能夠提供單點登陸的功能,並且服務實現上更簡單不須要每次都考慮登陸那套東西。實現上能夠看一下Spring Security實現的OAuth 2.0。

總結一下,對於其中的不少模式,咱們能夠發現其實在以前的一些介紹或多或少有一些涉及。這裏提到的30種模式有些體現的是一些設計細節,有些體現的是一種設計理念,它們大多時候是組合使用的,適合的就是最好的,你們能夠細細品味一下每種模式的適合場景,在合適的時候能夠想到它或許會有一種豁然開朗的感受。

相關文章
相關標籤/搜索