1. 程式人生 > >如何設計高效能的介面

如何設計高效能的介面

引言

高併發經常會發生在有大活躍使用者量,使用者高聚集的業務場景中,如:秒殺活動,定時領取紅包等。

為了讓業務可以流暢的執行並且給使用者一個好的互動體驗,我們需要根據業務場景預估達到的併發量等因素,來設計適合自己業務場景的高併發處理方案。

在工作這些年裡,我有幸遇到了高併發各種坑,對如何設計高效能介面有一些經驗,其實無外乎滿足以下幾個特點:

靈敏性

伸縮性

容錯性

事件驅動/訊息驅動

高效能介面設計準則

在引言裡我也說了高效能設計的四個準則,現在具體對這四個準則做一些描述;

1. 靈敏性

應用程式應該儘可能快的對請求做出響應。

如果可以在順序獲取資料和並行獲取資料之間進行選擇的話,為了儘快向用戶返回響應,始終應該優先選擇並行獲取資料,可以同時請求互相沒有關聯的資料。當我們需要請求多個互相無關,沒有依賴的資料的時候,應該考慮是否能夠同時請求這些資料。

如果可能出現錯誤,應該立即返回,將問題通知使用者,不要讓使用者等待直到超時。

1.1 如何設計靈敏性

快取前置

對於一些改變不頻繁的資料,應該放在分散式快取中,例如redis,如果是一些元資料(例如,一些計數器的配置資訊,變數的配置資訊等)則應該啟用本地快取,簡單流程如下:

如果一些熱點資料不大的話,建議服務啟動的時候就應該提前載入到快取中,這樣可以提高服務的效能。

讀寫拆分部署

如果你的服務既涉及到讀操作,也涉及到寫操作, 應該將讀寫隔離部署,這樣讀服務的壓力不會影響到寫服務,寫服務的壓力不會影響到讀服務。流程如下:

當然除了按照讀寫進行拆分部署外,還可以按照業務進行隔離部署。

對等設計、無狀態

所謂無狀態是指應用伺服器不儲存業務的上下文資訊,而僅根據每次請求提交的資料進行相應的業務邏輯處理,多個服務例項(伺服器)之間完全對等,請求提交到任意伺服器,處理結果是完全一樣的。

不儲存狀態的應用給高可用的架構設計帶來了巨大便利,既然伺服器不儲存請求的狀態,那麼所有的伺服器完全對等,當任意一臺或多臺伺服器宕機,請求提交給叢集中的其他任意一臺可用機器處理,這樣對終端使用者而言,請求總是能夠成功的,整個系統依然可用。對於應用伺服器叢集,實現這種伺服器可用狀態實時檢測、自動轉移失敗任務的機制就是負載均衡。

DB分庫分表,讀寫分離

對於資料層來說,如果資料量不大,db可以採用讀寫分離部署,對於讀多寫少的場景可以解決一部分壓力,從而提高我們介面的響應速度,如果寫的資料量和讀的資料量都很大,那麼就必須要對db進行分庫分表外加讀寫分離了。

2. 伸縮性

應用程式應該能夠根據不同的工作負載進行伸縮擴充套件(尤其是通過增加計算資源來進行擴充套件)。為了提供伸縮性,系統應該努力消除瓶頸。

如果在虛擬機器上執行記憶體資料庫,那麼新增另一個虛擬幾點就可以將所有的查詢請求分佈到兩臺虛擬伺服器上,將可能的吞吐量增加至原來的兩倍。新增額外的節點應該能夠幾乎線性的提高系統的效能。

增加一個記憶體資料庫的節點後,還可以將資料分為兩半,並將其中的一半移至新的節點,這樣就能夠將記憶體容量提高至原來的兩倍。新增節點應該能夠幾乎線性的提高記憶體容量。

所以一般好的介面設計是可以通過水平擴充套件機器來達到提升效能的,這就要求我們設計介面的時候提現無狀態性。

3. 容錯性

應用程式應該考慮到錯誤發生的情況,並且從容的對錯誤情況做出響應。如果系統的某個元件發生錯誤,對與該元件無關的請求不應該產生任務影響。錯誤是難以避免的,因此應該將錯誤造成的影響限制在發生錯誤的元件之內。如果可能的話,通過對重要元件及資料的備份和冗餘,這些元件發生錯誤時不應該對其外部行為有任何影響。

假設你的系統既使用了redis,也使用了mysql對資料進行處理,當redis或著mysql掛了的時候,程式應該可以繼續提供服務,而不是一味的報錯。流程如下:

當一個元件不可用的時候,可以使用開關對某一個元件進行降級,常見的降級方式分為手動降級和自動降級,手動降級可以藉助zookeeper進行,自動降級可以使用Hystrix。

4. 事件驅動/訊息驅動

使用訊息而不直接進行方法呼叫提供了一種幫助我們滿足另外3個高效能設計準則的方法。訊息驅動的系統著重於控制何時、何地以及如何對請求做出響應,允許做出響應的元件進行路由以及負載均衡。

由於非同步的訊息驅動系統只在真正需要時才會消耗資源(比如執行緒),因此它對系統資源的利用更為高效。訊息也可以被髮送到遠端機器(位置透明)。

通常不是萬不得已,否則我們認為丟失一部分資料換取服務的高效能,這是值得的。如果能容忍資料的部分丟失(在可接受範圍內),比如儲存資料到db,非同步計算耗時的任務,通過訊息佇列將是提升我們系統性能的比較好的方式。

總結

4個設計準則之間並不是完全獨立的。為了滿足某個準則而採取的方法通常也對滿足其他準備有所幫助。例如,如果發現某個服務響應速度較慢,我們可能會在短時間內停止再向該服務傳送請求,等待其恢復正常,並立即向用戶返回錯誤資訊。這樣做降低了響應慢的服務不堪重負直接崩潰的風險,因此也提高了系統的容錯性。除此之外,我們立即告知了使用者系統發生的問題,也就改善了系統的響應速度,如圖所示:

如果你想學好JAVA這門技術,也想在IT行業拿高薪,可以參加我們的訓練營課程,選擇最適合自己的課程學習,技術大牛親授,8個月後,進入名企拿高薪。我們的課程內容有:Java工程化、高效能及分散式、高效能、深入淺出。高架構。效能調優、Spring,MyBatis,Netty原始碼分析和大資料等多個知識點。如果你想拿高薪的,想學習的,想就業前景好的,想跟別人競爭能取得優勢的,想進阿里面試但擔心面試不過的,你都可以來,q群號為:180705916 進群免費領取學習資料。