基於akka的多線程框架在考拉APP後端的應用
本文來自網易雲社區。
問題背景
App品牌頁由於多版本的迭代,頁面承載模塊越來越多,如品牌基本信息、優惠券、熱銷、上新、品牌商品篩選、相關品牌推薦等,如下圖所示,用戶訪問品牌頁有時候會感覺載入較慢,主要原因是App品牌頁所有的數據都是通過一個HTTP請求返回數據,這個請求需要調用三次搜索、一次推薦、若干次緩存查詢和DB查詢,而且是順序同步執行,請求響應時間較長,導致的結果是:
1、用戶體驗較差,當可降級服務(熱銷/上新搜索、品牌推薦)某個環節處理較慢時,整個請求的響應時間會拉的很長,即使dubbo配置了超時,多個降級服務的最大響應時間疊加也是不能忍受的。
2、在用戶使用峰值,如每日秒殺或大促時間,慢請求會導致Dubbo線程阻塞。我們不怕請求多,我們就怕慢請求。
在已發版的客戶端無法修改的情況下,只能通過服務端加快處理邏輯,及時返回數據,解決慢請求的問題。
多線程解決方案
針對以上問題,我們打算採取多線程方案解決,JDK 7提供了兩種線程池方案,ThreadPoolExecutor和ForkJoinPool,對兩者原理研究和源碼閱讀後,我們進行了一個比較:
l 適用場景:Fork/Join比ThreadPoolExecutor更適合任務層層分解、處理、結果合併的場景。
l 性能:Fork/Join的工作流竊取演算法,能提供最大化的並行程度。
我們選定ForkJoinPool來解決問題,但是多線程編程有一定的難度,主要原因有:
l 鎖
l 線程間通信
l 異常處理
l 代碼可讀性
l 無ForkJoinPool線上時間經驗
我們需要一個簡單、易用、抽象層次更高的並發框架,我們又查閱了Actor模型的Java實現Akka。
Actor模型:Akka
Actor模型,一種用於處理並發計算的數學模型,特點如下:
l 非同步消息方式通信
l 狀態機
l 無共享
l 無鎖的並發處理方式
l 並行性
Akka是Actor模型的Java實現,底層線程池默認為ForkJoinPool,是比較理想的並發框架選擇,它的編程難度相比直接用JDK的線程池更低,簡單、易用、抽象層次更高。
我們進一步做的工作是結合Spring框架抽象封裝Akka,對外隱藏Akka的細節,提供更簡單的服務,進一步簡化多線程編程的難度。
效果
上線後,通過哨兵對比,App品牌頁性能提升約25%左右,如下圖所示:
相同的方案應用在用戶頁,平均響應時間提升約50%左右,如下圖所示:
用戶在訪問App品牌頁和用戶頁響應速度更快,體驗更佳,系統dubbo線程池彪滿的風險進一步降低,效果達到了預期。
原文:基於akka的多線程框架在考拉APP後端的應用
本文來自網易雲社區,經作者黃曉軍授權發布。
了解網易雲 :
網易雲官網:https://www.163yun.com
網易雲社區:https://sq.163yun.com/blog網易雲新用戶大禮包:https://www.163yun.com/gift更多網易研發、產品、運營經驗分享請訪問網易雲社區。
推薦閱讀: