溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

基于Java的同步異步統(tǒng)一處理框架

發(fā)布時間:2020-08-09 05:47:28 來源:ITPUB博客 閱讀:234 作者:allon2 欄目:編程語言
DActor框架可同時支持同步和異步代碼,簡化在線異步代碼的開發(fā),用同步代碼的思維來開發(fā)異步代碼,兼顧異步代碼的高并發(fā)、無阻塞和同步代碼的易讀性,可維護性。
基于協(xié)程思想設(shè)計
最大程度的降低阻塞,提高單個線程的處理能力,并可有效的降低線程數(shù)。
GitHub:https://github.com/allon2/dactor  
 GitEE:https://gitee.com/handyun/dactor  
目前開發(fā)過程中的幾個常見模型
同步編程
    所有步驟都在一個主線程中完成,調(diào)用一個方法,等待其響應(yīng)返回。一個請求占用一個線程,在有數(shù)據(jù)庫操作、TCP和Http通訊時因為有阻塞情況,會導(dǎo)致占用線程占用而無法及時釋放  
    ,因此在同步交易中引入了線程池概念,提高系統(tǒng)的吞吐量
異步編程
    所有步驟都可在不同線程中完成,調(diào)用一個方法,不等待響應(yīng)既返回,典型交易如NodeJs。
    目前市面上的異步框架都比較復(fù)雜,市面的通用解決方案是CallBack和Promise/Deferred模式模式。  
為了保留異步的高性能,簡化異步的開發(fā)模式,同時使得程序更容易被程序員理解,在性能和代碼可閱讀性中間取得平衡,設(shè)計了此框架。    
處理步驟:將請求封裝為消息,丟入消息隊列,尋找合適步驟處理消息,上述過程不斷循環(huán),直到所有可用步驟都執(zhí)行完畢。  
  因為是對消息隊列進行處理,對于同步交易,處理完畢即可丟入消息隊列。對于異步交易,等待回調(diào)完畢再丟入消息隊列。  
  兩種情況對于框架來說是無差別的。同時因為通過異步交易避免了阻塞情況的發(fā)生,所以可在不大幅度提高線程數(shù)的情況下,提高吞吐量,  
  同時也可在一定程度避免流量突增的情況發(fā)生。  
消息隊列采用Disruptor的的高性能隊列RingBuffer。
以Actor協(xié)程并發(fā)模型為基礎(chǔ)設(shè)計框架。 
1、集成Netty
2、集成HttpClient
3、集成HttpServlet
4、支持多層父子結(jié)構(gòu)
5、支持責(zé)任鏈模式  
6、J2EE支持json,csv,pdf,xml,html格式輸出
7、J2EE支持數(shù)據(jù)流輸出,動態(tài)文件下載、動態(tài)圖片輸出、跳轉(zhuǎn)和可根據(jù)配置動態(tài)輸出
 環(huán)境要求  
  JDK 1.8  
  Spring FrameWork 4.3.22.RELEASE +  
  Servlet 3.0+(因為需要使用Servlet的異步功能)  
 注意事項  
  請求的完整邏輯是分散在不同的線程中執(zhí)行的,所以盡量避免使用ThreadLocal
1.0.7版本  
     修正Step中所有條件不為真時,報錯問題  
1.0.6版本  
     通過設(shè)置async=true的方式,便捷的增加旁路交易  
     移除對javax.mail-api的依賴  
1.0.5版本  
     ServletMessage的用戶對象直接從會話中取得  
 1.0.4版本  
     優(yōu)化程序邏輯  
 1.0.3版本  
    Message增加setUser和getUser對象  
 1.0.2版本
初始化版本
example是J2EE程序,下載后,可直接運行,其中集成了若干例子  
    默認使用.do提交相關(guān)交易,但如果是.json將會返回json數(shù)據(jù)
   啟動后,在瀏覽器中輸入http://localhost:8080/example/randomTxt2.json  
   輸出的是json格式的字符串  
   randomTxt2:只有一級父子關(guān)系  
   randomTxt1:有二級父子關(guān)系 
   chaintest1:只使用責(zé)任鏈  
   chaintest2:同時使用責(zé)任鏈和一級父子關(guān)系  
   exceptionTest:子交易拋出錯誤,框架對錯誤的處理  
   httptest演示的是通過httpclient異步方式訪問百度網(wǎng)站   
        訪問URL:http://localhost:8080/example/ httptest.do    
   http://localhost:8080/example/np.randomTxt2.json為使用命名空間的例子,相關(guān)配置在conf/namespace.xml中。  
   啟動后,可在控制臺看到內(nèi)部調(diào)用結(jié)果  
   
   
執(zhí)行過程為chain->grandfather->parent->Selft。
依次調(diào)用執(zhí)行責(zé)任鏈中邏輯,grandfather中的邏輯,parent的邏輯和自身邏輯。
chain,grandfather,parent都可為空,不設(shè)置
在grandfather和parent中的Steps中至少有一個為placeholderActor交易,以調(diào)用子邏輯
整個過程中,需要先設(shè)置全局占位符  
    <actor:global id="actorglobal">  
           <actor:param name="beginBeanId" value="beginActor"/>  
           <actor:param name="endBeanId" value="endActor"/>  
       </actor:global>  
交易中如果未填寫beginBeanId或者endBeanId時,系統(tǒng)默認使用全局中配置的beginBeanId或者endBeanId  
condtion可為空,空字符串,或者是ognl表達式  
placeholderActor的作用是在暫存當前環(huán)境,并調(diào)用子交易,待子交易執(zhí)行完畢后,再恢復(fù)當前環(huán)境繼續(xù)執(zhí)行  
如果在Step中未找到toBeanIdActor,會直接調(diào)用endBeanId方法,認為自身交易已執(zhí)行結(jié)束。  
交易的請求和流轉(zhuǎn)信息都保存在Message中  
如果指定handleException=false或者使用默認設(shè)置,直接返回父中執(zhí)行,如果父中也未捕獲,則繼續(xù)返回上一級執(zhí)行,    
一般來說至少有要有一個actor中指定handleException=true
<bean id="MessageRingBufferDispatcher" class="cn.ymotel.dactor.core.disruptor.MessageRingBufferDispatcher">
</bean>
啟動框架接收和執(zhí)行請求
通過在xml中的Step實現(xiàn)內(nèi)部Actor之間的流程跳轉(zhuǎn)
 在配置文件中包含
 Actor、chain、和global配置 。
 程序整個執(zhí)行順序為根據(jù)交易碼找到對應(yīng)的Actor,然后執(zhí)行按照chain->parent->selft的順序進行執(zhí)行。  
 chain執(zhí)行到placeholder處,調(diào)用parent交易繼續(xù)執(zhí)行,在parent交易中執(zhí)行到placeholder交易后,調(diào)用selft自身交易繼續(xù)執(zhí)行。
 自身交易執(zhí)行完畢,彈出parent的placeholder處交易繼續(xù)執(zhí)行.parent執(zhí)行完畢,彈出chain中代碼繼續(xù)執(zhí)行。
 global配置如下
beginBeanId為默認的開始Actor,value中的值是在Spring中對應(yīng)的beanName,程序初始化時將會取得此值,對未指定beginBeanId或者endBeanId的Actor初始化全局配置。  
beginActor和endActor都需要繼承Actor接口。
actor配置如下
屬性handleException如果不設(shè)置的話,遇到異常,程序?qū)J為子類中已經(jīng)執(zhí)行完畢,跳到parent中PlaceHolder處執(zhí)行。設(shè)置為true,將不會直接跳轉(zhuǎn)到parent中,由子類進行自我處理。  
 parent和chain為調(diào)用具體交易前需要調(diào)用的公共交易,由于大部分交易都有通用的前置交易和統(tǒng)一的后置交易。通過設(shè)置parent或者chain,可提高代碼復(fù)用度。  
 fromBeanId和toBeanId配置的是Actor或者實現(xiàn)Actor接口的beanId。
 parent和chain中的ref都需要是Actor.  
 results中可定義返回的state和需要處理的viewActor  
 async標記是否是旁路交易,默認值為false,為true值時,會將上下文內(nèi)容設(shè)置復(fù)制一份,重新生成一份Message,進行執(zhí)行,不影響主流程。
chain配置
chain可直觀展現(xiàn)Actor調(diào)用順序.    
在chain中可順序并列多個parent類。每個parent中的Step都需要有placeHolderActor,以調(diào)用子類。      
依次執(zhí)行l(wèi)ist中的交易,再執(zhí)行自身交易。自身交易執(zhí)行完畢,再依次回溯責(zé)任鏈中的每個交易,直到無可用交易。 
命名空間
在actor中可增加命名空間,簡化代碼開發(fā)。在actor中配置namespace=np,則實例中的actor的id會自動拼裝為np.randomTxt2  
     http://localhost:8080/example/np.randomTxt2.json為使用命名空間的例子,相關(guān)配置在conf/namespace.xml中。  
cn.ymotel.dactor.core.MessageDispatcher是交易流轉(zhuǎn)的核心接口類   
    public void startMessage(Message message, ActorTransactionCfg actorcfg, boolean blocked) throws Exception  
方法,用于開始整個流程,其中message需要在執(zhí)行前進行構(gòu)造,actorcfg可通過spring的getBean方法得到為Actor對象,如下  
sendMessage方法內(nèi)部調(diào)用,用于將處理完畢的Message重新放入隊列,繼續(xù)下一步流程。
 cn.ymotel.dactor.core.disruptor.MessageRingBufferDispatcher是MessageDispatcher的接口實現(xiàn)類。,在啟動Spring是需要在配置中加上
MessageRingBufferDispatcher的strategy、bufferSize、threadNumber為三個可設(shè)置屬性.正常情況下使用默認設(shè)置即可。  
 strategy默認使用ringBuffer的BlockingWaitStrategy策略進行調(diào)度,如果交易量比較大,可調(diào)整此策略。  
 bufferSize默認使用1024。   
 threadNumber默認使用CPU個數(shù)的線程數(shù)。   
 cn.ymotel.dactor.message.Message.Actor,所有需要在執(zhí)行的交易都必須繼承此接口。   
 public Object HandleMessage(Message message) throws Exception;程序通過調(diào)用HandleMessage對象,如果返回的不是message對象或者為NULL,則認為此交易是異步執(zhí)行,不再自行調(diào)度。由異步交易在收到請求后,自己調(diào)用將Message再此放入隊列中。  
 cn.ymotel.dactor.action.PlaceholderActor 交易為特殊交易,用來將當前隊列暫存,并調(diào)用子交易。  
 cn.ymotel.dactor.action.BeginActor 為Actor中step的默認開始交易。  
 cn.ymotel.dactor.action.EndActor 為Actor中step的默認結(jié)束交易。
 cn.ymotel.dactor.action.JsonViewResolverActor為需要返回Json的J2EE view
  cn.ymotel.dactor.action.ViewResolveActor為需要返回J2EE view的統(tǒng)一處理Actor  
  cn.ymotel.dactor.action.httpclient.HttpClientActor 提供的異步調(diào)用httpClient的Actor  
cn.ymotel.dactor.action.netty.aysnsocket.TcpClientActor 提供的異步調(diào)用netty的Actor  
以上交易的交易流程圖如下以上的完整例子都可在example中得到


向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI