日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

一个可供参考的Java高并发异步应用案例--转

發布時間:2025/4/5 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个可供参考的Java高并发异步应用案例--转 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文地址:http://chuansong.me/n/355827651252

泰康在線微信公眾號系泰康在線財產保險股份有限公司旗下平臺,希望可以通過持續不斷的創新,提升客戶對于保險的認知及體驗,通過對大數據技術的應用,精準的為客戶設計產品以及提供服務。泰康在線微信公眾號,現有1000多萬粉絲。在日常的運營中,借助于紅包獎勵、卡券分享、消息通知、微信分享等手段,通過好的內容,好的活動、好的產品以及相應的精準營銷來增強用戶的粘性和活躍度。

在日常運營中,公眾號會通過給用戶下發營銷或者科普類的消息來通知客戶。 根據經驗,微信消息下發后10分鐘后流量會逐步上升,30分鐘左右到達峰值,1個小時后會顯著下降。在這個時間段內,系統的壓力會很大。

在系統設計和改進中,系統的很多場景使用異步進行實現,一方面能縮短主流程的時間處理,另一方面能夠通過異步隊列進行一定程度的削峰。今天重點介紹單個JVM內的異步優化實踐,不涉及分布式時的異步優化實踐。在異步執行時,可以調用遠程的服務集群來實現一定的任務分解。

部署示意圖

?

整個系統都部署在公有云上,虛擬機上有部署1個Nginx,4個Tomcat,Nginx使用隨機的方式負載均衡到Tomcat上面。虛機之間通過LB將客戶請求轉發到Nginx上面負載均衡,Nginx再將請求分配到tomcat應用服務器上。

由多臺應用服務器,對外服務提供Rest服務,在每個Tomcat內部使用異步隊列。同時由一臺控制服務器,進行異步任務的補償任務和管理功能。Tomcat和Redis使用多級緩存來降低對Redis的壓力,并減少依賴。

為什么要在虛機上部署Nginx將請求轉發到Tomcat,而不是由LB直接轉發到Tomcat。這是因為LB能夠支持的IP個數是有限的。

典型的用戶場景

在公眾號的運營過程中,典型的事件包括:

  • 發送短信驗證碼

  • 購買成功或者抽獎成功短信通知

  • 卡券或優惠券發放

  • 發放微信紅包

  • 微信消息通知

  • 訂單流程處理

  • 定時批處理(比如數據同步)

  • 工作流性質的異步任務(未完成異步任務補償)

面詳細說明不同場景能夠異步的原因:

  • 不同場景(用戶注冊,用戶購買產品等)下的短信驗證碼發送,可以使用異步方式發送: 一方面是因為客戶這個時效性要求沒有那樣高,另一方面在特定時間范圍內用戶沒有收到驗證碼,用戶可以點擊再次發送驗證碼。

  • 購買成功或者抽獎成功后短信或者郵件通知,可以通過異步的方式進行。 因為涉及用戶的利益,要謹慎對待。一方面一定要把數據先存到數據庫或者日志里面(注意信息安全^-^,別存敏感明文信息或者加密存儲),然后再放入到異步隊列中執行。

    另一個方面,要考慮到應用服務意外停止時,沒有發送成功數據的補償機制。 這種情況不常見,并且為了減少耦合和當前異步程序的復雜度。我們使用單獨的服務上部署異步任務補償程序,來掃描未完成的任務,并且進行重放(一定要注意嚴謹性)。

  • 優惠券和卡券的發放,跟購買成功或抽獎成功的方式類似。\u000b可以在當前活動高峰后延時發放,并且使用異步的方式進行。

  • 微信紅包,因為需要跟微信進行交互,并且微信會通知客戶紅包的情況,可以使用異步的方式進行。 當涉及資金或者禮品時,一定要謹慎對待設計,并且需要有方便進行異步任務停止和啟動的功能。

  • 微信消息通知,因為跟微信進行交互,成功后微信進行通知,可以使用異步。 這個跟短信驗證碼類似。

  • 訂單流程處理,可以使用異步,因為涉及到后續步驟可以使用簡單工作流來完成。有幾個開源的框架可以參考。

  • 數據同步或者異步任務補償,因為是延時處理,可以使用異步進行處理。在使用時,可以配合定時任務,比如cron4j來周期性的進行補償。適合后面總-分-總的任務處理模式。

  • 針對這些“無處不在的異步”,后面詳細分析其內在模型。

    無處不在的異步

    下圖包含了4種典型的異步隊列模型(圖片來源于網絡):

    ?

    一個生產者生產數據,一個消費者消費數據,一般用在后臺處理的業務邏輯中。

    • 一個生產者生產數據,多個消費者消費數據(這里面有兩種情況:同一個消息,可以被多個消費者分別消費。或者多個消費者組成一個組,一個消費者消費一個數據)。

    • 多個生產者生產數據,單個消費者消費數據,可以用在限流或者排隊等候單一資源處理的場景中。

    • 多個生產者分別生產數據,多個消費者消費數據(這里面有兩種情況:同一個消息,可以被多個消費者分別消費。或者多個消費者組成一個組,一個消費者消費一個數據)。

    ?


    總分總任務模型:特別適第一個線程取出一批數據放到隊列中(比如select);由多個線程分別執行業務邏輯;執行后的結果由一個線程來執行(比如update操作,這樣能夠防止數據庫鎖)

    這是從技術上分析的幾種常見模型,在實踐中涉及怎樣選擇框架。

  • 使用堵塞隊列的線程池

  • 使用固定步長或固定時間的隊列

  • 使用Disruptor

  • 使用MQ或Kafka

  • 使用線程池實現異步 (支持多生產者,多消費者)

    ?

    特點:可以使用JDK自帶的線程池實現異步,編程簡單,資料多。建議在并發量小的場景下優先選擇。

    使用Guava Queues (支持多生產者單消費者)

    ?

    特點:異步批量隊列,在隊列到達指定長度,或者到達指定時間后,批量進行數據處理。適合于對響應時間要求低,能夠容忍一定的數據丟失的場景。比如短小文本數據的批量保存。

    在經過一段時間調研后,我們發現Disruptor更能滿足我們需要。

    首先介紹一下Disruptor的強悍的性能。

    ?

    ?

    ?

    ?

    ?

    這張圖包含我列舉的上述的異步隊列模型景,因此很有代表意義。Disruptor因為使用無鎖的隊列方式,具有很高的性能。具體的原理不詳述,大家可以搜索看到。Disruptor支持上面典型場景,并且靈活使用Disruptor的工作流機制,能簡化編程。

    • 英文文章入門:https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started

    • 中文的demo鏈接:http://my.oschina.net/u/2273085/blog/507735?p=1

    • 并發框架Disruptor相關譯文:http://ifeve.com/disruptor/

    再貼一下官方的測試結果。

    ?

    下面從代碼層面說明disruptor的幾種用法。

    使用Disruptor(單生產者多消費者)

    ?

    Disruptor 提供了多個 WaitStrategy的實現,每種策略都具有不同性能和優缺點,根據實際運行環境的 CPU 的硬件特點選擇恰當的策略,并配合特定的 JVM的配置參數,能夠實現不同的性能提升。 例如,BlockingWaitStrategy、SleepingWaitStrategy、YieldingWaitStrategy 等,其中:

    • BlockingWaitStrategy 是最低效的策略,但其對CPU的消耗最小并且在各種不同部署環境中能提供更加一致的性能表現;

    • SleepingWaitStrategy 的性能表現跟 BlockingWaitStrategy 差不多,對 CPU的消耗也類似,但其對生產者線程的影響最小,適合用于異步日志類似的場景;

    • YieldingWaitStrategy的性能是最好的,適合用于低延遲的系統。在要求極高性能且事件處理線數小于 CPU邏輯核心數的場景中,推薦使用此策略;例如,CPU開啟超線程的特性。

    我們現在使用BlockingWaitStrategy這種模式。

    使用Disruptor(多生產者多消費者)

    ?

    ?

    使用Disruptor(多生產者多消費者)

    ?

    這個例子中,使用類似線程池的消費組處理數據。

    多步模式工作流:Disruptor

    ?

    使用異步后的煩惱

    煩惱一: 數據丟失的風險

    解決方式:先寫日志或數據庫,后放入異步隊列.

    煩惱二:對其他系統的壓力變大

    解決方式:使用一定的限流和熔斷,對其他系統進行保護。

    煩惱三:數據保存后異步任務未執行

    解決方式:使用異步任務補償的方式,定期從數據庫中獲取數據,放到隊列中進行執行,執行后更新數據狀態位。

    煩惱四:怎樣隊列長設置和消費者數量

    解決方式:使用實際的壓力測試來獲得隊列長度。或者使用排隊論的數學公式得到初步的值,然后進行實際壓測。

    最后介紹一下項目中的經驗:

      • 量力而行:根據業務特點進行技術選型,業務量小盡量避免使用異步。有所為,有所不為

      • 數據說話:異步時一定要進行必要的壓力測試

      • 先找出系統的關鍵點:優化單體系統內的性能,再通過整體系統分解來全局優化

      • 根據團隊和項目的特點選擇框架。

    ?

    轉載于:https://www.cnblogs.com/davidwang456/articles/6548394.html

    總結

    以上是生活随笔為你收集整理的一个可供参考的Java高并发异步应用案例--转的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。