大型Java項目架構演進

大型Java項目架構演進過程

1. All-In-One (所有服務在一臺服務器上):

   也就是所有的服務都在同一個服務器上,包括應用服務器、文件服務器和數據庫

6e96d67e9ab768800dfaaeeefc4cfb9ede1.jpg

2. 各服務分別部署在不同的服務器上

    隨着用戶越來越多,訪問量越來越大,硬盤、CPU、內存等硬件開始吃緊,一臺服務器已經無法滿足需求,這個時候就需要將不同的服務部署在多個服務器上,給應用服務(Application server)配置更好的內存和cpu,給數據庫服務器配置更好,更大,更快的硬盤。

e53071a73710771400b59420b38ea5aff69.jpg

3. 添加緩存服務器:

    隨着訪問的併發越來越高,爲了縮短接口的訪問時間,提高訪問性能。

    同時發現,我們的很多業務數據不需要每次都從數據庫中獲取,於是我們使用緩存來進行數據緩存,提高訪問速度。

    (80%的業務集中在20%的數據上,即2--8原則)

342c34ab5fa3ddadf8f00c80ba391d7734d.jpg

    在這裏緩存又可以分爲  本地緩存遠程緩存。 同時,遠程緩存又有兩種情形:單機緩存分佈式集羣緩存

    使用該架構需要思考和解決的問題:

        1. 哪種業務特點的數據需要進行緩存

        2. 哪些數據適合進行本地緩存,哪些數據適合進行遠程緩存

        3. 分佈式緩存在擴容時會遇到什麼問題,如果解決

        4. 分佈式緩存的算法都有哪幾種,各有什麼優缺點

 

4. 增加負載均衡器,服務器均衡:

    隨着訪問的QPS(每秒查詢率)不斷的提高,服務器的處理能力(例如Tomcat)可能就會出現瓶頸,雖然也可以購買更加強大的硬件,但總會有上限,而且這個成本到了後期會出現指數級的增長,這個時候就需要做一個服務器的集羣,通過負責均衡服務器來實現服務集羣訪問。

6b67860f4bff2fa0819501bef3585ea8636.jpg

    這個時候需要考慮的問題:

        1. 負責均衡的調度策略都有哪些,各有什麼優缺點,各適合什麼場景。

         調度策略: 輪訓、權重、地址散列(包含:源ip散列 和 目的ip散列)、最少連接、加權最少連接

        2. session的管理問題

            同一用戶可能第一次登陸的是A服務器,那麼session信息是保存在A服務器上的,第二次可能訪問的是B服務器,這個時候B服務器上並沒有該用戶的session信息,這時就涉及到了session管理的問題問題。

        方式1. 可以使用 Session Sticky(粘滯會話)

            56492eb4da8c94c50514f4ca811574486e9.jpg

            實現原理:對於同一連接中的數據包,負載均衡會將其進行一個轉化,然後轉發至後端固定的服務器上進行處理。也就像上圖所示,Browser1每次都會訪問Application1這個服務器。這個方案解決了session的共享問題。但是同時又有缺點:1. 如果Application1進行了重啓,那麼保存在其上的信息將會全部消失,2. 負載均衡器成爲了一個有狀態的服務器,要實現容災會有麻煩。

            方式2.  Session Copy

6abad3882e840d1898c1aa8eee275c7baf8.jpg

    實現原理:Application之間會copy自身保存的session到其他服務器上,使得用戶通過負載均衡不論將請求發送至哪個Application,該Application都有該用戶的session信息。缺點:1. 由於Application之間要不斷的同步session信息,可能造成帶寬不夠的問題。2. 當大量用戶在線的時候,Application會佔用大量的內存,不適合做大規模集羣。

方式3. 基於cookie

6ca677ce6331c44744ee957602914f4a507.jpg

        實現原理:用戶攜帶含有session信息的cookie去訪問Application。缺點:1. cookie的長度是有限制的  2. cookie保存在瀏覽器上,安全性是一個問題。

    方式4. 使用session服務器

f65ee7a06d9191839b63f4a34f729298a76.jpg

    實現原理:所有用戶的session信息都統一保存在session server中。缺點:1. session server是個單點的,如何解決該server的單點,保證其高可用性  

5. 數據庫的讀寫分離:

    當用戶量達到一定量的時候,數據庫的讀寫操作的都是同一個數據庫,這個時候數據庫就成爲了一個瓶頸,這個時候就可以進行數據庫的讀寫分離

37b2414622e8d8e7aa64962f402edf5aa59.jpg

        包含主庫和從庫,同時應用要接入多數據源,並且通過統一的數據訪問模型進行數據訪問,數據庫讀寫分離將所有的讀操作全部引入到Slave這個數據庫中,將所有的寫操作全部引入到Master這個數據庫中,同時由於進行了讀寫數據分離,我們在應用中實現了數據訪問模塊,使得上層寫代碼的人不知道數據讀寫分離的情況,這樣我們多數據源的讀寫對業務代碼就沒有了侵入。

        這個時候引申的問題就有:1. 如何支持多數據源,2. 如何封裝對業務沒有侵入,3. 如何使用目前項目使用的ORM框架完成底層的讀寫分離,4. 是否需要更換ORM,又各有什麼優缺點,如何取捨。

        當數據量非常大的時候,數據庫的讀寫分離又會遇到一下問題:1. 主庫和從庫在同步的時候,有沒有延時;如果我們將主庫和從庫進行了誇機房部署,那麼在跨機房數據傳輸的時候,延時更是一個問題。2. 應用對數據源的路由問題

 6. 曾加了CDN和反向代理服務器:

    爲了提高服務器,又增加了CDN 和反向代理服務器。使用CDN可以很好的解決不同地區訪問速度的問題;反向代理則可以緩存用戶的資源

99d0637a834fc737cd7bb19e141c268dad4.jpg

 

 7. 文件服務器改爲了分佈式文件服務器:

6c1353293de0e059e6a80c60aed9dbbfb65.jpg

    需要考慮的問題:1. 如何不影響已部署在線上的業務訪問(不能出現某個圖片不能訪問了),2. 是否需要業務部門幫忙清洗數據 3. 是否需要備份服務器 4. 是否需要重新做域名解析等等。

8. 數據庫分表:

    數據量大的時候,數據的增刪改查又出現了瓶頸,這個時候我們選擇使用專庫專用的方式,進行數據的垂直拆分,相關的業務都使用自己專有的庫。

e786a8bb5e35f094763127312601e19ba97.jpg

    需要考慮的問題:1. 跨業務的事物,誇庫的事物 (可以考慮分佈式事物,或者去掉事物,或者不追求強事物),2. 誇庫的join怎麼實現

9. 數據庫分表

    隨着訪問量過大,業務量過大,可能出現某個業務的數據庫的數據達到了單個數據庫的瓶頸,這個時候就要考慮進行數據庫的水平拆分(將同一個表的數據拆分到兩個數據庫中)

b6a136367b1827c82fc98d4360304b7fde1.jpg

        需要考慮的問題:1. sql路由的問題(假設查詢某個用戶,如何確定用戶在哪個數據庫中)2. 主見的策略會有所不同 3 分頁的問題

10. 添加了搜索引擎和NoSql服務器

        假如發現我們應用服務器上的搜索量飆升,或者因爲我們對外做了一個推廣,這個時候我們將Application中的搜索功能單獨拆分出來,做了一個搜索引擎,同時部分場景可以使用NoSql提高性能,同時我們開發一個統一的數據訪問模塊,這個某塊下面連着數據庫集羣、搜索引擎、還有NoSql,解決上層應用開發的數據源問題。

79af0e45454ee47cb1394536e118396f4c2.jpg

 

 

轉載於:https://my.oschina.net/Declan/blog/2222455