以淘寶網爲例,解析大型Java項目架構演進

  • 若汐緣

  • https://www.jianshu.com/p/796f488fd134

前言

以淘寶網爲例,簡單瞭解一下大型電商的服務端架構是怎樣的。如圖所示
最上面的就是安全體系系統,中間的就是業務運營系統,包含各個不同的業務服務,下面是一些共享服務,然後還有一些中間件,其中 ECS 就是雲服務器,MQS 是隊列服務,OCS 是緩存等等,右側是一些支撐體系服務。

除圖中所示之外還包含一些我們看不到的,比如高可用的體現。淘寶目前已經實現多機房容災和異地機房單元化部署,爲淘寶的業務也提供了穩定、高效和易於維護的基礎架構支撐。

這是一個含金量非常高的架構,也是一個非常複雜而龐大的架構,當然這個架構不是一天兩天演進成這樣的,也不是一開始就設計並開發成這樣的,對於初創公司而言,很難在初期就預估到未來流量千倍、萬倍的網站架構會是怎樣的狀況,同時如果初期就設計成千萬級併發的流量架構,也很難去支撐這個成本。

因此一個大型服務系統,都是從小一步一步走過來的,在每個階段找到對應該階段網站架構所面臨的問題,然後不斷解決這些問題,在這個過程中,整個架構會一直演進,同時內含的代碼也就會演進,大到架構、小到代碼都是在不斷演進和優化的。所以說高大上的項目技術架構和開發設計實現不是一蹴而就的,這是所謂的萬丈高樓平地起。

單機架構

從一個小網站說起,一般來說初始一臺服務器就夠了,文件服務器、數據庫以及應用都部署在一臺機器上。也就是俗稱的 allinone 架構。

多機部署

隨着網站用戶逐漸增多,訪問量越來越大,硬盤、cpu、內存等開始喫緊,一臺服務器難以支撐。看一下演進過程,我們將數據服務和應用服務進行分離,給應用服務器配置更好的 cpu、內存等等,而給數據服務器配置更好、更快的大的硬盤,如圖所示用了三臺服務器進行部署,能提高一定的性能和可用性。

分佈式緩存

隨着訪問的併發越來越高,爲了降低接口的訪問時間提高服務性能,繼續對架構進行演進。

我們發現有很多業務數據不需要每次都從數據庫中獲取,於是我們使用了緩存,因爲 80% 的業務訪問都集中在 20% 的數據上 (二八原則),如果能將這部分數據緩存下來,性能就能提高很多,緩存又分兩種,一種是 Application 中的本地緩存,還有遠程緩存,遠程緩存又分爲遠程的單機式緩存和分佈式緩存 (圖所示的是分佈式緩存集羣)。

我們需要思考幾點,具有哪種業務特點的數據使用緩存,具有哪種業務特點的數據使用本地緩存,具有哪種業務特點的數據使用遠程緩存。分佈式緩存在擴容時會遇上什麼問題,如何解決,分佈式緩存的算法都有哪幾種,都有什麼優缺點。這些問題都是我們在使用這個架構時需要思考並解決的問題。

服務器集羣

這個時候隨着訪問的 qps 不斷提高,假設我們使用的 Application Server 是 tomcat,那麼 tomcat 服務器的處理能力就會成爲一個瓶頸,雖然我們也可以通過購買更強大的硬件但總會有上限,並且這個成本到後期是呈指數級的增長。

這時候就可以對服務器做一個集羣 (cluster),然後添加負載均衡調度器 (LoadBalancer),服務器集羣后我們就可以橫向擴展我們的服務器了,解決了服務器處理能力的瓶頸。

此時我們又需要思考幾個問題, 負載均衡的調度策略都有哪些,各有什麼優缺點,各適合什麼場景,比如輪詢、權重、地址散列,地址散列又分爲原 IP 地址散列、目標 IP 地址散列、最小連接、加權最小連接等等。

服務器集羣后,假設我們登陸了 A 服務器,session 信息存放在 A 服務器上了,如果我們的負載均衡策略是輪詢或者最小連接等,下次是有可能訪問到 B 服務器,這時候存儲在 A 服務器上的 session 信息我們在 B 服務器是讀取不到的,所以我們需要解決 session 管理的問題。

Session 共享解決方案

session sticky

我們使用 session sticky這種方式來解決這個問題,它的處理規則是對於同一個連接中的數據包,負載均衡會將其進行 NAT 轉換後,轉發至後端固定的服務器進行處理,這種方案解決了 session 共享的問題。

如圖所示客戶端 1 通過負載均衡會固定轉發到服務器 1 中。缺點是第一假設有一臺服務器重啓了,那麼該服務器的 session 將全部消失,第二是我們的負載均衡服務器成了一種有狀態的服務器,要實現容災會有麻煩。

session 複製

session 複製,即當 browser1 經過負載均衡服務器把 session 存到 application1 中,會同時把 session 複製到 application2 中,所以多臺服務器都保存着相同的 session 信息。

缺點是應用服務器的帶寬問題,服務器之間要不斷同步 session 信息,當大量用戶在線時,服務器佔用內存會過多,不適合大規則集羣,適合機器不多情況。

基於 cookie

基於 cookie,也就是說我們每次都用攜帶 session 信息的 cookie 去訪問應用服務器。缺點是 cookie 的長度是有限制的,cookie 保存在瀏覽器上安全性也是一個問題。

session 服務器

把 session 做成了一個 session 服務器,比如可以使用 redis 實現。這樣每個用戶訪問到應用服務器,其 session 信息最終都存到 session server 中,應用服務器也是從 session server 中去獲取 session。

要考慮以下幾個問題,在當前架構中 session server 是一個單點的,如何解決單點,保證它的可用性,當然也可以將 session server 做成一個集羣,這種方式適用於 session 數量及 web 服務器數量大的情況,同時改成這種架構後,在寫應用時,也要調整存儲 session 的業務邏輯。

數據庫讀寫分離

在解決了服務器橫向擴展之後,繼續看數據庫,數據庫的讀與寫操作都需要經過數據庫,當用戶量達到一定量時,數據庫性能又成爲了一個瓶頸,我們繼續演進。

我們可以使用數據庫的讀寫分離,同時應用要接入多數據源。通過統一的數據訪問模型進行訪問。數據庫的讀寫分離是將所有的寫操作引入到主庫中 (master),將讀操作引入到從庫中 (slave),此時應用程序也要做出相應的變化,我們實現了一個數據訪問模塊 (data accessmodule),使上層寫代碼的人不知道讀寫分離的存在,這樣多數據源的讀寫對業務代碼就沒有侵入,這就是代碼層面的演變。

如何支持多數據源,如何封裝對業務沒有侵入,如何使用目前業務使用的 ORM 框架完成主從的讀寫分離,是否需要更換 ORM,各有什麼優缺點,如何取捨都是當前這個架構需要考慮的問題。
當訪問量過大時候,也就是說數據庫的 IO 非常大,我們的數據庫讀寫分離又會遇到以下問題?

例如主庫和從庫複製有沒有延遲,如果我們將主庫和從庫分機房部署的話,跨機房傳輸同步數據更是一個問題。另外應用對數據源的路由問題,這些也是需要思考和解決的點。

CDN 加速與反向代理

我們繼續增加了 CDN和反向代理服務器 (Reverseproxy server),使用 CDN可以很好的解決不同地區訪問速度問題,反向代理則在服務器機房中可以緩存用戶的資源。

分佈式文件服務器

這個時候我們的文件服務器又出現了瓶頸,我們將文件服務器改成了分佈式文件服務器集羣,在使用分佈式文件系統時,需要考慮幾個問題,如何不影響部署在線上的應用訪問,是否需要業務部門幫忙清洗數據,是否需要備份服務器,是否需要重新做域名解析等等。

數據庫分庫分表

這個時候我們的數據庫又出現了瓶頸,我們選擇專庫專用的形式,進行數據的垂直拆分,相關的業務獨用自己的一個庫,我們解決了寫數據併發量大的問題。

當我們把這些表分成不同的庫,又會帶來一些新的問題。例如跨業務和跨庫的事務,可以使用分佈式事務,或者去掉事務,或者不追求強事務。

隨着訪問量過大,數據量過大,某個業務的數據庫數據量和更新量已經達到了單個數據庫的瓶頸了,這個時候就需要進行數據庫的水平拆分,例如把 user 拆分成了 user1 和 user2,就是將同一個表的數據拆分到兩個數據庫當中,這個時候我們解決了單數據庫的瓶頸。

水平拆分時候又要注意哪些點,都有哪幾種水平拆分的方式。進行了水平拆分後,又會遇到幾個問題,第一 sql 路由的問題,假設有一個用戶,我們如何知道這個用戶信息是存在了 user1 還是 user2 數據庫中,由於分庫了,我們的主鍵策略也會有所不同,同時會面臨分頁的問題,假設我們要查詢某月份已經下單的用戶明細,而這些用戶又分佈在 user1 和 user2 庫中,我們後臺運營管理系統對它進行展示的時候還要進行分頁。這些都是我們在使用這個架構時需要解決的問題。

搜索引擎與 NoSQL

在網站發佈並進行了大規模的推廣後,導致我們應用服務器的搜索量又飆升,我們把應用服務器的搜索功能單獨抽取出來做了一個搜索引擎,同時部分場景可以使用 NoSQL來提高性能。同時我們開發一個數據統一的訪問模塊,同時連着數據庫集羣、搜索引擎和 NoSQL,解決上層應用開發的數據源問題。

後序

這裏只是簡單舉例,並沒有依據什麼實際的業務場景。事實上各個服務的架構是要根據實際的業務特點進行優化和演進的,所以這個過程也不是完全相同的。當然這個架構也不是最終形態,還存在很多要提升的地方。

例如負載均衡服務器目前是一個單點的,如果負載均衡服務器訪問不了,那麼後續的包括服務器集羣等也就無法訪問了。所以可以將負載均衡服務器做成集羣,然後做一些主從的雙機熱備,同時做一個自動切換的解決方案。

在整個架構的演進過程中,其實還包含更多需要關注的內容,比如安全性、數據分析、監控、反作弊......
針對一些特定的場景例如交易、充值、流計算等使用消息隊列、任務調度......
整個架構繼續發展下去,做成 SOA 架構、服務化 (微服務)、多機房......

最後,我想說高大上的項目技術架構和開發設計實現絕不是一僦而就的。

END

版權申明:內容來源網絡,版權歸原創者所有。除非無法確認,我們都會標明作者及出處,如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝。


如果你覺得文章不錯
記得給我「點贊」和「在看」哦~

本文分享自微信公衆號 - JAVA高級架構(gaojijiagou)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章