互聯(lián)網(wǎng)系統(tǒng)架構的演進
發(fā)表于43分鐘前| 次閱讀| 來源《程序員》| 0 條評論| 作者程序員雜志
摘要:多終端接入、開放平臺給互聯(lián)網(wǎng)帶來了前所未有的用戶數(shù)量和訪問規(guī)模,信息之多、傳播速度之快,是傳統(tǒng)網(wǎng)站難以想象的。本文將從發(fā)展演進的角度,解讀高性能互聯(lián)網(wǎng)系統(tǒng)架構。 多終端接入、開放平臺給互聯(lián)網(wǎng)帶來了前所未有的用戶量級和訪問規(guī)模,SNS網(wǎng)站產生了海量的UGC(用戶產生內容),而且這些內容依托關 系鏈擴散速度之快、傳播范圍之廣是傳統(tǒng)網(wǎng)站難以想象的,海量數(shù)據(jù)的計算存儲也一直是近年互聯(lián)網(wǎng)領域的熱點。本文將從發(fā)展演進的層面探討互聯(lián)網(wǎng)的系統(tǒng)架構。 天下武功唯快不破 網(wǎng)站初期的架構一般采用"短平快"的架構思路,架構以簡單清晰、容易開發(fā)為第一衡量指標。 互聯(lián)網(wǎng)架構選型首先包括開發(fā)語言的選擇,目前PHP、Java是主力語言。開發(fā)語言的選擇一般從團隊人員的知識儲備、社區(qū)活躍度、商業(yè)應用的成熟度、招聘人才的人力成本等方面考量。 選擇語言之后,一般會選擇該語言的流行框架輔助研發(fā),例如Java的SSH、Python的Django等。但這些框架并不是通常意義上的架構,架構一般可 分為物理架構、運行架構、邏輯架構、開發(fā)架構、數(shù)據(jù)架構等多個維度,框架往往只是代碼架構的一部分。代碼架構是指代碼的組織形式、規(guī)范、設計模式等,框架 其實是常用設計模式的軟件化。例如Struts是MVC模式的實現(xiàn),Hibernate、iBATIS是ORM模式的實現(xiàn)。 在架構視圖中,早期關注的主要是開發(fā)視圖和數(shù)據(jù)視圖,一般數(shù)據(jù)存儲采用DB,初期數(shù)據(jù)的關注點主要是安全和備份,MySQL的Master-Slave模式可以滿足該需求。 雞蛋不要放在一個籃子里 采用"短平快"三板斧將網(wǎng)站開發(fā)出來之后,急需解決的是網(wǎng)站的可用性問題??捎眯宰罨镜囊笫遣荒苡袉吸c,對程序節(jié)點而言,前端可采用LVS、HAProxy、Nginx等負載均衡/反向代理設備。 DB的可用性就復雜了很多,數(shù)據(jù)庫天然是有狀態(tài)的,狀態(tài)就是其中的數(shù)據(jù),新增一個數(shù)據(jù)節(jié)點一般伴隨著大量的數(shù)據(jù)復制和遷移。對金融行業(yè)而言,昂貴的商用存儲是 解決之道,"IBM+Oracle+EMC"是該類系統(tǒng)的標配。互聯(lián)網(wǎng)企業(yè)則一般采用較為廉價的方案,例如開源的DRDB+Heartbeat技術組合可 以在MySQL主庫宕機時實現(xiàn)備機接管,接管時間可以控制在30秒內。 程序節(jié)點其實也可能存在狀態(tài),例如Web服務中常用的Session 就是保存在容器中的狀態(tài),這種狀態(tài)保持要求所有相同用戶的請求都在同一臺機器上處理,無狀態(tài)的程序節(jié)點才能水平擴展。無狀態(tài)一般有兩種設計思路,還以 Session為例,一種思路是把用戶的狀態(tài)保存在客戶端Cookie,每次請求都把客戶端的用戶信息帶到服務器端,淘寶的分布式Session就是該思 路的一種實現(xiàn);另一種思路是狀態(tài)保留在另外一個服務中,例如有些公司將Session放在分布式緩存中。 性能是生命線 去除單點之后的系統(tǒng)就可以水平擴展,架構如圖1所示。但隨著網(wǎng)站的推廣運營,系統(tǒng)的規(guī)模開始擴大,此時可能會出現(xiàn)服務訪問緩慢,甚至不可用的狀況,如何提升系統(tǒng)性能就成了架構師的當務之急。 圖1 去除單點之后進行水平擴展 存儲架構和性能 互聯(lián)網(wǎng)系統(tǒng)所有的性能瓶頸中,數(shù)據(jù)存儲和訪問速度往往是最重要也是最難解決的,選擇合適的存儲是系統(tǒng)的關鍵。存儲的選擇一般需要從多個方面考量,如成本、內容、用途和模型。目前主流的存儲介質包括硬盤和內存兩種。 對機械硬盤來說,1秒可以完成150次左右的隨機I/O。而結合設計優(yōu)良的Hash算法,內存查找可以每秒執(zhí)行40萬次左右。硬盤的隨機讀寫能力決定了其讀 寫的最差性能,但操作系統(tǒng)在實現(xiàn)文件系統(tǒng)時會把最近讀寫過的數(shù)據(jù)緩存在內存中。由于磁盤訪問和內存訪問性能量級的差距,從操作系統(tǒng)的Cache命中率就可 以簡單計算文件存儲的性能,如果內存命中率可以達到80%,系統(tǒng)的I/O能力相較完全隨機I/O將有5倍提升。 對于數(shù)據(jù)層服務器,大內存已成為標配(一般為100GB左右),如果DB中存儲200GB的數(shù)據(jù),根據(jù)8/2原則,Cache命中率應為87.5%,因此對MySQL而言,一般讀寫可以達到每秒1千次以上。 對于讀寫頻率都很高、且可容忍數(shù)據(jù)丟失的場景,可以采用內存作為數(shù)據(jù)存儲的介質。可靠的內存存儲需要每次操作都記錄Biglog,即使數(shù)據(jù)丟失也可以恢復,同時內存中的數(shù)據(jù)一般定期持久化到硬盤。 從功能角度考量,還可以分為持久化存儲和Cache。持久化存儲也可稱為可靠存儲,Cache是為了提升系統(tǒng)性能,在可靠存儲的基礎上建立的訪問性能更加高效的數(shù)據(jù)讀取節(jié)點,通常是內存存儲,其架構一般如圖2所示。 圖2 持久化存儲和Cache 存儲的數(shù)據(jù)模型一般分為結構化存儲和NoSQL存儲。結構化存儲以各種傳統(tǒng)DB為代表,NoSQL技術的代表系統(tǒng)則有HBase、Memcached、 Redis等。各種NoSQL系統(tǒng)雖然特性各異,但相對傳統(tǒng)DB而言,由于結構化信息的缺失,往往不能做各種關聯(lián)查詢,適用場景更多是主鍵查詢,而且一般 是寫少讀多的系統(tǒng)。 對于大型互聯(lián)網(wǎng)公司,為了某些場景下的性能優(yōu)化,也會定制個性化的文件系統(tǒng),例如為了適應大文件存儲的場景,Google開發(fā)了GFS;為了更快讀取海量商品的描述圖片,TFS在阿里誕生。 雖然各類存儲快速涌現(xiàn),但DB作為結構化數(shù)據(jù)的傳統(tǒng)存儲設備,依然在架構中處于非常重要的地位。由于隨機I/O的瓶頸,DB的性能天花板十分明顯。在大型系 統(tǒng)中通常需要分庫操作,分庫一般有兩個維度——水平切分和垂直切分。水平切分一般根據(jù)主鍵規(guī)則或某種規(guī)則將同類數(shù)據(jù)切分到不同的單元表中,原則是數(shù)據(jù)切分均勻,尤其是熱點數(shù)據(jù)分布均勻。 垂直切分是把大表中的字段拆分到多張表。垂直切分一般按照數(shù)據(jù)訪問頻率的不同。邏輯關系的差別進行切分,例如將大字段、kv字段、計數(shù)等高頻訪問字段單獨剝離存儲都是常見的垂直切分方案。 除了切庫之外, MySQL的分表也會有效減少單表大小,使數(shù)據(jù)變得更簡單,甚至可以做到不下線變更,單表索引規(guī)模的下降也會帶來性能的提升。 分庫分表作為DB架構中重要的一環(huán),使DB更加穩(wěn)健,但它給業(yè)務代碼帶來了額外的復雜性,最好通過中間件來屏蔽DB的底層分布,對業(yè)務透明。 作為高性能網(wǎng)站必不可少的組件,Cache在各種主流架構中也起著重要的作用。 從部署模式上看,它可分為本地Cache和分布式Cache。本地Cache是指在應用進程中的Cache,通常的數(shù)據(jù)結構是一個MAP,其優(yōu)點是結構簡 單,效率較分布式Cache更高,缺點是一般應用程序服務器的內存有限,導致本地Cache容量受到局限,而且數(shù)據(jù)冗余度較高,每個應用服務器都需要一份 數(shù)據(jù),更新比較煩瑣,一般采用超時刪除機制。 分布式Cache的容量較大,方便擴容和更新,其數(shù)據(jù)分布可采用一致性Hash算法,減少節(jié)點變化帶來的數(shù)據(jù)遷移。 引入Cache不可避免的問題是服務器的宕機處理。Cache通常是一個集群,數(shù)據(jù)分布在多個節(jié)點,如果掛掉一個節(jié)點,只會影響部分數(shù)據(jù),而且對于可靠性要求較高的系統(tǒng),每個節(jié)點都可以有備份。 作為可靠存儲的數(shù)據(jù)備份,Cache在架構設計上往往承擔大部分讀訪問需求,其命中率尤為重要。Cache不命中有兩種情況,一是數(shù)據(jù)在Cache中不存 在,二是在持久化存儲中也不存在。對于后者的頻繁訪問會導致請求直接壓在DB上,在設計時應盡量避免,可以通過維護Bitmap對持久化存儲中沒有的數(shù)據(jù) 進行攔截,直接返回,也可以簡單地將這些數(shù)據(jù)對應空對象放進Cache。 Cache的存儲一般是將索引和數(shù)據(jù)分離,對于索引數(shù)據(jù)可以全量緩存,對于體量較大的數(shù)據(jù)一般采用部分緩存的方式。 Cache的使用場景有一定的局限,對于較為靜態(tài)的數(shù)據(jù)才有意義,這個臨界值一般是5分鐘。由于當前存儲技術的進步,Cache也可以用其他高性能的存儲介質代替,例如SSD的引入使得硬盤的隨機讀寫能力提升數(shù)十倍,也會使得Cache的重要性有所下降。 程序架構和性能 對一般的系統(tǒng)而言,程序邏輯的主要作用是調用各種數(shù)據(jù)訪問接口,該操作通常需要等待,所以除搜索等少數(shù)系統(tǒng)外,程序邏輯一般是非CPU密集型。該類系統(tǒng)中"線程"是稀缺資源,線程數(shù)和接口耗時構成了系統(tǒng)的QPS能力。 大型互聯(lián)網(wǎng)系統(tǒng)的QPS可能為幾萬甚至峰值達到幾十萬,此時增加機器可以解決問題,但這些機器的利用率其實很低,因為大部分時間是在等待,此時引入異步變得非常重要,異步在同樣的時間可以處理更多工作,擁有更好的性能。 圖3 同步調用和異步調用 利用Nio的多路復用方式可方便地實現(xiàn)異步系統(tǒng),當然也可用協(xié)程令代碼更加清晰。業(yè)界流行的SEDA技術可將一次請求拆分為粒度更細的Actor,每個 Actor使用獨立隊列,前一個的輸出是后一個的輸入。SEDA通過該方式將請求中等待和非等待的環(huán)節(jié)分離,提升了系統(tǒng)的吞吐量,這種方式在小米等互聯(lián)網(wǎng) 公司有較多應用。 除了異步之外,并行對系統(tǒng)也很重要,它可以有效縮短請求的響應時間。批量接口也可以有效減少系統(tǒng)調用次數(shù),使得系統(tǒng)線程消耗更少,從而提升系統(tǒng)吞吐量。 對線程而言,還有一個重要的參數(shù)是超時時間。響應快的服務,超時時間可以長一些,對于響應慢的服務,超時時間可以短一些,盡快失敗是保護自己的有效手段。 網(wǎng)絡架構和性能 大型網(wǎng)站的網(wǎng)絡接入一般是"DNS+負載均衡層+CDN"這種模式。對于大型互聯(lián)網(wǎng)公司,往往有多個IDC提供對外服務,中國互聯(lián)網(wǎng)的南北不互通使得解決不 同地域不同運營商的接入速度問題成了難題,該問題的解決一般需要公司自己開發(fā)DNS服務器,結合IP測速平臺,引流用戶請求到訪問速度最快的節(jié)點。 大系統(tǒng)小做 業(yè)務邏輯復雜多變,如何保證程序邏輯的代碼穩(wěn)定是架構師需要解決的問題,良好的模塊劃分和擴展性強的接口設計都是解決這個問題的利器。 模塊是和領域模型相關的一個概念,其往往指系統(tǒng)中高內聚的一個數(shù)據(jù)訪問單元。例如對電商系統(tǒng)而言,最大的兩個領域模型分別是商品信息和交易信息,每個領域模 型對應一系列數(shù)據(jù),商品會有商品的基本信息、類目信息等,交易會包括交易的訂單,這些"領域模型+數(shù)據(jù)+業(yè)務方法"就構成了一個個的模塊,高度內聚的模塊 是數(shù)據(jù)的訪問的入口。例如交易時也需要去獲取商品信息,但一般不會被允許直接調用商品模塊的數(shù)據(jù)表,而是通過商品模塊提供的接口進行訪問,這樣做有下面一 些優(yōu)點。 接口和數(shù)據(jù)分離,底層數(shù)據(jù)結構的變化不會影響到外圍系統(tǒng)。 數(shù)據(jù)直接暴露給其他系統(tǒng),增加了系統(tǒng)的不穩(wěn)定性。 接口的收斂減少了重復開發(fā),提高了系統(tǒng)可用性。 對較小規(guī)模的應用,模塊可部署在一起,但對大型系統(tǒng)而言,模塊一般是單獨部署,通過RPC交互,這樣可以減少彼此之間的系統(tǒng)層面影響。例如Amazon就傾向將所有服務器程序暴露為接口。 分布式系統(tǒng)增加了系統(tǒng)交互的復雜性,也為系統(tǒng)引入了更多潛在的失敗環(huán)節(jié),但分布式系統(tǒng)可以帶來的好處更明顯。 有利于系統(tǒng)分級,針對不同服務提供不同的可用性。 大規(guī)模開發(fā)有了可能,每個模塊可以單獨開發(fā)和部署。 系統(tǒng)可重用性加強,避免重復制造輪子。 服務治理更加簡單,一般RPC天然提供容災,可以自動發(fā)現(xiàn)新增節(jié)點和剔除問題節(jié)點。 邏輯層的接口設計如何做到穩(wěn)定呢?首先接口的設計不應該是產品驅動的,而應該由數(shù)據(jù)驅動,盡量考慮接口以后的發(fā)展,接口的參數(shù)盡量是對象,參數(shù)不要采用boolean這種難以擴展的數(shù)據(jù)類型。 邏輯層的接口設計,一般有粗粒度和細粒度兩種模式。粗粒度接口的優(yōu)點是交互少,一次調用基本可以滿足需求,缺點是業(yè)務邏輯較多,所以不穩(wěn)定性增加,這里的不穩(wěn)定性不僅是系統(tǒng)穩(wěn)定性,還包括業(yè)務邏輯的穩(wěn)定性。細粒度接口交互較多,但更加有利于重用性。 細粒度接口多次交互是否會帶來明顯的性能損耗呢?目前服務器1秒可以執(zhí)行近萬次TCP連接,網(wǎng)絡傳輸對于千兆網(wǎng)卡而言,一般也不會造成瓶頸,尤其RPC框架般都會保持長連接。因此,通常情況下我們可以忽略RPC調用帶來的性能損耗。 邏輯層接口盡量采用大系統(tǒng)小做的原則,該原則是騰訊架構中重要的價值觀。一個接口不做太多事情,只做關鍵路徑,非關鍵邏輯可以用消息隊列或事件通知等方式剝離出來,使得關鍵路徑更加穩(wěn)定。這也體現(xiàn)了服務分級的思想,把最大的精力花在最重要的接口上。 除了按重要性劃分服務之外,也可以按接入方劃分,避免不同終端的Bug影響。還可以按快慢劃分,例如為上傳文件等功能提供單獨的服務,避免長時間占用線程,影響系統(tǒng)穩(wěn)定性。 模塊化是程序的水平切分,有時也會采用垂直切分,這種架構有以下好處。 系統(tǒng)規(guī)模更方便水平擴展,數(shù)據(jù)處理能力會顯著增加。例如某個模塊的容量不足,可以單獨擴容該模塊。 減少系統(tǒng)耦合,提升穩(wěn)定性。例如將多變的Web層和穩(wěn)定的數(shù)據(jù)層進行拆分,可以避免因為頁面頻繁發(fā)布導致的系統(tǒng)故障;將無線的接入層和Web接入層分離可以減少因為一個接入方引起的全局問題。 開放勢不可擋 系統(tǒng)發(fā)展往往會帶來平臺化需求,例如微博的大多數(shù)服務除了滿足PC訪問,還要滿足移動端及內外部平臺,此時系統(tǒng)通常會抽象出一個接入層。 接入層設計 接入層一般分為:通信、協(xié)議和路由模塊。 常用的通信方式有TCP、UDP和HTTP等,對開放平臺等以外圍接入為主的系統(tǒng)而言,HTTP因其簡單方便是最合適的通信方式,而內部系統(tǒng)接入出于性能考量,可以直接用TCP或者UDP。 目前的主流協(xié)議有JSON、XML、Hessian等,對外部調用一般采用XML或者JSON,內部系統(tǒng)可以采用Hessian或其他自定義的二進制協(xié)議。 路由層是根據(jù)用戶的信息將請求轉發(fā)到后端服務層。LVS可看作是路由層,根據(jù)IP協(xié)議將不同來源的請求轉發(fā)到不同IP Server,Nginx等具備反向代理的服務器也可以看作路由,根據(jù)不同URL轉發(fā)到不同后端。我們經常會自定義路由層,通過用戶調用的不同方法轉發(fā)到 不同Server,或者根據(jù)用戶的特征,將用戶路由到我們的灰度測試機。 云平臺概念 具有了平臺化的接入功能,系統(tǒng)可以方便地接入內部或者外部系統(tǒng),此時就具有了"云"的特征,對各種公有云或私有云來說,系統(tǒng)的隔離和自動擴容都十分重要,虛擬化等技術在該類系統(tǒng)中有了充分應用,例如阿里云等云平臺都大量使用了虛擬化。 穩(wěn)定壓倒一切 代碼穩(wěn)定性 穩(wěn)定性是系統(tǒng)架構中一以貫之的內容,可以從圖4中理解它的含義。 正常情況下,圖4左邊系統(tǒng)的性能明顯優(yōu)于右邊,但從架構角度考慮,右圖要好于左圖,因為突起的毛刺使得系統(tǒng)的容量驟降,很容易引發(fā)雪崩。性能考量不僅是系統(tǒng)的最優(yōu)性能或者平均性能,最差性能往往也是系統(tǒng)出現(xiàn)問題的原因。 圖4 兩種穩(wěn)定性對比 容災 除了特別小型的系統(tǒng),沒有100%可用的系統(tǒng)。一般需要根據(jù)系統(tǒng)的情況制定合適的目標,該目標最通用的衡量維度是系統(tǒng)可用率。 系統(tǒng)可用率是可以提供服務的時間與總時間的比率,常用的系統(tǒng)可用率如表1所示。 而對于災難,我們有下面幾個環(huán)節(jié)可以介入。 預防:容量估算和接入方限流是常用的手段,以應對宕機或者突發(fā)流量。 發(fā)現(xiàn):主要依賴監(jiān)控和各種工具,可以分為系統(tǒng)、接口、公共組件、業(yè)務等方面。 解決:應對災難需要我們事先做足功課,例如對外部的調用我們都有降級開關可以隨時關閉;針對系統(tǒng)內部某個接口導致整個系統(tǒng)失去響應的場景,可以限制每個接口的并發(fā)量。 系統(tǒng)容量的冗余和可水平擴展也是容災的必備要求,無狀態(tài)的系統(tǒng)對于系統(tǒng)擴容更友好。 作者楊光輝,淘寶北京研發(fā)中心技術專家,花名三玄。曾在互動百科、騰訊科技等公司任職,對服務器端架構和開發(fā)等有一定研究。 本文為《程序員》原創(chuàng)文章,未經允許不得轉載,如需轉載請聯(lián)系market#csdn.net(#換成@) 原文地址:http://iphone.myzaker.com/l.php?l=521eadaa81853d141800008e 該文章在 2013/10/9 21:54:15 編輯過 |
關鍵字查詢
相關文章
正在查詢... |