此處我說的HTTP服務主要指如訪問京東網站時咱們看到的熱門搜索、用戶登陸、實時價格、實時庫存、服務支持、廣告語等這種非Web頁面,而是在Web頁面中異步加載的相關數據。這些服務有個特色即訪問量巨大、邏輯比較單一;可是如實時庫存邏輯實際上是很是複雜的。在京東這些服務天天有幾億十幾億的訪問量,好比實時庫存服務曾經在沒有任何IP限流、DDos防護的狀況被刷到600多萬/分鐘的訪問量,並且能輕鬆應對。支撐如此大的訪問量就須要考慮設計良好的架構,並很容易實現水平擴展。html
此處介紹下Nginx+JavaEE的架構。web
早期架構可能就是Nginx直接upstream請求到後端Tomcat,擴容時基本是增長新的Tomcat實例,而後經過Nginx負載均衡upstream過去。此時數據庫還不是瓶頸。當訪問量到必定級別,數據庫的壓力就上來了,此處單純的靠單個數據庫可能扛不住了,此時能夠經過數據庫的讀寫分離或加緩存來實現。算法
此時就經過使用如數據庫讀寫分離或者Redis這種緩存來支撐更大的訪問量。使用緩存這種架構會遇到的問題諸如緩存與數據庫數據不一樣步形成數據不一致(通常設置過時時間),或者如Redis掛了,此時會直接命中數據庫致使數據庫壓力過大;能夠考慮Redis的主從或者一致性Hash 算法作分片的Redis集羣;使用緩存這種架構要求應用對數據的一致性要求不是很高;好比像下訂單這種要落地的數據不適合用Redis存儲,可是訂單的讀取可使用緩存。sql
首先Nginx經過Lua讀取本機Redis緩存,若是不命中才回源到後端Tomcat集羣;後端Tomcat集羣再讀取Mysql數據庫。Redis都是安裝到和Nginx同一臺服務器,Nginx直接讀本機能夠減小網絡延時。Redis經過主從方式同步數據,Redis主從通常採用樹的方式實現:
在葉子節點能夠作AOF持久化,保證在主Redis掛時能進行恢復;此處假設對Redis很依賴的話,能夠考慮多主Redis架構,而不是單主,來防止單主掛了時數據的不一致和擊穿到後端Tomcat集羣。這種架構的缺點就是要求Redis實例數據量較小,若是單機內存不足以存儲這麼多數據,固然也能夠經過如尾號爲1的在A服務器,尾號爲2的在B服務器這種方式實現;缺點也很明顯,運維複雜、擴展性差。數據庫
和以前架構不一樣的點是此時咱們使用一致性Hash算法實現Redis集羣而不是讀本機Redis,保證其中一臺掛了,只有不多的數據會丟失,防止擊穿到數據庫。Redis集羣分片可使用Twemproxy;若是 Tomcat實例不少的話,此時就要考慮Redis和Mysql連接數問題,由於大部分Redis/Mysql客戶端都是經過鏈接池實現,此時的連接數會成爲瓶頸。通常方法是經過中間件來減小連接數。
Twemproxy與Redis之間經過單連接交互,並Twemproxy實現分片邏輯;這樣咱們能夠水平擴展更多的Twemproxy來增長連接數。
此時的問題就是Twemproxy實例衆多,應用維護配置困難;此時就須要在之上作負載均衡,好比經過LVS/HAProxy實現VIP(虛擬IP),能夠作到切換對應用透明、故障自動轉移;還能夠經過實現內網DNS來作其負載均衡。
本文沒有涉及Nginx之上是如何架構的,對於Nginx、Redis、Mysql等的負載均衡、資源的CDN化不是本文關注的點,有興趣能夠參考
很早的Taobao CDN架構
Nginx/LVS/HAProxy負載均衡軟件的優缺點詳解後端