高效能、高流量Java Web站點打造的22條建議
從2005年-2013年,Ashwanth Fernando曾供職於Best Buy、Pearson VUE、Walgreens、Walmart eCommerce等多家知名公司,現在Apple從事高階工程師、平臺工程師一職,擁有豐富的高流量Web應用程式打造及架構經驗,近日Ashwanth撰文分享了他的高流量Web軟體打造經驗。
下為譯文
受Joshua Bloch寫的《Effective Java》啟發,我想分享自己關於建立高流量Web軟體的整體建議。這些術語中的一些可能不僅僅關於軟體設計也關於工程組織、文化等相關領域。
免責宣告
- 只代表個人觀點
- 如發現與現實情況相違背的原則,請謹慎對待,或使用一般認識
1. 考慮使用不止一個資料中心
在商務領域,一直存在許多恐怖的道聽途說,而這些恐慌都因為他們只使用了單一的資料中心。如果你想在自然災害或者電力供應故障中倖免,那麼請使用多於1個的資料中心,使用active-active模式來配置你所有的資料中心。雖然在開銷上可能會有所增加,但是比只使用單active的配置要值得多——因為在passive和active副本上,總會發現有些資料片不一致。
2. 考慮使用稀疏資料中心部署
不管是通過PaSS,還是運營團隊進行,當軟體叢集被部署到同一個資料中心的機架上時,確保這些機架使用不同的電力供應。你不可能保證機架供電的萬無一失,一旦失敗將會導致整個機架上伺服器的丟失,這個時候你絕對不會希望整個資料中心都只連在一個電路上。
3. 考慮使用私有云來組織資源
IaaS開源解決方案Openstack等其他的軟體至今尚未成熟,需要龐大的團隊來運營,在執行期間會產生各種各樣的問題,除非你有足夠的預算,否則別考慮建立一個私有的雲服務。然而,私有云可以提供眾多優勢。首先在部署方面就可以進行眾多的定製化,這遠比AWS或者是Rackspace貨架上的選擇要多。其次它允許你做許多的硬體定製化,就好比在硬體層次的Oracle就比準虛擬化環境快得多。
4. 考慮使用PaaS做解決方案
為軟體釋放投入巨量人力進行部署的日子已接近盡頭,各個機構在敏捷及快速市場投放上絞盡腦汁,而PaaS無疑會加速這個部署過程。它允許特性儘可能快的釋出,同時也能讓開發者得到極大的滿足。這是個非常好的開始,給予開發者部署集維護自己軟體的工具,這將給工作積極性帶來很大的提高。同時,越來越多的開發者甚至不願意加入沒有自動化軟體部署系統的公司。更少的領導,更簡化的環節,將給你帶來無與倫比的效率。
5. 如果使用Oracle或者MySQL,只做基於主鍵的查詢
只有在RAC中存在很少的Artifacts時,Oracle才能在流量高峰時獲得最佳效能。儘可能避免使用Referential Integrity、Triggers、Materialized Views、Views、Stored Procedures和其他的Oracle Artifacts。Triggers可以在從資料訪問層實現。Stored Procedures可以完全轉移到應用層。資料庫只用來儲存資料,基於欄位進行儲存而不是主鍵,使用類似Lucene的索引器做表的索引,使用一個允許在結果集上做基於其他欄位的查詢,這將會返回這個記錄的主鍵,而這個主關鍵字可以進一步被用來拿取記錄。
6. 考慮使用Oracle或者MySQL分片
當schema達到臨界點,Oracle的可伸縮性將被限制,這裡建議你對schema做基於功能(比如訂單,產品目錄,促銷活動,客戶等)上的分片,同時也為高密度表做key shards。為key shards使用一致性雜湊,這樣當一個新的RAC被新增RAC集時,你不再需要遍歷所有RAC中的鍵,以獲悉哪些鍵需要被移動到鍵的分片中。
7. 如果你使用Oracle做RDBMS,考慮使用Data Guard及Golden Gate
使用這兩種技術將大大簡化甲骨文的運營週期,Data Guard允許一個近實時passive讀副本(沒有客戶端會與之連線),而Golden Gate則允許一個近實時的active讀寫副本。
推薦的部署拓撲之一就是為同個資料中心的每個分片配置1個Data Guard;使用Golden Gate來備份其他資料中心的每一個分片。
注意:Golden Gate只是近實時
8. 為Oracle或者MySQL新增資料訪問層
假設你有一個可以接受500個連線的Oracle RAC,而你有25個jBoss例項和這個甲骨文RAC對話,每個Jboss例項配置範圍10到50的資料庫連線池。
當jBoss叢集開啟時,連線到Oracle的數目為250(25乘10),一切執行良好。隨著流量快到jBoss叢集的峰值,想象一下將會發生什麼。在某個點後,Oracle將開始拒絕連線。
因此建議通過一個Multiplexer層建立一個Multiplexe應用程式伺服器連線。可以是一個簡單的 netty應用,這個應用執行在一個每個netty節點僅能夠與Oracle建立25個連線的叢集上,但是對入站連線來者不拒。它會將所有的連線迴圈傳遞給Oracle,但是絕對不會超過25個,同時還使用Oracle JDBC驅動與Oracle通訊。
9. 避免跨資料中心事務
當下,這已經是非常簡單的事情,但是在任何地方都非常適用,包括Oracle。在兩個資料不同資料中心,不要適用1個XA介面卡去做跨資料中心事務,這將導致相當長時間的應用執行緒阻塞,直到兩個階段的提交完成,因此將帶來你的應用程式服務、服務和所有同步上傳流崩潰,最終會因為執行緒數量增加而導致整個應用程式崩潰,比如在類似Black Friday流量情況下。
10. 考慮分散式快取框架
Memcached、Counbase是最常用的選擇。但實際上,解除安裝非易失性資料到一箇中心快取叢集上,確實沒必要在每個JVM上做相同的拷貝。但是確實需要設定小數量的JVM堆作為分散式快取的一個MRU快取,這樣的話,快取叢集本身將會受到非常少的網路呼叫。
- 在JVM上大多數分散式快取支援本地快取的概念,它將儲存最常用的物件。
- JVM上,GC的pause time同樣被最小化了,因為物件圖中需要遍歷的物件比以前更少了。
- Warmup過程是必不可少的,這可以幫助將資料匯入分散式快取,這個過程應該在晚上或者是使用者訪問量低的時候。
11. 考慮把web應用程式分解為服務
上帝保佑,如果你負責的web應用程式超過50萬行程式碼,而且仍然只作單一的專案部署,那麼是時候根據服務功能把它分解成專業的服務了,並分配到不同的子組織或團隊去操作。將Web應用程式分解為服務有以下諸多優勢:
- Debug將變得簡單
- 擴充套件及讓子系統執行的更好將變得簡單
- 很容易瞭解執行環境裡發生了什麼
- 更快的新增新功能
12. 不要使用session stickiness
這絕是與魔鬼共舞,session stickiness會讓極值負荷下無法擴充套件。你的客戶端應該能夠呼叫ANY應用程式伺服器,並得到其查詢值。其中一個方法是讓服務無狀態,也稱為RestFUL服務。每個請求,客戶端會收發標識狀態的id,代表客戶session的資料儲存在資料庫或跨多個請求的分散式快取。
如果因為某個原因,取代RestFUL服務,你網站大部分是建立在HttpServlets和HttpSession屬性上,使用以下方法可以實現獨立session stickiness的網站:
一個servlet過濾器面對每項服務,取走每個請求的id,然後呼叫分散式快取來填充會話屬性,這將有助於處理請求。因此資料中心任何伺服器都可以響應來自客戶端的請求,因為session狀態被保持在memcached。
不使用session stickiness還允許使用“rolling restart”方式重啟你的應用程式伺服器叢集,從而實現100%的正常執行時間。
13. 終止反向代理商的SSL
在SSL訊號交換及潛在TCP通訊有效保持上,反向代理非常擅長。在反向代理有上設定一個顯式的TCP維持計時器,nGinx及許多其他http伺服器都允許這麼做,這允許TCP連線多次重複使用。與TCP訊號交換的成本是3個network call,這樣許多請求就可以避免這個開銷。
因此從反向代理到應用程式伺服器,通常是RAW http;因此,同樣也要維持TCP的上行連線。
14. 為GSLB型別的負載平衡器使用粘性負載平衡
跨資料中心的負載平衡,建議使用session stickiness。這是因為在跨資料中心複製上,資料庫Oracle或Cassandra只能依賴最終一致性技術。因此,非粘性跨資料中心負載均衡器將使你的客戶端再也無法訪問網站。因此經常使用GSLB,多數情況下,你的CDN將獲得基於位置的GSLB資料中心解決方案。
15. 減少主頁上的CNAME查詢
儘量減少主頁上的CNAME查詢。單單主頁的CNAME查詢,一些網站就有10個或更多。即使客戶端DNS查詢的答案可能來自他們的ISP遞迴快取,我們仍然可以做的更好。www.amazon.com CNAME查詢為零。
dig www.amazon.com
;; QUESTION SECTION:
;www.amazon.com. IN A
;; ANSWER SECTION:
www.amazon.com.28 IN A 205.251.242.54
16. 擁抱一切“reactor”
在高流量軟體系統中,reactor模式一次又一次的得以證明。一系列框架被建立用以實現reactor模式,reactor大致使用場景如下:
- 作為一個反向代理:nGinx
- 應用程式伺服器: node.js
- 並行處理的: Scala的actor model
除非你的業務邏輯是高度CPU繫結,否則就得考慮使用reactor模式或基於事件迴圈的軟體。如果無法實現,可以考慮像RxJava框架那樣的響應式程式設計模型。
17. 實現呼叫取消
從Siddharth Anand的一個會議上得到靈感,服務呼叫時的呼叫圖。首先,通過數字的遞減實現超時。接下來,服務呼叫圖的每次呼叫,都會建立一個UUID,並在分散式快取中為UUID設定一個標誌:
UUID:true
- 如果服務呼叫圖中的任何服務超時,UUID的標誌設定為false。
- 現在為所有服務實現一個servlet過濾器,一直檢查這個標誌,只在這個標誌是真時才繼續處理。
- 如果標誌是是假,程式返回一個空的response。
- 這在大業務量時,可以禁止不必要的呼叫。
18. 執行GC搜尋協議
再次,靈感來自於同一個人——通過Netty讓所有的服務也顯示一個TCP埠。在呼叫一個服務之前,呼叫TCP埠然後暫停2 - 5 ms等待訪問。如果呼叫超時,這意味著這個Java程式正字做一個“stop the world”的垃圾收集。客戶立即切換到另一個服務例項,然後嘗試同樣的步驟。如果呼叫成功,然後呼叫例項上的實際服務。
注意:實現GC搜尋協議需要的客戶端ip地址配置(即客戶端負載均衡)。
19. 儘可能讓業務邏輯和I / O存取非同步進行
在流量爆炸時,非同步業務邏輯能讓您的應用程式避免建立過多的執行緒。將事件佇列推送給負載均衡叢集,讓它去做程式訂閱的業務邏輯,而不是在http request/response週期執行緒做這些事。
20. 偏愛最終一致性資料庫
尤其是當你在執行跨資料中心的應用程式。除非你的用例是事務處理的(比如訂單)等等,否則偏愛使用最終一致性資料庫比如Cassandra,並儘可能少的使用ACID型別資料庫。
21. 使用CDN服務靜態內容
使用CDN服務靜態內容——javascript、影象、css 等。CDN能有效地將靜態內容複製到近客戶地方,因此許多針對這些靜態內容的http請求最終穿越不會超過幾百英里。
22. 打包壓縮javascript到一個檔案中
減少javascript內聯。
注意:不要在pre-prod環境中這麼做,這裡需要使用除錯程式做javascript的debug。
原文連結: 22 Recommendations For Building Effective High Traffic Web Software
相關文章
- 建立高效能移動 web 站點Web
- 用PHP如何打造一個高可用高效能的網站PHP網站
- 自學 JAVA 的幾點建議Java
- 學java的一點建議Java
- 打造抖音私域流量,站點月賺百萬的祕籍
- 構建高效能 ASP.NET 應用的幾點建議ASP.NET
- 構建高效能 ASP.NET 應用的 12 點建議ASP.NET
- 構建高效能ASP.NET應用的幾點建議ASP.NET
- JAVA程式碼編寫的30條建議 .Java
- JAVA程式碼編寫的30條建議Java
- 8條關於Web前端效能的優化建議Web前端優化
- 用Tomcat構建WEB站點TomcatWeb
- 降低Java垃圾回收開銷的5條建議Java
- JAVA程式碼編寫的30條建議(轉)Java
- 給初學java的一點建議Java
- 利用麥咖啡(McAfee)打造超安全的Web站點目錄Web
- 將 Web 應用效能提高十倍的10條建議Web
- 24條 Docker 建議Docker
- 高流量站點NGINX與PHP-fpm配置最佳化NginxPHP
- JAVA優質程式碼編寫的30條可行建議Java
- 提升網站流量6條法則網站
- 避開NullPointerException的10條建議NullException
- 控制IT預算的5條建議
- 我總結了寫出高質量程式碼的12條建議
- 網站流量異常變動的8種常見原因及解決建議網站
- #給java程式設計師的10條建議,吐血推薦!Java程式設計師
- Google網站管理員:提升移動Web效能的4個建議Go網站Web
- web前端教程分享初學HTML5的幾點建議Web前端HTML
- 國內開源映象站資訊盤點(建議收藏!)
- 程式碼簡潔的十條建議
- 成為最差開發者的10條建議
- Pinterest:九條實用的旅行建議REST
- 融入開源社群的4條建議
- 使用Backbone構建精美應用的7條建議
- 高效設計構建軟體的十三條建議
- java-web-j2ee學習建議路線JavaWeb
- 網站SEO的18個建議網站
- 如何建設一個高效能的網站網站