以淘寶網為例,簡單了解一下大型電商的服務端架構是怎樣的。如圖所示
最上面的就是安全體系系統,中間的就是業務營運系統,包含各個不同的業務服務,下面是一些共享服務,然後還有一些中間件,其中 ECS 就是雲伺服器,MQS 是隊列服務,OCS 是緩存等等,右側是一些支撐體系服務。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLi0zaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLwkzX39GZhh2csATMflHLwEzX4xSZz91ZsADMx8FdsYkRGZkRG9lcvx2bjxSa2EWNhJTW1AlUxEFeVRUUfRHelRHL2EzXlpXazxyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3PnVGcq5CNiNGMiFDZjFWMlZWZ4gzYxcDMhRmNkdzYxIGZxYzN48CX4AzLcdDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL0M3Lc9CX6MHc0RHaiojIsJye.jpeg)
除圖中所示之外還包含一些我們看不到的,比如高可用的展現。淘寶目前已經實作多機房容災和異地機房單元化部署,為淘寶的業務也提供了穩定、高效和易于維護的基礎架構支撐。
這是一個含金量非常高的架構,也是一個非常複雜而龐大的架構,當然這個架構不是一天兩天演進成這樣的,也不是一開始就設計并開發成這樣的,對于初創公司而言,很難在初期就預估到未來流量千倍、萬倍的網站架構會是怎樣的狀況,同時如果初期就設計成千萬級并發的流量架構,也很難去支撐這個成本。
是以一個大型服務系統,都是從小一步一步走過來的,在每個階段找到對應該階段網站架構所面臨的問題,然後不斷解決這些問題,在這個過程中,整個架構會一直演進,同時内含的代碼也就會演進,大到架構、小到代碼都是在不斷演進和優化的。是以說高大上的項目技術架構和開發設計實作不是一蹴而就的,這是所謂的萬丈高樓平地起。
從一個小網站說起,一般來說初始一台伺服器就夠了,檔案伺服器、資料庫以及應用都部署在一台機器上。也就是俗稱的 allinone 架構。
随着網站使用者逐漸增多,通路量越來越大,硬碟、cpu、記憶體等開始吃緊,一台伺服器難以支撐。看一下演進過程,我們将資料服務和應用服務進行分離,給應用伺服器配置更好的 cpu、記憶體等等,而給資料伺服器配置更好、更快的大的硬碟,如圖所示用了三台伺服器進行部署,能提高一定的性能和可用性。
随着通路的并發越來越高,為了降低接口的通路時間提高服務性能,繼續對架構進行演進。
我們發現有很多業務資料不需要每次都從資料庫中擷取,于是我們使用了緩存,因為 80% 的業務通路都集中在 20% 的資料上 (二八原則),如果能将這部分資料緩存下來,性能就能提高很多,緩存又分兩種,一種是 Application 中的本地緩存,還有遠端緩存,遠端緩存又分為遠端的單機式緩存和分布式緩存 (圖所示的是分布式緩存叢集)。
我們需要思考幾點,具有哪種業務特點的資料使用緩存,具有哪種業務特點的資料使用本地緩存,具有哪種業務特點的資料使用遠端緩存。分布式緩存在擴容時會遇上什麼問題,如何解決,分布式緩存的算法都有哪幾種,都有什麼優缺點。這些問題都是我們在使用這個架構時需要思考并解決的問題。
這個時候随着通路的 qps 不斷提高,假設我們使用的 Application Server 是 tomcat,那麼 tomcat 伺服器的處理能力就會成為一個瓶頸,雖然我們也可以通過購買更強大的硬體但總會有上限,并且這個成本到後期是呈指數級的增長。
這時候就可以對伺服器做一個叢集 (cluster),然後添加負載均衡排程器 (LoadBalancer),伺服器叢集後我們就可以橫向擴充我們的伺服器了,解決了伺服器處理能力的瓶頸。
此時我們又需要思考幾個問題, 負載均衡的排程政策都有哪些,各有什麼優缺點,各适合什麼場景,比如輪詢、權重、位址散列,位址散列又分為原 IP 位址散列、目标 IP 位址散列、最小連接配接、權重最小連接配接等等。
伺服器叢集後,假設我們登陸了 A 伺服器,session 資訊存放在 A 伺服器上了,如果我們的負載均衡政策是輪詢或者最小連接配接等,下次是有可能通路到 B 伺服器,這時候存儲在 A 伺服器上的 session 資訊我們在 B 伺服器是讀取不到的,是以我們需要解決 session 管理的問題。
我們使用 session sticky這種方式來解決這個問題,它的處理規則是對于同一個連接配接中的資料包,負載均衡會将其進行 NAT 轉換後,轉發至後端固定的伺服器進行處理,這種方案解決了 session 共享的問題。
如圖所示用戶端 1 通過負載均衡會固定轉發到伺服器 1 中。缺點是第一假設有一台伺服器重新開機了,那麼該伺服器的 session 将全部消失,第二是我們的負載均衡伺服器成了一種有狀态的伺服器,要實作容災會有麻煩。
session 複制,即當 browser1 經過負載均衡伺服器把 session 存到 application1 中,會同時把 session 複制到 application2 中,是以多台伺服器都儲存着相同的 session 資訊。
缺點是應用伺服器的帶寬問題,伺服器之間要不斷同步 session 資訊,當大量使用者線上時,伺服器占用記憶體會過多,不适合大規則叢集,适合機器不多情況。
基于 cookie,也就是說我們每次都用攜帶 session 資訊的 cookie 去通路應用伺服器。缺點是 cookie 的長度是有限制的,cookie 儲存在浏覽器上安全性也是一個問題。
把 session 做成了一個 session 伺服器,比如可以使用 redis 實作。這樣每個使用者通路到應用伺服器,其 session 資訊最終都存到 session server 中,應用伺服器也是從 session server 中去擷取 session。
要考慮以下幾個問題,在目前架構中 session server 是一個單點的,如何解決單點,保證它的可用性,當然也可以将 session server 做成一個叢集,這種方式适用于 session 數量及 web 伺服器數量大的情況,同時改成這種架構後,在寫應用時,也要調整存儲 session 的業務邏輯。
在解決了伺服器橫向擴充之後,繼續看資料庫,資料庫的讀與寫操作都需要經過資料庫,當使用者量達到一定量時,資料庫性能又成為了一個瓶頸,我們繼續演進。
我們可以使用資料庫的讀寫分離,同時應用要接入多資料源。通過統一的資料通路模型進行通路。資料庫的讀寫分離是将所有的寫操作引入到主庫中 (master),将讀操作引入到從庫中 (slave),此時應用程式也要做出相應的變化,我們實作了一個資料通路子產品 (data accessmodule),使上層寫代碼的人不知道讀寫分離的存在,這樣多資料源的讀寫對業務代碼就沒有侵入,這就是代碼層面的演變。
如何支援多資料源,如何封裝對業務沒有侵入,如何使用目前業務使用的 ORM 架構完成主從的讀寫分離,是否需要更換 ORM,各有什麼優缺點,如何取舍都是目前這個架構需要考慮的問題。
當通路量過大時候,也就是說資料庫的 IO 非常大,我們的資料庫讀寫分離又會遇到以下問題?
例如主庫和從庫複制有沒有延遲,如果我們将主庫和從庫分機房部署的話,跨機房傳輸同步資料更是一個問題。另外應用對資料源的路由問題,這些也是需要思考和解決的點。
我們繼續增加了 CDN和反向代理伺服器 (Reverseproxy server),使用 CDN可以很好的解決不同地區通路速度問題,反向代理則在伺服器機房中可以緩存使用者的資源。
這個時候我們的檔案伺服器又出現了瓶頸,我們将檔案伺服器改成了分布式檔案伺服器叢集,在使用分布式檔案系統時,需要考慮幾個問題,如何不影響部署線上上的應用通路,是否需要業務部門幫忙清洗資料,是否需要備份伺服器,是否需要重新做域名解析等等。
這個時候我們的資料庫又出現了瓶頸,我們選擇專庫專用的形式,進行資料的垂直拆分,相關的業務獨用自己的一個庫,我們解決了寫資料并發量大的問題。
當我們把這些表分成不同的庫,又會帶來一些新的問題。例如跨業務和跨庫的事務,可以使用分布式事務,或者去掉事務,或者不追求強事務。
随着通路量過大,資料量過大,某個業務的資料庫資料量和更新量已經達到了單個資料庫的瓶頸了,這個時候就需要進行資料庫的水準拆分,例如把 user 拆分成了 user1 和 user2,就是将同一個表的資料拆分到兩個資料庫當中,這個時候我們解決了單資料庫的瓶頸。
水準拆分時候又要注意哪些點,都有哪幾種水準拆分的方式。進行了水準拆分後,又會遇到幾個問題,第一 sql 路由的問題,假設有一個使用者,我們如何知道這個使用者資訊是存在了 user1 還是 user2 資料庫中,由于分庫了,我們的主鍵政策也會有所不同,同時會面臨分頁的問題,假設我們要查詢某月份已經下單的使用者明細,而這些使用者又分布在 user1 和 user2 庫中,我們背景營運管理系統對它進行展示的時候還要進行分頁。這些都是我們在使用這個架構時需要解決的問題。
在網站釋出并進行了大規模的推廣後,導緻我們應用伺服器的搜尋量又飙升,我們把應用伺服器的搜尋功能單獨抽取出來做了一個搜尋引擎,同時部分場景可以使用 NoSQL來提高性能。同時我們開發一個資料統一的通路子產品,同時連着資料庫叢集、搜尋引擎和 NoSQL,解決上層應用開發的資料源問題。
這裡隻是簡單舉例,并沒有依據什麼實際的業務場景。事實上各個服務的架構是要根據實際的業務特點進行優化和演進的,是以這個過程也不是完全相同的。當然這個架構也不是最終形态,還存在很多要提升的地方。
例如負載均衡伺服器目前是一個單點的,如果負載均衡伺服器通路不了,那麼後續的包括伺服器叢集等也就無法通路了。是以可以将負載均衡伺服器做成叢集,然後做一些主從的雙機熱備,同時做一個自動切換的解決方案。
在整個架構的演進過程中,其實還包含更多需要關注的内容,比如安全性、資料分析、監控、反作弊......
針對一些特定的場景例如交易、充值、流計算等使用消息隊列、任務排程......
整個架構繼續發展下去,做成 SOA 架構、服務化 (微服務)、多機房......
最後,我想說高大上的項目技術架構和開發設計實作絕不是一僦而就的。
END