OpenResty學習——第六章 Web開發實戰1——HTTP服務

原文鏈接:https://blog.csdn.net/jinnianshilongnian/article/details/84704000

本文轉自https://blog.csdn.net/jinnianshilongnian/article/details/84704000,好文要頂,感謝博主分享!

 

此處我說的HTTP服務主要指如訪問京東網站時我們看到的熱門搜索、用戶登錄、實時價格、實時庫存、服務支持、廣告語等這種非Web頁面,而是在Web頁面中異步加載的相關數據。這些服務有個特點即訪問量巨大、邏輯比較單一;但是如實時庫存邏輯其實是非常複雜的。在京東這些服務每天有幾億十幾億的訪問量,比如實時庫存服務曾經在沒有任何IP限流、DDos防禦的情況被刷到600多萬/分鐘的訪問量,而且能輕鬆應對。支撐如此大的訪問量就需要考慮設計良好的架構,並很容易實現水平擴展

 

架構

此處介紹下我曾使用過Nginx+JavaEE的架構。

 

1、單DB架構

早期架構可能就是Nginx直接upstream請求到後端Tomcat,擴容時基本是增加新的Tomcat實例,然後通過Nginx負載均衡upstream過去。此時數據庫還不是瓶頸。當訪問量到一定級別,數據庫的壓力就上來了,此處單純的靠單個數據庫可能扛不住了,此時可以通過數據庫的讀寫分離或加緩存來實現。

 

2、DB+Cache/數據庫讀寫分離架構

此時就通過使用如數據庫讀寫分離或者Redis這種緩存來支撐更大的訪問量。使用緩存這種架構會遇到的問題諸如緩存與數據庫數據不同步造成數據不一致(一般設置過期時間),或者如Redis掛了,此時會直接命中數據庫導致數據庫壓力過大;可以考慮Redis的主從或者一致性Hash 算法做分片的Redis集羣;使用緩存這種架­構要求應用對數據的一致性要求不是很高;比如像下訂單這種要落地的數據不適合用Redis存儲,但是訂單的讀取可以使用緩存。

 

3、Nginx+Lua+Local Redis+Mysql集羣架構

首先Nginx通過Lua讀取本機Redis緩存,如果不命中才回源到後端Tomcat集羣;後端Tomcat集羣再讀取Mysql數據庫。Redis都是安裝到和Nginx同一臺服務器,Nginx直接讀本機可以減少網絡延時。Redis通過主從方式同步數據,Redis主從一般採用樹的方式實現:

在葉子節點可以做AOF持久化,保證在主Redis掛時能進行恢復;此處假設對Redis很依賴的話,可以考慮多主Redis架構,而不是單主,來防止單主掛了時數據的不一致和擊穿到後端Tomcat集羣。這種架構的缺點就是要求Redis實例數據量較小,如果單機內存不足以存儲這麼多數據,當然也可以通過如尾號爲1的在A服務器,尾號爲2的在B服務器這種方式實現;缺點也很明顯,運維複雜、擴展性差。

 

4、Nginx+Lua+ Redis集羣+Mysql集羣架構 

和之前架構不同的點是此時我們使用一致性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負載均衡軟件的優缺點詳解 

 

實現

接下來我們來搭建一下第四種架構。

以獲取如京東商品頁廣告詞爲例,如下圖

假設京東有10億商品,那麼廣告詞極限情況是10億;所以在設計時就要考慮:

1、數據量,數據更新是否頻繁且更新量是否很大;

2、是K-V還是關係,是否需要批量獲取,是否需要按照規則查詢。

 

而對於本例,廣告詞更新量不會很大,每分鐘可能在幾萬左右;而且是K-V的,其實適合使用關係存儲;因爲廣告詞是商家維護,因此後臺查詢需要知道這些商品是哪個商家的;而對於前臺是不關心商家的,是KV存儲,所以前臺顯示的可以放進如Redis中。 即存在兩種設計:

1、所有數據存儲到Mysql,然後熱點數據加載到Redis;

2、關係存儲到Mysql,而數據存儲到如SSDB這種持久化KV存儲中。

基本數據結構:商品ID、廣告詞、所屬商家、開始時間、結束時間、是否有效。

 

後臺邏輯

1、商家登錄後臺;

2、按照商家分頁查詢商家數據,此處要按照商品關鍵詞或商品類目查詢的話,需要走商品系統的搜索子系統,如通過Solr或elasticsearch實現搜索子系統;

3、進行廣告詞的增刪改查;

4、增刪改時可以直接更新Redis緩存或者只刪除Redis緩存(第一次前臺查詢時寫入緩存);

 

前臺邏輯

1、首先Nginx通過Lua查詢Redis緩存;

2、查詢不到的話回源到Tomcat,Tomcat讀取數據庫查詢到數據,然後把最新的數據異步寫入Redis(一般設置過期時間,如5分鐘);此處設計時要考慮假設Tomcat讀取Mysql的極限值是多少,然後設計降級開關,如假設每秒回源達到100,則直接不查詢Mysql而返回空的廣告詞來防止Tomcat應用雪崩。

 

爲了簡單,我們不進行後臺的設計實現,只做前端的設計實現,此時數據結構我們簡化爲[商品ID、廣告詞]。另外有朋友可能看到了,可以直接把Tomcat部分幹掉,通過Lua直接讀取Mysql進行回源實現。爲了完整性此處我們還是做回源到Tomcat的設計,因爲如果邏輯比較複雜的話或一些限制(比如使用Java特有協議的RPC)還是通過Java去實現更方便一些。

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