1. 程式人生 > >Java高並發高性能分布式框架從無到有微服務架構設計

Java高並發高性能分布式框架從無到有微服務架構設計

創建 最終 轉移 lis 分布式 err 靜態頁面 提升性能 squid

微服務架構模式(Microservice Architect Pattern)。近兩年在服務的瘋狂增長與雲計算技術的進步,讓微服務架構受到重點關註

微服務架構是一種架構模式,它提倡將單一應用程序劃分成一組小的服務,服務之間互相協調、互相配合,為用戶提供最終價值。每個服務運行在其獨立的進程中,服務與服務間采用輕量級的通信機制互相溝通(通常是基於HTTP的RESTful API)。每個服務都圍繞著具體業務進行構建,並且能夠被獨立地部署到生產環境、類生產環境等。另外,應盡量避免統一的、集中式的服務管理機制,對具體的一個服務而言,應根據業務上下文,選擇合適的語言、工具對其進行構建。

微服務架構優勢

首先簡單介紹了微服務(Microservices)的內涵及優勢,微服務架構的本質,是用一些功能比較明確、業務比較精練的服務去解決更大、更實際的問題。微服務架構將服務拆分,分別采用相對獨立的服務對各方面進行管理,彼此之間使用統一的接口來進行交流,架構變得復雜,優勢也很明顯:

復雜度可控:在將應用分解的同時,規避了原本復雜度無止境的積累。每一個微服務專註於單一功能,並通過定義良好的接口清晰表述服務邊界。由於體積小、復雜度低,每個微服務可由一個小規模開發團隊完全掌控,易於保持高可維護性和開發效率。

什麽是微服務架構

微服務架構優勢

獨立部署:由於微服務具備獨立的運行進程,所以每個微服務也可以獨立部署。當某個微服務發生變更時無需編譯、部署整個應用。由微服務組成的應用相當於具備一系列可並行的發布流程,使得發布更加高效,同時降低對生產環境所造成的風險,最終縮短應用交付周期。

技術選型靈活:微服務架構下,技術選型是去中心化的。每個團隊可以根據自身服務的需求和行業發展的現狀,自由選擇最適合的技術棧。由於每個微服務相對簡單,當需要對技術棧進行升級時所面臨的風險較低,甚至完全重構一個微服務也是可行的。

容錯:當某一組建發生故障時,在單一進程的傳統架構下,故障很有可能在進程內擴散,形成應用全局性的不可用。在微服務架構下,故障會被隔離在單個服務中。若設計良好,其他服務可通過重試、平穩退化等機制實現應用層面的容錯。

擴展:單塊架構應用也可以實現橫向擴展,就是將整個應用完整的復制到不同的節點。當應用的不同組件在擴展需求上存在差異時,微服務架構便體現出其靈活性,因為每個服務可以根據實際需求獨立進行擴展。

互聯網高並發相關名詞

頁面瀏覽數(page views )

唯一身份瀏覽量(Unique PageViews)

獨立訪問者數量(unique visitors)

重復訪問者數量(repeat visitors)

每個訪問者的頁面瀏覽數(Page Views per user)

高並發

之前我將高並發的解決方法誤認為是線程或者是隊列可以解決,因為高並發的時候是有很多用戶在訪問,導致出現系統數據不正確、丟失數據現象,所以想到 的是用隊列解決,其實隊列解決的方式也可以處理,比如我們在競拍商品、轉發評論微博或者是秒殺商品等,同一時間訪問量特別大,隊列在此起到特別的作用,將 所有請求放入隊列,以毫秒計時單位,有序的進行,從而不會出現數據丟失系統數據不正確的情況。

經過查資料,高並發的解決方法有倆種,一種是使用緩存、另一種是使用生成靜態頁面;還有就是從最基礎的地方優化我們寫代碼減少不必要的資源浪費:(

1.不要頻繁的new對象,對於在整個應用中只需要存在一個實例的類使用單例模式.對於String的連接操作,使用StringBuffer或者StringBuilder.對於utility類型的類通過靜態方法來訪問。

避免使用錯誤的方式,如Exception可以控制方法推出,但是Exception要保留stacktrace消耗性能,除非必要不要使用 instanceof做條件判斷,盡量使用比的條件判斷方式.使用JAVA中效率高的類,比如ArrayList比Vector性能好。)

高並發 - 需要解決的問題

一:應用緩存

二:HTTP緩存

三:多級緩存

四:池化

五:異步並發

六:擴容

七:隊列

高並發-應用緩存

堆緩存

使用Java堆內存來存儲緩存對象。使用堆緩存的好處是沒有序列化/反序列化,是最快的緩存。缺點也很明顯,當緩存的數據量很大時,GC(垃圾回收)暫停時間會變長,存儲容量受限於堆空間大小。一般通過軟引用/弱引用來存儲緩存對象,即當堆內存不足時,可以強制回收這部分內存釋放堆內存空間。一般使用堆緩存存儲較熱的數據。有

Guava Cache: 緩存和ConcurrentMap是非常相像的,但是它們也不完全一樣。最根本的區別就是,ConcurrentMap會持有所有添加的對象,直到被顯示的移除。而緩存為了限制其內存的使用,通常都會配置成可以自動的將對象移除。在某些情況下即使不自動移除對象也是非常有用的,如LoadingCache它會自動加載緩存對象。

Ehcache 3.x:是一種廣泛使用的開源Java分布式緩存。主要面向通用緩存,Java EE和輕量級容器。它具有內存和磁盤存儲,緩存加載器,緩存擴展,緩存異常處理程序,一個gzip緩存servlet過濾器,支持REST和SOAP api等特點。

MapDB: mapdb是一個內嵌的純java的數據庫,提供了並發的HashMap、TreeMap、Queue,可以基於堆外或者磁盤來存儲數據

高並發-應用緩存

堆外緩存

即緩存數據存儲在堆外內存,可以減少GC暫停時間(堆對象轉移到堆外,GC掃描和移動的對象變少),但是,讀取數據時需要序列化/反序列化,因此會比堆緩存要慢很多。有Ehcache 3.x、MapDB實現

磁盤緩存

即緩存數據存儲在磁道上,在JVM重啟時數據還存在的,而堆緩存/堆外緩存數據會丟失,需要重新加載。有Ehcache 3.x、MapDB實現

分布式緩存

進程內緩存和磁盤緩存,在多JVM實例的情況下,會存在兩個問題:

1、單機容量問題;

2、數據一致性問題(多臺JVM實例的緩存數據不一致怎麽辦?),這個問題不用糾結,既然數據允許緩存,則表示允許一定時間內的不一致,因此可以設置緩存數據的過期時間來定期更新數據;

3、緩存不命中時,需要回源到DB/服務請求多變問題:每個實例在緩存不命中的情況下都會回源到DB加載數據,因此多實例後DB整體的訪問量變多了解決辦法是可以使用如一致性哈希分片算法。因此,這些情況可以考慮使用分布式緩存來解決。

可以使用ehcache –clustered(配合 Terracotta server) 實現JAVA進程間分布式緩存。最好的辦法是使用redis實現分布式緩存。

高並發- HTTP緩存

瀏覽器緩存是指當我們使用瀏覽器訪問一些網站頁面或者http服務時,根據服務端返回的緩存設置響應頭將響應內容緩存到瀏覽器,下次可以直接使用緩存內容或者僅需要去服務端驗證內容是否過期即可。這樣的好處可以減少瀏覽器和服務端之間來回傳輸的數據量,節省帶寬提升性能。

解決辦法:內容不需要動態(計算、渲染等)速度更快,內容越接近於用戶速度越快。像apache traffic server、squid、varnish、nginx等技術都可以來進行內容緩存。還有CDN就是用來加速用戶訪問的:

技術分享圖片

即用戶首先訪問到全國各地的CDN節點(使用如ATS、Squid實現),如果CDN沒命中,會回源到中央nginx集群,該集群如果沒有命中緩存(該集群的緩存不是必須的,要根據實際命中情況等決定),最後回源到後端應用集群。

高並發- 多級緩存(分布式緩存)

技術分享圖片

高並發-池化

在應用系統開發過程中,我們經常會用到池化技術,如對象池、連接池、線程池等,通過池化來減少一些消耗,以提升性能。

對象池通過復用對象從而減少創建對象、垃圾回收 的開銷。但是,池化不能太大,太大會影響GC時的掃描時間。

Java高並發高性能分布式框架從無到有微服務架構設計