DActor
Introduction
DActoræ¡æ¶åºäºåç¨ææ³è®¾è®¡ï¼å¯åæ¶æ¯æåæ¥åå¼æ¥ä»£ç ï¼ç®åå¨çº¿å¼æ¥ä»£ç çå¼åï¼ç¨åæ¥ä»£ç çæç»´æ¥å¼åå¼æ¥ä»£ç ï¼å ¼é¡¾å¼æ¥ä»£ç çé«å¹¶åãæ é»å¡ååæ¥ä»£ç çæ读æ§ï¼å¯ç»´æ¤æ§ã
æ大ç¨åº¦çéä½é»å¡ï¼æé«å个线ç¨çå¤çè½åï¼å¹¶å¯ææçéä½çº¿ç¨æ°ã
项ç®å°å
ææ¡£
è§å¾é 置说æ:è§å¾é 置说æ
SpringBoot Yml é 置说æ:Ymlé 置说æ
XML é 置说æ:XMLé 置说æ
常ç¨ç±»è¯´æ:常ç¨ç±»è¯´æ
é ç½®åAPI说æ:é ç½®åAPI说æ
æ´å¤æ档详è§ï¼WIKI
QQ交æµç¾¤
783580303
æ¥å ¥ç³»ç»
Dpressï¼åºäºDactoræ建çå¤ååå客系ç»
æç»æ´æ°ä¸ãã欢è¿å¤§å®¶èªè
Overview
ç®åå¼åè¿ç¨ä¸çå 个常è§æ¨¡å
åæ¥ç¼ç¨
æææ¥éª¤é½å¨ä¸ä¸ªä¸»çº¿ç¨ä¸å®æ,è°ç¨ä¸ä¸ªæ¹æ³ï¼çå¾ å ¶ååºè¿åãä¸ä¸ªè¯·æ±å ç¨ä¸ä¸ªçº¿ç¨,å¨ææ°æ®åºæä½ãTCPåHttpé讯æ¶å 为æé»å¡æ åµï¼ä¼å¯¼è´å ç¨çº¿ç¨å ç¨èæ æ³åæ¶éæ¾
ï¼å æ¤å¨åæ¥äº¤æä¸å¼å ¥äºçº¿ç¨æ± æ¦å¿µ,æé«ç³»ç»çååé
å¼æ¥ç¼ç¨
æææ¥éª¤é½å¯å¨ä¸å线ç¨ä¸å®æ,è°ç¨ä¸ä¸ªæ¹æ³ï¼ä¸çå¾ ååºæ¢è¿åï¼å ¸å交æå¦NodeJsã
ç®åå¸é¢ä¸çå¼æ¥æ¡æ¶é½æ¯è¾å¤æï¼å¸é¢çéç¨è§£å³æ¹æ¡æ¯CallBackåPromise/Deferred模å¼æ¨¡å¼ã
设计æè·¯
为äºä¿çå¼æ¥çé«æ§è½,ç®åå¼æ¥çå¼å模å¼ï¼åæ¶ä½¿å¾ç¨åºæ´å®¹æ被ç¨åºåç解ï¼å¨æ§è½å代ç å¯é 读æ§ä¸é´åå¾å¹³è¡¡ï¼è®¾è®¡äºæ¤æ¡æ¶ã
å¤çæ¥éª¤:å°è¯·æ±å°è£ 为æ¶æ¯,ä¸¢å ¥æ¶æ¯éåï¼å¯»æ¾åéæ¥éª¤å¤çæ¶æ¯,ä¸è¿°è¿ç¨ä¸æ循ç¯ï¼ç´å°ææå¯ç¨æ¥éª¤é½æ§è¡å®æ¯ã
å 为æ¯å¯¹æ¶æ¯éåè¿è¡å¤ç,对äºåæ¥äº¤æï¼å¤çå®æ¯å³å¯ä¸¢å ¥æ¶æ¯éåã对äºå¼æ¥äº¤æï¼çå¾ åè°å®æ¯åä¸¢å ¥æ¶æ¯éåã
两ç§æ åµå¯¹äºæ¡æ¶æ¥è¯´æ¯æ å·®å«çãåæ¶å 为éè¿å¼æ¥äº¤æé¿å äºé»å¡æ åµçåç,æ以å¯å¨ä¸å¤§å¹ 度æé«çº¿ç¨æ°çæ åµä¸ï¼æé«ååéï¼
åæ¶ä¹å¯å¨ä¸å®ç¨åº¦é¿å æµéçªå¢çæ åµåçã
æ¶æ¯éåéç¨Disruptorççé«æ§è½éåRingBufferã
以Actoråç¨å¹¶å模å为åºç¡è®¾è®¡æ¡æ¶ã
Features
1ãéæNetty
2ãéæHttpClient
3ãéæHttpServlet
4ãæ¯æå¤å±ç¶åç»æ
5ãæ¯æ责任é¾æ¨¡å¼
6ãJ2EEæ¯æjson,csv,pdf,xml,htmlæ ¼å¼è¾åº
7ãJ2EEæ¯ææ°æ®æµè¾åº,å¨ææ件ä¸è½½ãå¨æå¾çè¾åºã跳转åå¯æ ¹æ®é ç½®å¨æè¾åº
8ãåæ¶æ¯æSpringBootåSpring
ç¯å¢è¦æ±
JDK 1.8
Spring FrameWork 5.2.4.RELEASE + æè Spring Boot 2.2.7.RELEASE +
Servlet 3.0+(å 为éè¦ä½¿ç¨Servletçå¼æ¥åè½)
注æäºé¡¹
请æ±çå®æ´é»è¾æ¯åæ£å¨ä¸åç线ç¨ä¸æ§è¡çï¼æ以尽éé¿å 使ç¨ThreadLocal
Getting Started
exampleæ¯J2EEç¨åº,ä¸è½½åï¼å¯ç´æ¥è¿è¡,å ¶ä¸éæäºè¥å¹²ä¾å
é»è®¤ä½¿ç¨.doæ交ç¸å ³äº¤æï¼ä½å¦ææ¯.jsonå°ä¼è¿åjsonæ°æ®
å¯å¨å,å¨æµè§å¨ä¸è¾å ¥http://localhost:8080/example/randomTxt2.json
è¾åºçæ¯jsonæ ¼å¼çå符串
randomTxt2:åªæä¸çº§ç¶åå ³ç³»
randomTxt1:æäºçº§ç¶åå ³ç³»
chaintest1:åªä½¿ç¨è´£ä»»é¾
chaintest2:åæ¶ä½¿ç¨è´£ä»»é¾åä¸çº§ç¶åå ³ç³»
exceptionTest:å交ææåºé误,æ¡æ¶å¯¹é误çå¤ç
randomTxt3为beginBeanId为Actoræ ç¾çBeanIdä¾å
httptestæ¼ç¤ºçæ¯éè¿httpclientå¼æ¥æ¹å¼è®¿é®ç¾åº¦ç½ç«
访é®URL:http://localhost:8080/example/ httptest.do
http://localhost:8080/example/np.randomTxt2.json为使ç¨å½å空é´çä¾å,ç¸å ³é ç½®å¨conf/namespace.xmlä¸ã
å¯å¨åï¼å¯å¨æ§å¶å°çå°å é¨è°ç¨ç»æ
Maven dependency
cn.ymotel
dactor
1.1.2
Gradle dependency
compile group: 'cn.ymotel', name: 'dactor', version:'1.1.2'
代ç ç®å讲解
æ§è¡è¿ç¨ä¸ºchain->grandfather->parent->Selftã
ä¾æ¬¡è°ç¨æ§è¡è´£ä»»é¾ä¸é»è¾ï¼grandfatherä¸çé»è¾ï¼parentçé»è¾åèªèº«é»è¾ã
chain,grandfather,parenté½å¯ä¸ºç©ºï¼ä¸è®¾ç½®
å¨grandfatheråparentä¸çStepsä¸è³å°æä¸ä¸ªä¸ºplaceholderActor交æï¼ä»¥è°ç¨åé»è¾
æ´ä¸ªè¿ç¨ä¸ï¼éè¦å è®¾ç½®å ¨å±å ä½ç¬¦
交æä¸å¦ææªå¡«åbeginBeanIdæè endBeanIdæ¶ï¼ç³»ç»é»è®¤ä½¿ç¨å ¨å±ä¸é ç½®çbeginBeanIdæè endBeanId
condtionå¯ä¸ºç©ºï¼ç©ºå符串ï¼æè æ¯ognl表达å¼
placeholderActorçä½ç¨æ¯å¨æåå½åç¯å¢ï¼å¹¶è°ç¨å交æï¼å¾ å交ææ§è¡å®æ¯åï¼åæ¢å¤å½åç¯å¢ç»§ç»æ§è¡
å¦æå¨Stepä¸æªæ¾å°toBeanIdActorï¼ä¼ç´æ¥è°ç¨endBeanIdæ¹æ³ï¼è®¤ä¸ºèªèº«äº¤æå·²æ§è¡ç»æã
交æç请æ±åæµè½¬ä¿¡æ¯é½ä¿åå¨Messageä¸
å¦ææå®handleException=falseæè 使ç¨é»è®¤è®¾ç½®ï¼ç´æ¥è¿åç¶ä¸æ§è¡ï¼å¦æç¶ä¸ä¹æªæè·ï¼å继ç»è¿åä¸ä¸çº§æ§è¡ï¼
ä¸è¬æ¥è¯´è³å°æè¦æä¸ä¸ªactorä¸æå®handleException=true
å¯å¨æ¡æ¶æ¥æ¶åæ§è¡è¯·æ±
åæ¥å¼æ¥åæ³
åæ¥åæ³
public class BeginActor implements Actor {
@Override
public Object HandleMessage(Message message) throws Exception {
return message;
}
}
继æ¿Actoræ¥å£ï¼å¨HandlerMessageè¿åmessageæ¹æ³ï¼æ¡æ¶å¤æè¿åä¸ä¸ºç©ºçæ åµä¸ï¼ç´æ¥å°ç»æ丢ç»æ¡æ¶è¿è¡ä¸ä¸æ¥åºæ¥
å¼æ¥åæ³
以HttpClientActor为ä¾,å¨HandlerMessageä¸æåè¿ånullï¼æ¡æ¶æ¶å°è¯·æ±åçå¾ ä¸ä¸æ¥å¤çï¼éæ¾çº¿ç¨ï¼å¨HttpClientä¸çCallBackä¸è°ç¨
message.getControlMessage().getMessageDispatcher().sendMessage(message);æ¡æ¶æ¶å°åè¿è¡ä¸ä¸æ¥å¤çã
public Object HandleMessage(final Message message) throws Exception {
Map context = message.getContext();
//
HttpUriRequest request = getHttpBuild(message.getContext()).build();
if (referer != null) {
request.addHeader("Referer", referer);
}
HttpClientContext tmplocalContext = null;
if (context.containsKey(HTTPCLIENT_CONTEXT)) {
tmplocalContext = (HttpClientContext) context.get(HTTPCLIENT_CONTEXT);
} else {
tmplocalContext = HttpClientContext.create();
CookieStore cookieStore = new BasicCookieStore();
tmplocalContext.setCookieStore(cookieStore);
context.put(HTTPCLIENT_CONTEXT, tmplocalContext);
}
final HttpClientContext localContext = tmplocalContext;
// CookieStore cookieStore = new BasicCookieStore();
// localContext.setCookieStore(cookieStore);
if (logger.isInfoEnabled()) {
logger.info("HandleMessage(Message) - httpclient----" + request); //$NON-NLS-1$
}
// final HttpGet httpget = new HttpGet(uri);
final String tmpcontent = content;
final String tmpcharset = charset != null ? charset : (String) context.get(CHARSET);
httpClientHelper.getHttpclient().execute(request, localContext, new FutureCallback() {
public void completed(final HttpResponse response) {
try {
message.getContext().remove(tmpcontent);
actorHttpClientResponse.handleResponse(response, localContext, tmpcharset, message);
//String responseString=HandleResponse((String)message.getContext().get(CHARSET),response);
//message.getContext().put(RESPONSE, responseString);
} catch (Exception e) {
// TODO Auto-generated catch block
if (logger.isErrorEnabled()) {
logger.error("$FutureCallback.completed(HttpResponse)", e); //$NON-NLS-1$
}
message.setException(e);
message.getControlMessage().getMessageDispatcher().sendMessage(message);
}
// System.out.println(httpget.getRequestLine() + "->" + response.getStatusLine());
}
public void failed(final Exception ex) {
if (logger.isErrorEnabled()) {
logger.error("$FutureCallback.failed(Exception)", ex); //$NON-NLS-1$
}
message.setException(ex);
message.getControlMessage().getMessageDispatcher().sendMessage(message);
// System.out.println(httpget.getRequestLine() + "->" + ex);
}
public void cancelled() {
Exception exception = new Exception("å·²åæ¶");
message.setException(exception);
message.getControlMessage().getMessageDispatcher().sendMessage(message);
// System.out.println(httpget.getRequestLine() + " cancelled");
}
});
return null;
}
é ç½®åAPI说æ
é 置说æ
éè¿å¨xmlä¸çStepå®ç°å é¨Actorä¹é´çæµç¨è·³è½¬
å¨é ç½®æ件ä¸å å«
Actorãchainãåglobalé ç½® ã
ç¨åºæ´ä¸ªæ§è¡é¡ºåºä¸ºæ ¹æ®äº¤æç æ¾å°å¯¹åºçActor,ç¶åæ§è¡æç §chain->parent->selftç顺åºè¿è¡æ§è¡ã
chainæ§è¡å°placeholderå¤,è°ç¨parent交æ继ç»æ§è¡,å¨parent交æä¸æ§è¡å°placeholder交æåï¼è°ç¨selftèªèº«äº¤æ继ç»æ§è¡ã
èªèº«äº¤ææ§è¡å®æ¯ï¼å¼¹åºparentçplaceholderå¤äº¤æ继ç»æ§è¡.parentæ§è¡å®æ¯,å¼¹åºchainä¸ä»£ç 继ç»æ§è¡ã
globalé ç½®å¦ä¸
beginBeanId为é»è®¤çå¼å§Actor,valueä¸çå¼æ¯å¨Springä¸å¯¹åºçbeanNameï¼ç¨åºåå§åæ¶å°ä¼åå¾æ¤å¼ï¼å¯¹æªæå®beginBeanIdæè endBeanIdçActoråå§åå ¨å±é ç½®ã
beginActoråendActoré½éè¦ç»§æ¿Actoræ¥å£ã
actoré ç½®å¦ä¸
htmlstream:
å±æ§handleExceptionå¦æä¸è®¾ç½®çè¯,éå°å¼å¸¸,ç¨åºå°ä¼è®¤ä¸ºåç±»ä¸å·²ç»æ§è¡å®æ¯,è·³å°parentä¸PlaceHolderå¤æ§è¡ã设置为trueï¼å°ä¸ä¼ç´æ¥è·³è½¬å°parentä¸ï¼ç±åç±»è¿è¡èªæå¤çã
parentåchain为è°ç¨å ·ä½äº¤æåéè¦è°ç¨çå ¬å ±äº¤æï¼ç±äºå¤§é¨å交æé½æéç¨çå置交æåç»ä¸çå置交æãéè¿è®¾ç½®parentæè chainï¼å¯æé«ä»£ç å¤ç¨åº¦ã
fromBeanIdåtoBeanIdé ç½®çæ¯Actoræè å®ç°Actoræ¥å£çbeanIdã
parentåchainä¸çrefé½éè¦æ¯Actor.
resultsä¸å¯å®ä¹è¿åçstateåéè¦å¤ççviewActor
asyncæ è®°æ¯å¦æ¯æ路交æï¼é»è®¤å¼ä¸ºfalseï¼ä¸ºtrueå¼æ¶,ä¼å°ä¸ä¸æå 容设置å¤å¶ä¸ä»½ï¼éæ°çæä¸ä»½Message,è¿è¡æ§è¡ï¼ä¸å½±å主æµç¨ã
chainé ç½®
chainå¯ç´è§å±ç°Actorè°ç¨é¡ºåº.
å¨chainä¸å¯é¡ºåºå¹¶åå¤ä¸ªparentç±»ãæ¯ä¸ªparentä¸çStepé½éè¦æplaceHolderActorï¼ä»¥è°ç¨åç±»ã
ä¾æ¬¡æ§è¡listä¸ç交æï¼åæ§è¡èªèº«äº¤æãèªèº«äº¤ææ§è¡å®æ¯ï¼åä¾æ¬¡å溯责任é¾ä¸çæ¯ä¸ªäº¤æï¼ç´å°æ å¯ç¨äº¤æã
å½å空é´
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:actor="http://www.ymotel.cn/schema/dactor"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.ymotel.cn/schema/dactor http://www.ymotel.cn/schema/dactor.xsd" namespace="np">
éè¦ç±»æ¹æ³è¯´æ
cn.ymotel.dactor.core.MessageDispatcheræ¯äº¤ææµè½¬çæ ¸å¿æ¥å£ç±»
public void startMessage(Message message, ActorTransactionCfg actorcfg, boolean blocked) throws Exception
æ¹æ³,ç¨äºå¼å§æ´ä¸ªæµç¨ï¼å ¶ä¸messageéè¦å¨æ§è¡åè¿è¡æé ï¼actorcfgå¯éè¿springçgetBeanæ¹æ³å¾å°ä¸ºActor对象ï¼å¦ä¸
éè¿getBean('randomTxt1')å³å¯å¾å°ActorTransactionCfg对象ã
blocked为æ¯å¦é»å¡ï¼ä¸è¬å¨äº¤æå次æ¾å ¥éåæ¯ä¸ºfalse,表示å¦æéå满ï¼åç´æ¥æç»å®¢æ·ç«¯è¿è¡å¤çã为trueåä¸è¬ä¸ºå é¨äº¤æ,å¿ é¡»æ交ç»éåè¿è¡å¤çã
sendMessageæ¹æ³å é¨è°ç¨ï¼ç¨äºå°å¤çå®æ¯çMessageéæ°æ¾å ¥éåï¼ç»§ç»ä¸ä¸æ¥æµç¨ã
cn.ymotel.dactor.core.disruptor.MessageRingBufferDispatcheræ¯MessageDispatcherçæ¥å£å®ç°ç±»ã,å¨å¯å¨Springæ¯éè¦å¨é ç½®ä¸å ä¸
MessageRingBufferDispatcherçstrategyãbufferSizeãthreadNumber为ä¸ä¸ªå¯è®¾ç½®å±æ§.æ£å¸¸æ åµä¸ä½¿ç¨é»è®¤è®¾ç½®å³å¯ã
strategyé»è®¤ä½¿ç¨ringBufferçBlockingWaitStrategyçç¥è¿è¡è°åº¦ï¼å¦æ交æéæ¯è¾å¤§ï¼å¯è°æ´æ¤çç¥ã
bufferSizeé»è®¤ä½¿ç¨1024ã
threadNumberé»è®¤ä½¿ç¨CPU个æ°ç线ç¨æ°ã
å ¶ä»é»è®¤Actor说æ
cn.ymotel.dactor.message.Message.Actor,ææéè¦å¨æ§è¡ç交æé½å¿ 须继æ¿æ¤æ¥å£ã
public Object HandleMessage(Message message) throws Exception;ç¨åºéè¿è°ç¨HandleMessage对象,å¦æè¿åçä¸æ¯message对象æè 为NULL,å认为æ¤äº¤ææ¯å¼æ¥æ§è¡,ä¸åèªè¡è°åº¦ãç±å¼æ¥äº¤æå¨æ¶å°è¯·æ±åï¼èªå·±è°ç¨å°Messageåæ¤æ¾å ¥éåä¸ã
cn.ymotel.dactor.action.PlaceholderActor 交æ为ç¹æ®äº¤æï¼ç¨æ¥å°å½åéåæåï¼å¹¶è°ç¨å交æã
cn.ymotel.dactor.action.BeginActor 为Actorä¸stepçé»è®¤å¼å§äº¤æã
cn.ymotel.dactor.action.EndActor 为Actorä¸stepçé»è®¤ç»æ交æã
cn.ymotel.dactor.action.JsonViewResolverActor为éè¦è¿åJsonçJ2EE view
cn.ymotel.dactor.action.ViewResolveActor为éè¦è¿åJ2EE viewçç»ä¸å¤çActor
cn.ymotel.dactor.action.httpclient.HttpClientActor æä¾çå¼æ¥è°ç¨httpClientçActor
cn.ymotel.dactor.action.netty.aysnsocket.TcpClientActor æä¾çå¼æ¥è°ç¨nettyçActor
交ææµç¨ä¸¾ä¾è¯´æ
以ä¸äº¤æç交ææµç¨å¾å¦ä¸
以ä¸çå®æ´ä¾åé½å¯å¨exampleä¸å¾å°