├── .gitignore ├── spi.jar ├── assets ├── treetask_thread.png └── treetask_console.png ├── src ├── main │ └── java │ │ ├── fun │ │ └── lib │ │ │ └── actor │ │ │ ├── api │ │ │ ├── cb │ │ │ │ ├── CbTimeout.java │ │ │ │ ├── CbActorRsp.java │ │ │ │ ├── CbHttpServer.java │ │ │ │ ├── CbCallHere.java │ │ │ │ ├── CbCallHereBlock.java │ │ │ │ ├── CbActorReq.java │ │ │ │ ├── CbActorRspAsync.java │ │ │ │ ├── CbHttpClient.java │ │ │ │ ├── CbNode.java │ │ │ │ ├── RpcFuture.java │ │ │ │ ├── Cb.java │ │ │ │ ├── RpcContext.java │ │ │ │ └── CallHereContext.java │ │ │ ├── http │ │ │ │ ├── DFHttpMethod.java │ │ │ │ ├── DFHttpSvrRsp.java │ │ │ │ ├── DFHttpDispatcher.java │ │ │ │ ├── DFHttpCliReq.java │ │ │ │ ├── DFHttpHeader.java │ │ │ │ ├── DFHttpCliRsp.java │ │ │ │ ├── DFHttpContentType.java │ │ │ │ └── DFHttpSvrReq.java │ │ │ ├── DFTcpEncoder.java │ │ │ ├── DFTcpDecoder.java │ │ │ ├── DFUdpDecoder.java │ │ │ ├── DFActorUdpDispatcher.java │ │ │ ├── DFUdpChannel.java │ │ │ ├── DFActorLog.java │ │ │ ├── DFSerializable.java │ │ │ ├── DFActorMongo.java │ │ │ ├── DFActorTimer.java │ │ │ ├── DFActorDb.java │ │ │ ├── DFActorRedis.java │ │ │ ├── DFTcpChannel.java │ │ │ ├── DFActorTcpDispatcher.java │ │ │ └── DFActorNet.java │ │ │ ├── core │ │ │ ├── DFActorSchedule.java │ │ │ ├── DFHttpReqBuilder.java │ │ │ ├── IScriptHttpSvrRsp.java │ │ │ ├── DFJsEvent.java │ │ │ ├── DFNodeInfo.java │ │ │ ├── RegNodeReq.java │ │ │ ├── IScriptHttpSvrReq.java │ │ │ ├── IScriptBuffer.java │ │ │ ├── DFHttpData.java │ │ │ ├── DFActorMongoWrap.java │ │ │ ├── IVirtualHost.java │ │ │ ├── RpcFutureWrap.java │ │ │ ├── DFUdpChannelWrap.java │ │ │ ├── DFActorTimerWrap.java │ │ │ ├── DFActorRedisWrap.java │ │ │ ├── DFJsLaunchActor.java │ │ │ ├── DFActorDbWrap.java │ │ │ ├── DFActorLogWrap.java │ │ │ ├── DFActorMessage.java │ │ │ ├── DFHttpMultiData.java │ │ │ ├── DFVirtualHostManager.java │ │ │ ├── DFDbManager.java │ │ │ ├── DFActorDefine.java │ │ │ ├── DFJsHttpSvrReq.java │ │ │ ├── DFHttpCliRspWrap.java │ │ │ ├── DFJsBuffer.java │ │ │ ├── IScriptAPI.java │ │ │ ├── DFMongoManager.java │ │ │ ├── DFWSRequestHandler.java │ │ │ ├── DFHttpSyncHandler.java │ │ │ ├── DFRedisManager.java │ │ │ ├── DFMysqlManager.java │ │ │ ├── DFHttpSvrRspWrap.java │ │ │ └── DFActorNetWrap.java │ │ │ ├── msg │ │ │ ├── proto │ │ │ │ ├── gen.bat │ │ │ │ └── DMCluster.proto │ │ │ └── DMCmd.java │ │ │ ├── kcp │ │ │ ├── KcpChannel.java │ │ │ ├── KcpListener.java │ │ │ ├── KcpConfigInner.java │ │ │ ├── KcpConfig.java │ │ │ ├── KcpServer.java │ │ │ └── KcpLoop.java │ │ │ ├── define │ │ │ ├── DFActorErrorCode.java │ │ │ ├── RpcError.java │ │ │ └── RpcParamType.java │ │ │ ├── po │ │ │ ├── IPRange.java │ │ │ ├── DFPageInfo.java │ │ │ ├── DFWebResInfo.java │ │ │ ├── DFNode.java │ │ │ ├── DFActorResult.java │ │ │ ├── DFSSLConfig.java │ │ │ ├── DFUdpServerCfg.java │ │ │ ├── DFMongoCfg.java │ │ │ ├── ActorProp.java │ │ │ ├── DFActorEvent.java │ │ │ ├── DFRedisCfg.java │ │ │ ├── DFDbCfg.java │ │ │ ├── DFActorClusterConfig.java │ │ │ ├── DFDbResultSet.java │ │ │ ├── DFTcpClientCfg.java │ │ │ ├── DFActorManagerConfig.java │ │ │ └── DFTcpServerCfg.java │ │ │ └── helper │ │ │ ├── DFSysBlockActor.java │ │ │ ├── ActorLogData.java │ │ │ ├── DFActorLogLevel.java │ │ │ └── ActorLog.java │ │ ├── com │ │ └── funtag │ │ │ └── util │ │ │ ├── timer │ │ │ ├── DFTimeout.java │ │ │ └── DFScheduleTick.java │ │ │ ├── script │ │ │ ├── IScriptAnalyzer.java │ │ │ ├── DFWebResModel.java │ │ │ └── DFJsUtil.java │ │ │ ├── fs │ │ │ └── IFSMonitor.java │ │ │ ├── log │ │ │ ├── DFLogger.java │ │ │ └── DFLogFactory.java │ │ │ ├── db │ │ │ ├── DFDbConfig.java │ │ │ ├── DFDbSrc.java │ │ │ ├── DFDbMSConfig.java │ │ │ ├── DFDbMSSrc.java │ │ │ └── DFDbUtil.java │ │ │ ├── cache │ │ │ ├── DFRedisConfig.java │ │ │ └── DFRedisUtil.java │ │ │ ├── proto │ │ │ └── DFProtoUtil.java │ │ │ ├── cipher │ │ │ └── DFCipherUtil.java │ │ │ ├── concurrent │ │ │ └── DFSpinLock.java │ │ │ ├── net │ │ │ └── DFIpUtil.java │ │ │ └── system │ │ │ └── DFSysUtil.java │ │ └── log4j.properties └── test │ └── java │ └── fun │ └── lib │ └── actor │ ├── example │ ├── StartAsDaemon.java │ ├── Startup.java │ ├── Shutdown.java │ ├── ExitActor.java │ ├── Schedule.java │ ├── SimpleHttpServer.java │ ├── Timeout.java │ ├── HttpClient.java │ ├── CallHere.java │ ├── Sendback.java │ ├── po │ │ └── ClusterCustomMsg.java │ ├── ActorConn.java │ ├── CallHereBlock.java │ ├── HttpsServer.java │ ├── RpcLocal.java │ ├── WebsocketServer.java │ ├── BlockActor.java │ ├── MongodbTest.java │ ├── HttpServerBenchmark.java │ ├── RedisTest.java │ ├── ClusterBroadcast.java │ ├── ClusterNodeEvent.java │ ├── RpcCluster.java │ ├── ClusterSimple.java │ ├── MysqlTest.java │ └── HttpServerDispatcher.java │ └── deprecated │ └── ActorUdpTest.java ├── LICENSE ├── cert.crt └── key.pem /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | .classpath 4 | .project 5 | .settings/ 6 | -------------------------------------------------------------------------------- /spi.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostsky3000/dfactor/HEAD/spi.jar -------------------------------------------------------------------------------- /assets/treetask_thread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostsky3000/dfactor/HEAD/assets/treetask_thread.png -------------------------------------------------------------------------------- /assets/treetask_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostsky3000/dfactor/HEAD/assets/treetask_console.png -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbTimeout.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface CbTimeout { 4 | 5 | public void onTimeout(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/timer/DFTimeout.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.timer; 2 | 3 | public interface DFTimeout { 4 | 5 | public void onTimeout(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorSchedule.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | public interface DFActorSchedule { 4 | 5 | void onScheduleTick(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/msg/proto/gen.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set binPath=F:\dev\protobuf\protoc.exe 4 | 5 | 6 | %binPath% -I=.\ --java_out=..\..\..\..\..\ DMCluster.proto 7 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbActorRsp.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface CbActorRsp { 4 | 5 | public int onCallback(int cmd, Object payload); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/timer/DFScheduleTick.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.timer; 2 | 3 | public interface DFScheduleTick { 4 | 5 | public int onScheduleTick(long dlt); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/http/DFHttpMethod.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.http; 2 | 3 | 4 | public final class DFHttpMethod { 5 | 6 | public static final String GET = "get"; 7 | public static final String POST = "post"; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbHttpServer.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface CbHttpServer { 4 | 5 | public void onListenResult(boolean isSucc, String errMsg); 6 | 7 | public int onHttpRequest(Object msg); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/script/IScriptAnalyzer.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.script; 2 | 3 | public interface IScriptAnalyzer { 4 | 5 | public void _scriptCall(Object content); 6 | 7 | public void _textCall(Integer txtId); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbCallHere.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface CbCallHere { 4 | 5 | public void inOtherActor(int cmd, Object payload, CallHereContext ctx); 6 | 7 | public void onCallback(int cmd, Object payload); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/kcp/KcpChannel.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.kcp; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | 5 | public interface KcpChannel { 6 | 7 | public int write(ByteBuf bufSend); 8 | public int getConnId(); 9 | public void close(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFTcpEncoder.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | public interface DFTcpEncoder { 4 | 5 | /** 6 | * 消息编码 7 | * @param msgRaw 应用层消息对象 8 | * @return 编码后消息对象,由通信层发送出去 9 | */ 10 | public Object onEncode(Object msgRaw); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbCallHereBlock.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface CbCallHereBlock { 4 | 5 | public void inBlockActor(int cmd, Object payload, CallHereContext ctx); 6 | 7 | public void onCallback(int cmd, Object payload); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFTcpDecoder.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | public interface DFTcpDecoder { 4 | 5 | /** 6 | * 消息解码 7 | * @param msgRaw 原始消息对象(解码后,将由系统自动释放) 8 | * @return 解码后的消息对象 9 | */ 10 | public Object onDecode(Object msgRaw); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFUdpDecoder.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | public interface DFUdpDecoder { 4 | 5 | /** 6 | * 消息解码 7 | * @param msgRaw 原始消息对象(解码后,将由系统自动释放) 8 | * @return 解码后的消息对象 9 | */ 10 | public Object onDecode(Object msgRaw); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/log4j.properties: -------------------------------------------------------------------------------- 1 | #表示INFO级别 输出到控制台 2 | log4j.rootLogger=DEBUG, Console 3 | #Console 4 | log4j.appender.Console=org.apache.log4j.ConsoleAppender 5 | log4j.appender.Console.layout=org.apache.log4j.PatternLayout 6 | log4j.appender.Console.layout.ConversionPattern=%-5p - %m%n -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFHttpReqBuilder.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import fun.lib.actor.api.http.DFHttpCliReq; 4 | 5 | public final class DFHttpReqBuilder { 6 | 7 | public static DFHttpCliReq build(){ 8 | return new DFHttpCliReqWrap(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/IScriptHttpSvrRsp.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | public interface IScriptHttpSvrRsp { 4 | 5 | public IScriptHttpSvrRsp headers(Object headers); 6 | public IScriptHttpSvrRsp status(int statusCode); 7 | public int send(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/define/DFActorErrorCode.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.define; 2 | 3 | public final class DFActorErrorCode { 4 | 5 | public static final int FAILURE = -1; 6 | public static final int SUCC = 0; 7 | 8 | public static final int ERR_ID_DUPLICATE = 1; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/define/RpcError.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.define; 2 | 3 | public final class RpcError { 4 | /** 5 | * rpc回调超时 6 | */ 7 | public static final int TIMEOUT = 0; 8 | /** 9 | * 远程结点处理调用时失败 10 | */ 11 | public static final int REMOTE_FAILED = 1; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFActorUdpDispatcher.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | public interface DFActorUdpDispatcher { 4 | 5 | /** 6 | * 获取要转发到的actorId(io线程中回调) 7 | * @param msg udp包 8 | * @return 目标actorId 9 | */ 10 | public int onQueryMsgActorId(Object msg); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFUdpChannel.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | public interface DFUdpChannel { 4 | 5 | public int write(Object msg); 6 | 7 | // public void registerActor(InetSocketAddress addr, int actorId); 8 | // public void registerActor(String addr, int actorId); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbActorReq.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface CbActorReq { 4 | 5 | /** 6 | * 向消息来源actor发送回复 7 | * @param cmd 消息码 8 | * @param payload 消息体 9 | * @return 0成功,非0失败 10 | */ 11 | public int callback(int cmd, Object payload); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/fs/IFSMonitor.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.fs; 2 | 3 | import java.io.File; 4 | 5 | public interface IFSMonitor { 6 | 7 | public void onCreate(File f); 8 | 9 | public void onModify(File f); 10 | 11 | public void onDelete(File f); 12 | 13 | public void onClose(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbActorRspAsync.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface CbActorRspAsync { 4 | 5 | /** 6 | * 向消息来源actor发送回复 7 | * @param cmd 消息码 8 | * @param payload 消息体 9 | * @return 0成功,非0失败 10 | */ 11 | public int callback(int cmd, Object payload); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/log/DFLogger.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.log; 2 | 3 | public interface DFLogger { 4 | 5 | public void V(String msg); 6 | public void D(String msg); 7 | public void I(String msg); 8 | public void W(String msg); 9 | public void E(String msg); 10 | public void F(String msg); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/IPRange.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class IPRange { 4 | 5 | public final String ipBegin; 6 | public final String ipEnd; 7 | 8 | 9 | public IPRange(String ipBegin, String ipEnd) { 10 | this.ipBegin = ipBegin; 11 | this.ipEnd = ipEnd; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/define/RpcParamType.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.define; 2 | 3 | public final class RpcParamType { 4 | 5 | public static final int BYTE_ARR = 1; 6 | public static final int BYTE_BUF = 2; 7 | public static final int STRING = 3; 8 | public static final int JSON = 4; 9 | public static final int CUSTOM = 5; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFActorLog.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | public interface DFActorLog { 4 | 5 | public void verb(Object msg); 6 | public void debug(Object msg); 7 | public void info(Object msg); 8 | public void warn(Object msg); 9 | public void error(Object msg); 10 | public void fatal(Object msg); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/http/DFHttpSvrRsp.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.http; 2 | 3 | 4 | public interface DFHttpSvrRsp { 5 | 6 | // 7 | public DFHttpSvrRsp header(String key, String val); 8 | public DFHttpSvrRsp contentType(String contentType); 9 | public DFHttpSvrRsp userAgent(String userAgent); 10 | public void send(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFJsEvent.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | public final class DFJsEvent { 4 | 5 | public String type; 6 | public boolean succ; 7 | public String err; 8 | 9 | public DFJsEvent(String type, boolean succ, String err) { 10 | this.type = type; 11 | this.succ = succ; 12 | this.err = err; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbHttpClient.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface CbHttpClient { 4 | 5 | /** 6 | * http请求响应回调 7 | * @param rsp 响应内容 8 | * @param isSucc 请求是否成功 9 | * @param errMsg 请求失败时的错误信息 10 | * @return 响应消息是否由框架自动释放 11 | */ 12 | public int onHttpResponse(Object rsp, boolean isSucc, String errMsg); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/db/DFDbConfig.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.db; 2 | 3 | public final class DFDbConfig { 4 | 5 | public final String url; 6 | public final String user; 7 | public final String pwd; 8 | 9 | public DFDbConfig(String url, String user, String pwd) { 10 | this.url = url; 11 | this.user = user; 12 | this.pwd = pwd; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CbNode.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | import fun.lib.actor.po.DFNode; 4 | 5 | public interface CbNode { 6 | /** 7 | * 结点上线回调 8 | * @param node 结点对象 9 | */ 10 | public void onNodeAdd(DFNode node); 11 | 12 | /** 13 | * 结点下线回调 14 | * @param node 结点对象 15 | */ 16 | public void onNodeRemove(DFNode node); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/helper/DFSysBlockActor.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.helper; 2 | 3 | import fun.lib.actor.core.DFActor; 4 | 5 | public final class DFSysBlockActor extends DFActor{ 6 | 7 | public DFSysBlockActor(Integer id, String name, Boolean isBlockActor) { 8 | super(id, name, isBlockActor); 9 | // TODO Auto-generated constructor stub 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/cache/DFRedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.cache; 2 | 3 | public final class DFRedisConfig { 4 | 5 | public final String host; 6 | public final int port; 7 | public final String auth; 8 | 9 | public DFRedisConfig(String host, int port, String auth) { 10 | this.host = host; 11 | this.port = port; 12 | this.auth = auth; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFNodeInfo.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | public final class DFNodeInfo { 4 | 5 | protected final String host; 6 | protected final int port; 7 | protected final String idAddr; 8 | 9 | protected DFNodeInfo(String host, int port) { 10 | this.host = host; 11 | this.port = port; 12 | this.idAddr = host+":"+port; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/RpcFuture.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface RpcFuture { 4 | 5 | /** 6 | * 添加结果回调监听 7 | * @param cb 回调对象 8 | * @param timeoutMilli 回调超时(毫秒) 9 | * @return 是否成功 10 | */ 11 | public boolean addListener(Cb cb, int timeoutMilli); 12 | 13 | /** 14 | * 是否发送成功 15 | * @return 是/否 16 | */ 17 | public boolean isSendSucc(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/helper/ActorLogData.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.helper; 2 | 3 | 4 | public final class ActorLogData{ 5 | 6 | public final int level; 7 | public final Object msg; 8 | public final String actorName; 9 | 10 | public ActorLogData(int level, Object msg, final String actorName) { 11 | this.level = level; 12 | this.msg = msg; 13 | this.actorName = actorName; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFPageInfo.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class DFPageInfo { 4 | 5 | private volatile int version = 0; 6 | public final String path; 7 | 8 | public DFPageInfo(String path) { 9 | this.path = path; 10 | } 11 | 12 | public int increaseVersion(){ 13 | return ++version; 14 | } 15 | public int getVersion(){ 16 | return this.version; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/Cb.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface Cb { 4 | 5 | /** 6 | * rpc回调方法 7 | * @param cmd 消息码 8 | * @param payload 消息体 9 | * @return 0 10 | */ 11 | public int onCallback(int cmd, Object payload); 12 | 13 | /** 14 | * rpc调用失败的通知 15 | * @param code 错误码,见RpcError.java 16 | * @return 0 17 | */ 18 | public int onFailed(int code); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFWebResInfo.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class DFWebResInfo { 4 | 5 | private volatile int version = 0; 6 | public final String path; 7 | 8 | public DFWebResInfo(String path) { 9 | this.path = path; 10 | } 11 | 12 | public int increaseVersion(){ 13 | return ++version; 14 | } 15 | public int getVersion(){ 16 | return this.version; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/http/DFHttpDispatcher.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.http; 2 | 3 | import java.net.InetSocketAddress; 4 | 5 | public interface DFHttpDispatcher { 6 | 7 | /** 8 | * 获取要转发到的actorId(io线程中回调) 9 | * @param port 监听的端口号 10 | * @param addrRemote 远程连接地址 11 | * @param msg 消息 12 | * @return 接收消息的actorId, 0则不分发 13 | */ 14 | public int onQueryMsgActorId(int port, InetSocketAddress addrRemote, Object msg); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/kcp/KcpListener.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.kcp; 2 | 3 | import io.netty.channel.socket.DatagramPacket; 4 | 5 | public interface KcpListener { 6 | 7 | public void onOutput(DatagramPacket pack); 8 | 9 | public void onInput(DatagramPacket pack, KcpChannel kcpChannel); 10 | 11 | public void onChannelActive(KcpChannel kcpChannel, int connId); 12 | public void onChannelInactive(KcpChannel kcpChannel, int code); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/msg/DMCmd.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.msg; 2 | 3 | public final class DMCmd { 4 | 5 | public static final int NewNodeAsk = 1000; 6 | public static final int NewNodeRsp = 1001; 7 | public static final int NewNodeSucc = 1002; 8 | public static final int AskOtherConn = 1003; 9 | public static final int NewNodeLogin = 1004; 10 | 11 | public static final int UserMsg = 1005; 12 | public static final int RpcFail = 1006; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/proto/DFProtoUtil.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.proto; 2 | 3 | public final class DFProtoUtil { 4 | 5 | public static int execProtoc(String binPath, String srcDir, String outDir, String srcPath){ 6 | int ret = -1; 7 | try{ 8 | String cmd = binPath+" -I="+srcDir+" --java_out="+outDir+" "+srcPath; 9 | Process p = Runtime.getRuntime().exec(cmd); 10 | ret = p.waitFor(); 11 | }catch(Throwable e){ 12 | e.printStackTrace(); 13 | return -2; 14 | } 15 | return ret; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/cipher/DFCipherUtil.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.cipher; 2 | 3 | import java.util.UUID; 4 | 5 | import org.apache.commons.codec.digest.DigestUtils; 6 | 7 | public final class DFCipherUtil { 8 | 9 | public static String getUUID(){ 10 | return UUID.randomUUID().toString(); 11 | } 12 | public static String getUUIDDigest(){ 13 | String uuid = getUUID(); 14 | return getMD5(uuid); 15 | } 16 | 17 | public static String getMD5(String src){ 18 | return DigestUtils.md5Hex(src); 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/helper/DFActorLogLevel.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.helper; 2 | 3 | import com.funtag.util.log.DFLogFactory; 4 | 5 | public final class DFActorLogLevel { 6 | 7 | public static final int VERB = DFLogFactory.LEVEL_VERB; 8 | public static final int DEBUG = DFLogFactory.LEVEL_DEBUG; 9 | public static final int INFO = DFLogFactory.LEVEL_INFO; 10 | public static final int WARN = DFLogFactory.LEVEL_WARN; 11 | public static final int ERROR = DFLogFactory.LEVEL_ERROR; 12 | public static final int FATAL = DFLogFactory.LEVEL_FATAL; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFSerializable.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | 5 | public interface DFSerializable { 6 | 7 | /** 8 | * 获取序列化后的大小,以分配序列化所需内存 9 | * @return 大小 10 | */ 11 | public int getSerializedSize(); 12 | 13 | /** 14 | * 序列化时调用,buf尺寸为getSerializedSize()返回的大小 15 | * @param buf 写入缓存 16 | * @return 0 17 | */ 18 | public int onSerialize(ByteBuf buf); 19 | 20 | /** 21 | * 反序列化 22 | * @param buf 读取缓存 23 | * @return 0 24 | */ 25 | public int onDeserialize(ByteBuf buf); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/RpcContext.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | public interface RpcContext { 4 | 5 | /** 6 | * 向调用方返回结果 7 | * @param cmd 消息码 8 | * @param payload 消息体 9 | */ 10 | public void response(int cmd, Object payload); 11 | 12 | /** 13 | * 是否来自集群内其它结点调用 14 | * @return 是/否 15 | */ 16 | public boolean isRemote(); 17 | 18 | /** 19 | * 获取调用方结点名字(集群内远程调用时有值) 20 | * @return 名字 21 | */ 22 | public String getSrcNode(); 23 | 24 | /** 25 | * 调用方actor名字 26 | * @return 名字 27 | */ 28 | public String getSrcActor(); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/http/DFHttpCliReq.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.http; 2 | 3 | 4 | public interface DFHttpCliReq { 5 | 6 | public DFHttpCliReq end(); 7 | 8 | public DFHttpCliReq uri(String uri); 9 | 10 | public DFHttpCliReq method(String method); 11 | 12 | public DFHttpCliReq header(String name, String val); 13 | 14 | public DFHttpCliReq content(Object data); 15 | 16 | public DFHttpCliReq contentType(String contentType); 17 | 18 | public DFHttpCliReq form(Boolean isForm); 19 | 20 | public DFHttpCliReq useDefaultHeader(boolean use); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFNode.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class DFNode { 4 | /** 5 | * 结点名字 6 | */ 7 | public final String name; 8 | /** 9 | * 结点类型 10 | */ 11 | public final String type; 12 | /** 13 | * 结点主机地址 14 | */ 15 | public final String host; 16 | 17 | public DFNode(String name, String type, String host) { 18 | this.name = name; 19 | this.type = type; 20 | this.host = host; 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | // TODO Auto-generated method stub 26 | return name+"("+type+") from "+host; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/RegNodeReq.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import fun.lib.actor.api.cb.CbNode; 4 | 5 | public final class RegNodeReq { 6 | 7 | protected final int type; 8 | protected final String value; 9 | protected final int srcId; 10 | protected final CbNode cb; 11 | 12 | protected RegNodeReq(int type, String value, int srcId, CbNode cb) { 13 | this.type = type; 14 | this.value = value; 15 | this.srcId = srcId; 16 | this.cb = cb; 17 | } 18 | 19 | public static final int ALL = 0; 20 | public static final int NODE_TYPE = 1; 21 | public static final int NODE_NAME = 2; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/IScriptHttpSvrReq.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.util.Iterator; 4 | import java.util.Map.Entry; 5 | 6 | import fun.lib.actor.api.http.DFHttpSvrRsp; 7 | 8 | public interface IScriptHttpSvrReq { 9 | 10 | public String getMethod(); 11 | public String getUri(); 12 | public String getContentType(); 13 | public int getContentLength(); 14 | public boolean isIsStr(); 15 | public Object getContent(); 16 | public String header(String key); 17 | public String getUserAgent(); 18 | 19 | public Iterator> getFieldIterator(); 20 | 21 | public DFHttpSvrRsp response(Object data); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFActorMongo.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | import com.mongodb.client.MongoDatabase; 4 | 5 | import fun.lib.actor.po.DFMongoCfg; 6 | 7 | public interface DFActorMongo { 8 | /** 9 | * 初始化mongodb连接池 10 | * @param cfg mongodb连接池牌配置 11 | * @return 大于 有效的连接池id 小于等于0 创建连接池失败 12 | */ 13 | public int initPool(DFMongoCfg cfg); 14 | 15 | /** 16 | * 获取一个mongodb数据库 17 | * @param id 连接池id 18 | * @param dbName 数据库名字 19 | * @return 数据库 20 | */ 21 | public MongoDatabase getDatabase(int id, String dbName); 22 | /** 23 | * 关闭指定连接池并释放资源 24 | * @param id 连接池id 25 | */ 26 | public void closePool(int id); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/IScriptBuffer.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | public interface IScriptBuffer { 4 | 5 | public int leftRead(); 6 | 7 | public boolean writeInt(int num); 8 | public boolean writeShort(int num); 9 | public boolean writeByte(int num); 10 | public boolean writeStr(String src, int len); 11 | public boolean writeBytes(IScriptBuffer src); 12 | 13 | public int readInt(); 14 | public int readShort(); 15 | public int readByte(); 16 | public String readStr(int len); 17 | 18 | public int getInt(int idx); 19 | public int getShort(int idx); 20 | public int getByte(int idx); 21 | 22 | public void release(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/http/DFHttpHeader.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.http; 2 | 3 | import io.netty.handler.codec.http.HttpHeaderNames; 4 | 5 | public final class DFHttpHeader { 6 | 7 | public static final String CONTENT_TYPE = HttpHeaderNames.CONTENT_TYPE.toString(); //"Content-Type"; 8 | public static final String CONTENT_LENGTH = HttpHeaderNames.CONTENT_LENGTH.toString() ; //"Content-Length"; 9 | public static final String CONNECTION = HttpHeaderNames.CONNECTION.toString(); //"Connection"; 10 | public static final String USER_AGENT = HttpHeaderNames.USER_AGENT.toString(); //"User-Agent"; 11 | public static final String KEEP_ALIVE = "keep-alive"; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/script/DFWebResModel.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.script; 2 | 3 | 4 | import fun.lib.actor.api.http.DFHttpContentType; 5 | 6 | public final class DFWebResModel { 7 | 8 | public final String path; 9 | public final byte[] data; 10 | public final int dataLen; 11 | public final String contentType; //default 12 | 13 | 14 | public DFWebResModel(String path, String contentType, byte[] data, int dataLen) { 15 | this.path = path; 16 | if(contentType != null){ 17 | this.contentType = contentType; 18 | }else{ 19 | this.contentType = DFHttpContentType.OCTET_STREAM; 20 | } 21 | this.data = data; 22 | this.dataLen = dataLen; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFActorTimer.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | import fun.lib.actor.api.cb.CbTimeout; 4 | 5 | public interface DFActorTimer { 6 | 7 | /** 8 | * 注册计时器,仅回调一次 9 | * @param delayMilli 延迟毫秒数 10 | * @param requestId 请求标识 11 | */ 12 | public void timeout(int delayMilli, int requestId); 13 | 14 | /** 15 | * 注册计时器,仅回调一次 16 | * @param delayMilli 延迟毫秒数 17 | * @param cb 超时回调函数 18 | */ 19 | public void timeout(int delayMilli, CbTimeout cb); 20 | 21 | /** 22 | * 获取计时器启动时间,单位毫秒 23 | * @return 时间 24 | */ 25 | public long getTimeStart(); 26 | /** 27 | * 获取计时器当前时间,单位毫秒 28 | * @return 时间 29 | */ 30 | public long getTimeNow(); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/http/DFHttpCliRsp.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.http; 2 | 3 | import java.util.Iterator; 4 | import java.util.Map.Entry; 5 | 6 | import fun.lib.actor.core.IScriptBuffer; 7 | import io.netty.buffer.ByteBuf; 8 | 9 | public interface DFHttpCliRsp { 10 | 11 | public boolean isBinary(); 12 | public boolean isIsStr(); 13 | public int getContentLength(); 14 | 15 | public Object getContent(); 16 | public ByteBuf getContentBuf(); 17 | public String getContentStr(); 18 | 19 | public String getContentType(); 20 | public Iterator> getHeaderIterator(); 21 | public String header(String name); 22 | public int getStatus(); 23 | public void release(); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/db/DFDbSrc.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.db; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | import org.apache.tomcat.jdbc.pool.DataSource; 7 | 8 | public final class DFDbSrc { 9 | 10 | private volatile DataSource dbSrc = null; 11 | 12 | public DFDbSrc(final DataSource dbSrc) { 13 | this.dbSrc = dbSrc; 14 | } 15 | 16 | public Connection getConn(){ 17 | if(dbSrc != null){ 18 | try { 19 | return dbSrc.getConnection(); 20 | } catch (SQLException e) { 21 | e.printStackTrace(); 22 | return null; 23 | } 24 | } 25 | return null; 26 | } 27 | 28 | public void close(){ 29 | if(dbSrc != null){ 30 | dbSrc.close(); 31 | } 32 | dbSrc = null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/script/DFJsUtil.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.script; 2 | 3 | import jdk.nashorn.api.scripting.ScriptObjectMirror; 4 | 5 | public final class DFJsUtil { 6 | 7 | public static boolean isJsFunction(Object func){ 8 | if(func != null && func instanceof ScriptObjectMirror){ 9 | ScriptObjectMirror mir = (ScriptObjectMirror) func; 10 | return mir.isFunction(); 11 | } 12 | return false; 13 | } 14 | 15 | public static boolean isJsArray(Object arr){ 16 | if(arr != null && arr instanceof ScriptObjectMirror){ 17 | ScriptObjectMirror mir = (ScriptObjectMirror) arr; 18 | boolean b = mir.isArray(); 19 | b = mir.isExtensible(); 20 | 21 | return mir.isArray(); 22 | } 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFHttpData.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import io.netty.handler.codec.http.multipart.FileUpload; 7 | 8 | public final class DFHttpData { 9 | 10 | private final FileUpload fileUp; 11 | 12 | protected DFHttpData(FileUpload fileUp) { 13 | this.fileUp = fileUp; 14 | } 15 | 16 | 17 | //api 18 | public String getContentType(){ 19 | return fileUp.getContentType(); 20 | } 21 | public String getField(){ 22 | return fileUp.getName(); 23 | } 24 | public String getFileName(){ 25 | return fileUp.getFilename(); 26 | } 27 | public boolean moveTo(String dstPath) throws IOException{ 28 | return fileUp.renameTo(new File(dstPath)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFActorDb.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | import java.sql.Connection; 4 | 5 | import fun.lib.actor.po.DFDbCfg; 6 | 7 | public interface DFActorDb { 8 | /** 9 | * 初始化db连接池 10 | * @param cfg db连接池牌配置 11 | * @return 大于0 有效的连接池id 小于等于0 创建连接池失败 12 | */ 13 | public int initPool(DFDbCfg cfg) ; 14 | 15 | /** 16 | * 获取一个db连接 17 | * @param id 连接池id 18 | * @return 连接 19 | */ 20 | public Connection getConn(int id); 21 | /** 22 | * 关闭连接 23 | * @param conn 连接对象 24 | */ 25 | public void closeConn(Connection conn); 26 | /** 27 | * 关闭指定连接池并释放资源 28 | * @param id 连接池id 29 | */ 30 | public void closePool(int id); 31 | /** 32 | * 获取最近一次错误信息 33 | * @return 错误信息 34 | */ 35 | public String getLastError(); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorMongoWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import com.mongodb.client.MongoDatabase; 4 | 5 | import fun.lib.actor.api.DFActorMongo; 6 | import fun.lib.actor.po.DFMongoCfg; 7 | 8 | public final class DFActorMongoWrap implements DFActorMongo{ 9 | 10 | private final DFDbManager dbMgr; 11 | 12 | protected DFActorMongoWrap() { 13 | dbMgr = DFDbManager.get(); 14 | } 15 | 16 | @Override 17 | public int initPool(DFMongoCfg cfg) { 18 | return dbMgr.initMongoPool(cfg); 19 | } 20 | @Override 21 | public MongoDatabase getDatabase(int id, String dbName) { 22 | return dbMgr.getMongoDatabase(id, dbName); 23 | } 24 | 25 | @Override 26 | public void closePool(int id) { 27 | dbMgr.closeMongoPool(id); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/db/DFDbMSConfig.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.db; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | public final class DFDbMSConfig { 8 | 9 | public final DFDbConfig master; 10 | private final List lsSlave; 11 | public final int slaveNum; 12 | 13 | public DFDbMSConfig(DFDbConfig master, List lsSlave) { 14 | this.master = master; 15 | this.lsSlave = new ArrayList<>(lsSlave.size()); 16 | for(DFDbConfig cfg : lsSlave){ 17 | this.lsSlave.add(cfg); 18 | } 19 | slaveNum = this.lsSlave.size(); 20 | } 21 | 22 | public DFDbConfig getSlave(int idx){ 23 | if(idx >= 0 && idx < slaveNum){ 24 | return lsSlave.get(idx); 25 | } 26 | return null; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/cb/CallHereContext.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.cb; 2 | 3 | import fun.lib.actor.api.DFActorDb; 4 | import fun.lib.actor.api.DFActorLog; 5 | import fun.lib.actor.api.DFActorMongo; 6 | import fun.lib.actor.api.DFActorNet; 7 | import fun.lib.actor.api.DFActorRedis; 8 | import fun.lib.actor.api.DFActorSystem; 9 | import fun.lib.actor.api.DFActorTimer; 10 | 11 | public interface CallHereContext { 12 | 13 | public String getActorName(); 14 | 15 | public void callback(int cmd, Object payload); 16 | 17 | public DFActorLog getLog(); 18 | public DFActorSystem getSys(); 19 | public DFActorNet getNet(); 20 | public DFActorTimer getTimer(); 21 | public DFActorRedis getRedisWrap(); 22 | public DFActorDb getDb(); 23 | public DFActorMongo getMongo(); 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/StartAsDaemon.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.core.DFActorManager; 4 | import fun.lib.actor.po.DFActorManagerConfig; 5 | 6 | /** 7 | * daemon模式启动dfactor示例, 加载外部jar执行逻辑 8 | * @author lostsky 9 | * 10 | */ 11 | public final class StartAsDaemon { 12 | 13 | public static void main(String[] args) { 14 | String dirJar = "F:/dev/guaji/svn/program/server/src/dfactor"; 15 | // String dirJar = "/var/dfactor/ext"; //jar文件存放目录 16 | String entryFullName = "fun.test.spi.TestEntryActor"; //启动actor全路径名,要求继承DFActor 17 | String param = "launch param"; //传入启动actor的参数 18 | DFActorManagerConfig cfg = new DFActorManagerConfig(); 19 | // 20 | DFActorManager.get().startAsDaemon(cfg, dirJar, entryFullName, param); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFActorRedis.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | import fun.lib.actor.po.DFRedisCfg; 4 | import redis.clients.jedis.Jedis; 5 | 6 | public interface DFActorRedis { 7 | /** 8 | * 初始化redis连接池 9 | * @param cfg redis连接池牌配置 10 | * @return 大于 有效的连接池id 小于等于 创建连接池失败 11 | */ 12 | public int initPool(DFRedisCfg cfg); 13 | 14 | /** 15 | * 获取一个redis连接 16 | * @param id 连接池id 17 | * @return 连接 18 | */ 19 | public Jedis getConn(int id); 20 | 21 | /** 22 | * 关闭连接 23 | * @param conn 连接对象 24 | */ 25 | public void closeConn(Jedis conn); 26 | 27 | /** 28 | * 关闭指定连接池并释放资源 29 | * @param id 连接池id 30 | */ 31 | public void closePool(int id); 32 | 33 | /** 34 | * 最近一次错误信息 35 | * @return 错误信息 36 | */ 37 | public String getLastError(); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/concurrent/DFSpinLock.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.concurrent; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | 5 | public final class DFSpinLock{ 6 | 7 | private final AtomicBoolean _owner = new AtomicBoolean(false); 8 | 9 | public void lock(){ 10 | // final long tmStart = System.nanoTime(); 11 | while(!_owner.compareAndSet(false, true)){ 12 | 13 | } 14 | // final int tmCost = (int) (System.nanoTime() - tmStart); 15 | // if(tmCost > 5000000){ 16 | // int m = 1; 17 | // int n = m; 18 | // } 19 | } 20 | public boolean tryLock(int tryTimes){ 21 | while(!_owner.compareAndSet(false, true)){ 22 | if(--tryTimes < 1){ 23 | return false; 24 | } 25 | } 26 | return true; 27 | } 28 | 29 | public void unlock(){ 30 | _owner.compareAndSet(true, false); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/http/DFHttpContentType.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.http; 2 | 3 | import io.netty.handler.codec.http.HttpHeaderValues; 4 | 5 | public final class DFHttpContentType { 6 | 7 | public static final String TEXT_HTML = "text/html"; 8 | public static final String TEXT_PLAIN = HttpHeaderValues.TEXT_PLAIN.toString();// "text/plain"; 9 | public static final String FORM = HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString();// "application/x-www-form-urlencoded"; 10 | public static final String JSON = HttpHeaderValues.APPLICATION_JSON.toString(); //"application/json"; 11 | public static final String XML = "application/xml"; 12 | public static final String OCTET_STREAM = HttpHeaderValues.APPLICATION_OCTET_STREAM.toString(); //"application/octet-stream"; 13 | // public static final String UNKNOWN = "unknown"; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFTcpChannel.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | public interface DFTcpChannel { 4 | /** 5 | * 获取远程连接主机地址 6 | * @return 地址 7 | */ 8 | public String getRemoteHost(); 9 | /** 10 | * 获取远程连接端口 11 | * @return 端口 12 | */ 13 | public int getRemotePort(); 14 | /** 15 | * 发送消息 16 | * @param msg 消息 17 | * @return 0 18 | */ 19 | public int write(Object msg); 20 | 21 | /** 22 | * 关闭连接 23 | */ 24 | public void close(); 25 | /** 26 | * 连接是否关闭 27 | * @return 是/否 28 | */ 29 | public boolean isClosed(); 30 | /** 31 | * 获取当前连接的id 32 | * @return id 33 | */ 34 | public int getChannelId(); 35 | /** 36 | * 获取连接建立时间 37 | * @return 时间 38 | */ 39 | public long getOpenTime(); 40 | 41 | 42 | // 43 | public void setStatusActor(int actorId); 44 | public void setMessageActor(int actorId); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/IVirtualHost.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | public interface IVirtualHost { 4 | 5 | public int getPort(); 6 | public void close(); 7 | 8 | public static final String JS_INNER_ANALYZER = "df_kadajsapi"; 9 | public static final String JS_DF_NAME = "df_uqO3k8aRl"; 10 | public static final String JS_QUERY_IT = "df_Undk12ual"; 11 | public static final String JS_HEADER_IT = "df_dHjq34tikp"; 12 | public static final String JS_SESSION_IT = "df_mNE7rMpqk"; 13 | public static final String JS_IS_GET = "df_k23sDf73op"; 14 | public static final String JS_API_NAME = "df_Jk17DuRoqp"; 15 | public static final String JS_DIR = "_DIR_"; 16 | public static final String JS_FILE = "_FILE_"; 17 | public static final String JS_PAGE_ID = "_PAGE_ID_"; 18 | public static final String JS_INPUT = "_INPUT"; 19 | public static final String JS_ARGS = "_ARG"; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/RpcFutureWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import fun.lib.actor.api.cb.Cb; 4 | import fun.lib.actor.api.cb.RpcFuture; 5 | 6 | public final class RpcFutureWrap implements RpcFuture{ 7 | 8 | private Cb cb = null; 9 | private final boolean sendSucc; 10 | private final int sessionId; 11 | 12 | private final DFActorSystemWrap sysWrap; 13 | 14 | protected RpcFutureWrap(boolean sendSucc, int sessionId, DFActorSystemWrap sysWrap) { 15 | this.sendSucc = sendSucc; 16 | this.sessionId = sessionId; 17 | this.sysWrap = sysWrap; 18 | } 19 | 20 | @Override 21 | public boolean addListener(Cb cb, int timeoutMilli) { 22 | if(sendSucc){ 23 | this.cb = cb; 24 | sysWrap.addCallback(cb, sessionId, timeoutMilli); 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean isSendSucc() { 32 | return sendSucc; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/Startup.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.core.DFActor; 4 | import fun.lib.actor.core.DFActorManager; 5 | /** 6 | * 快速启动一个dfactor示例 7 | * @author lostsky 8 | * 9 | */ 10 | public final class Startup { 11 | 12 | public static void main(String[] args) { 13 | final DFActorManager mgr = DFActorManager.get(); 14 | //启动入口actor,开始消息循环 15 | mgr.start(EntryActor.class); 16 | } 17 | 18 | /** 19 | * 入口actor 20 | * @author lostsky 21 | * 22 | */ 23 | private static class EntryActor extends DFActor{ 24 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 25 | super(id, name, isBlockActor); 26 | // TODO Auto-generated constructor stub 27 | } 28 | @Override 29 | public void onStart(Object param) { 30 | //使用自带日志打印 31 | log.info("EntryActor start, curThread="+Thread.currentThread().getName()); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFActorResult.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class DFActorResult { 4 | 5 | public final int code; 6 | public final String msg; 7 | public final int extInt; 8 | public final String extString; 9 | public final Object extObj; 10 | 11 | public DFActorResult(int code, String msg) { 12 | this.code = code; 13 | this.msg = msg; 14 | this.extInt = 0; 15 | this.extString = null; 16 | this.extObj = null; 17 | } 18 | public DFActorResult(int code, String msg, int extInt, String extString) { 19 | this.code = code; 20 | this.msg = msg; 21 | this.extInt = extInt; 22 | this.extString = extString; 23 | this.extObj = null; 24 | } 25 | public DFActorResult(int code, String msg, int extInt, String extString, Object extObj) { 26 | this.code = code; 27 | this.msg = msg; 28 | this.extInt = extInt; 29 | this.extString = extString; 30 | this.extObj = extObj; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFSSLConfig.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class DFSSLConfig { 4 | /** 5 | * 证书文件路径 6 | */ 7 | private String certPath; 8 | /** 9 | * 私钥文件路径 10 | */ 11 | private String pemPath; 12 | 13 | private DFSSLConfig() { 14 | } 15 | 16 | /** 17 | * 设置证书文件路径 18 | * @param path 19 | * @return 20 | */ 21 | public DFSSLConfig certPath(String path){ 22 | certPath = path; 23 | return this; 24 | } 25 | /** 26 | * 设置私钥文件路径 27 | * @param path 28 | * @return 29 | */ 30 | public DFSSLConfig pemPath(String path){ 31 | pemPath = path; 32 | return this; 33 | } 34 | /** 35 | * 获取证书文件路径 36 | * @return 37 | */ 38 | public String getCertPath(){ 39 | return certPath; 40 | } 41 | /** 42 | * 获取私钥文件路径 43 | * @return 44 | */ 45 | public String getPemPath(){ 46 | return pemPath; 47 | } 48 | 49 | // 50 | public static DFSSLConfig newCfg(){ 51 | return new DFSSLConfig(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFUdpChannelWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import fun.lib.actor.api.DFUdpChannel; 4 | import fun.lib.actor.kcp.KcpServer; 5 | import io.netty.channel.Channel; 6 | 7 | public final class DFUdpChannelWrap implements DFUdpChannel{ 8 | 9 | private volatile Channel channel = null; 10 | protected DFUdpChannelWrap(){ 11 | 12 | } 13 | private volatile KcpServer kcpServer; 14 | protected KcpServer getKcpServer(){ 15 | return this.kcpServer; 16 | } 17 | protected void setKcpServer(KcpServer kcpServer){ 18 | if(this.kcpServer != null){ 19 | return ; 20 | } 21 | this.kcpServer = kcpServer; 22 | } 23 | 24 | protected void onChannelActive(Channel channel){ 25 | if(this.channel != null){ 26 | return ; 27 | } 28 | this.channel = channel; 29 | } 30 | 31 | @Override 32 | public int write(Object msg) { 33 | if(channel != null){ 34 | channel.writeAndFlush(msg); 35 | return 0; 36 | } 37 | return 1; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorTimerWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import fun.lib.actor.api.DFActorTimer; 4 | import fun.lib.actor.api.cb.CbTimeout; 5 | 6 | public final class DFActorTimerWrap implements DFActorTimer{ 7 | 8 | private final int id; 9 | private final DFActorManager _mgr; 10 | 11 | protected DFActorTimerWrap(int id) { 12 | this.id = id; 13 | _mgr = DFActorManager.get(); 14 | } 15 | 16 | @Override 17 | public void timeout(int delayMilli, int requestId) { 18 | _mgr.addTimeout(id, DFActor.transTimeRealToTimer(delayMilli), DFActorDefine.SUBJECT_TIMER, requestId, null); 19 | } 20 | 21 | @Override 22 | public void timeout(int delayMilli, CbTimeout cb) { 23 | _mgr.addTimeout(id, DFActor.transTimeRealToTimer(delayMilli), DFActorDefine.SUBJECT_TIMER, 0, cb); 24 | } 25 | 26 | @Override 27 | public long getTimeStart() { 28 | return _mgr.getTimerStartNano(); 29 | } 30 | 31 | @Override 32 | public long getTimeNow() { 33 | return _mgr.getTimerNowNano(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorRedisWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import fun.lib.actor.api.DFActorRedis; 4 | import fun.lib.actor.po.DFRedisCfg; 5 | import redis.clients.jedis.Jedis; 6 | 7 | public final class DFActorRedisWrap implements DFActorRedis{ 8 | private final DFDbManager dbMgr; 9 | 10 | private String lastError = null; 11 | 12 | protected DFActorRedisWrap() { 13 | dbMgr = DFDbManager.get(); 14 | } 15 | @Override 16 | public int initPool(DFRedisCfg cfg) { 17 | try { 18 | return dbMgr.initRedisPool(cfg); 19 | } catch (Throwable e) { 20 | lastError = e.getMessage(); 21 | } 22 | return -1; 23 | } 24 | @Override 25 | public Jedis getConn(int id) { 26 | return dbMgr.getRedisConn(id); 27 | } 28 | @Override 29 | public void closePool(int id) { 30 | dbMgr.closeRedisPool(id); 31 | } 32 | @Override 33 | public void closeConn(Jedis conn) { 34 | if(conn != null){ 35 | conn.close(); 36 | } 37 | } 38 | @Override 39 | public String getLastError() { 40 | return lastError; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFActorTcpDispatcher.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | 3 | import java.net.InetSocketAddress; 4 | 5 | 6 | public interface DFActorTcpDispatcher { 7 | /** 8 | * 创建连接通知(io线程中回调) 9 | * @param requestId 创建连接时的唯一标识 10 | * @param channelId 会话id 11 | * @param addrRemote 远程连接地址 12 | * @return 接收创建连接事件的actorId, 0则不分发 13 | */ 14 | public int onConnActiveUnsafe(int requestId, int channelId, InetSocketAddress addrRemote); 15 | /** 16 | * 连接断开通知(io线程中回调) 17 | * @param requestId 创建连接时的唯一标识 18 | * @param channelId 会话id 19 | * @param addrRemote 远程连接地址 20 | * @return 接收连接断开事件的actorId, 0则不分发 21 | */ 22 | public int onConnInactiveUnsafe(int requestId, int channelId, InetSocketAddress addrRemote); 23 | /** 24 | * 获取要转发到的actorId(io线程中回调) 25 | * @param requestId 创建连接时的唯一标识 26 | * @param channelId 会话id 27 | * @param addrRemote 远程连接地址 28 | * @param msg 消息 29 | * @return 接收消息的actorId, 0则不分发 30 | */ 31 | public int onQueryMsgActorId(int requestId, int channelId, InetSocketAddress addrRemote, Object msg); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/kcp/KcpConfigInner.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.kcp; 2 | 3 | public final class KcpConfigInner { 4 | 5 | protected final int sendWnd; 6 | protected final int recvWnd; 7 | protected final short fastResendTrig; 8 | protected final short resendMax; 9 | protected final int sendTimeout; 10 | protected final int idleTimeout; 11 | 12 | protected KcpConfigInner(int sendWnd, int recvWnd, short fastResendTrig, 13 | short resendMax, int sendTimeout, int idleTimeout) { 14 | this.sendWnd = sendWnd; 15 | this.recvWnd = recvWnd; 16 | this.fastResendTrig = fastResendTrig; 17 | this.resendMax = resendMax; 18 | this.sendTimeout = sendTimeout; 19 | this.idleTimeout = idleTimeout; 20 | } 21 | 22 | 23 | // 24 | public static KcpConfigInner copyConfig(final KcpConfig cfgOri){ 25 | final KcpConfigInner cfg = new KcpConfigInner(cfgOri.getSendWnd(), 26 | cfgOri.getRecvWnd(), cfgOri.getFastResendTrig(), 27 | cfgOri.getResendMax(), cfgOri.getSendTimeout(), 28 | cfgOri.getIdleTimeout()); 29 | return cfg; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 lostsky3000 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFJsLaunchActor.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.script.Bindings; 7 | import javax.script.ScriptContext; 8 | import javax.script.ScriptEngine; 9 | import jdk.nashorn.api.scripting.ScriptObjectMirror; 10 | 11 | public final class DFJsLaunchActor extends DFActor{ 12 | 13 | public DFJsLaunchActor(Integer id, String name, Boolean isBlockActor) { 14 | super(id, name, isBlockActor); 15 | // TODO Auto-generated constructor stub 16 | } 17 | 18 | @Override 19 | public void onStart(Object param) { 20 | Map mapParam = (Map) param; 21 | ScriptEngine engine = (ScriptEngine) mapParam.get("engine"); 22 | String entryActor = (String) mapParam.get("entryActor"); 23 | String entryActorName = (String) mapParam.get("entryActorName"); 24 | Bindings bind = engine.getBindings(ScriptContext.ENGINE_SCOPE); 25 | // 26 | ScriptObjectMirror mirFunc = (ScriptObjectMirror) bind.get(entryActor); 27 | // 28 | DFActorManagerJs.get().createActor(mirFunc, entryActorName, null, null); 29 | mapParam.clear(); mapParam = null; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/Shutdown.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.core.DFActor; 4 | import fun.lib.actor.core.DFActorManager; 5 | /** 6 | * 关闭整个dfactor示例 7 | * @author lostsky 8 | * 9 | */ 10 | public final class Shutdown { 11 | 12 | public static void main(String[] args) { 13 | final DFActorManager mgr = DFActorManager.get(); 14 | //启动入口actor,开始消息循环 15 | mgr.start("EntryActor", EntryActor.class); 16 | } 17 | 18 | /** 19 | * 入口actor 20 | * @author lostsky 21 | * 22 | */ 23 | private static class EntryActor extends DFActor{ 24 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 25 | super(id, name, isBlockActor); 26 | // TODO Auto-generated constructor stub 27 | } 28 | @Override 29 | public void onStart(Object param) { 30 | //使用自带日志打印 31 | log.info("EntryActor start, curThread="+Thread.currentThread().getName()); 32 | //启动定时器 33 | timer.timeout(1000, 1); 34 | } 35 | 36 | @Override 37 | public void onTimeout(int requestId) { 38 | log.info("onTimeout, requestId="+requestId+", curThread="+Thread.currentThread().getName()); 39 | //关闭整个dfactor 40 | sys.shutdown(); 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/ExitActor.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.core.DFActor; 4 | import fun.lib.actor.core.DFActorManager; 5 | /** 6 | * 退出actor示例 7 | * @author lostsky 8 | * 9 | */ 10 | public final class ExitActor { 11 | 12 | public static void main(String[] args) { 13 | final DFActorManager mgr = DFActorManager.get(); 14 | //启动入口actor,开始消息循环 15 | mgr.start(EntryActor.class); 16 | } 17 | 18 | /** 19 | * 入口actor 20 | * @author lostsky 21 | * 22 | */ 23 | private static class EntryActor extends DFActor{ 24 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 25 | super(id, name, isBlockActor); 26 | // TODO Auto-generated constructor stub 27 | } 28 | @Override 29 | public void onStart(Object param) { 30 | //使用自带日志打印 31 | log.info("EntryActor start, curThread="+Thread.currentThread().getName()); 32 | //启动定时器 33 | timer.timeout(1000, 1); 34 | } 35 | 36 | @Override 37 | public void onTimeout(int requestId) { 38 | log.info("onTimeout, requestId="+requestId+", curThread="+Thread.currentThread().getName()); 39 | //退出当前actor 40 | sys.exit(); 41 | log.info("exit EntryActor"); 42 | } 43 | 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/Schedule.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.core.DFActor; 4 | import fun.lib.actor.core.DFActorManager; 5 | import fun.lib.actor.po.ActorProp; 6 | /** 7 | * 定时回调示例 8 | * @author lostsky 9 | * 10 | */ 11 | public final class Schedule { 12 | 13 | public static void main(String[] args) { 14 | final DFActorManager mgr = DFActorManager.get(); 15 | //启动入口actor,开始消息循环 16 | mgr.start(ActorProp.newProp() 17 | .name("EntryActor") 18 | .classz(EntryActor.class) 19 | .scheduleMilli(1000)); 20 | } 21 | 22 | /** 23 | * 入口actor 24 | * @author lostsky 25 | * 26 | */ 27 | private static class EntryActor extends DFActor{ 28 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 29 | super(id, name, isBlockActor); 30 | // TODO Auto-generated constructor stub 31 | } 32 | @Override 33 | public void onStart(Object param) { 34 | //使用自带日志打印 35 | log.info("EntryActor start, curThread="+Thread.currentThread().getName()); 36 | 37 | } 38 | @Override 39 | public void onSchedule(long dltMilli) { 40 | log.info("onSchedule, dltMilli="+dltMilli+", curThread="+Thread.currentThread().getName()); 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cert.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDVzCCAj+gAwIBAgIJAMDTFzz6BN5dMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV 3 | BAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg 4 | Q29tcGFueSBMdGQwHhcNMTgwNDI1MDcyNzM4WhcNMTkwNDI1MDcyNzM4WjBCMQsw 5 | CQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZh 6 | dWx0IENvbXBhbnkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 7 | qV+IFRmWQKEtBnAs04DIxDXq2vxNhvkgc0nflULod3BrETR0ZCXMqNyJwoVafo4d 8 | cyFRp/RCdknw9xsAdiKMvd9XzC56ZYFEy1GuV4V9i3CynUN5yFQC9wAXiRaJeKkl 9 | Cuwt0t3s/TFBRMe0mwBudNZ3HAsR1VNjVQUI4oCYUDmII2Km7DkuhE6QkTdKfQvH 10 | yghJWuFYA4GkGksSWxTsZkD3kT4LutZrjjQS9euWpN+vvzsVV6F/Hb9Yv/6x+u8B 11 | FctO8a8nR2DM2J8zk82krHxCgGlGvzvh4qGQG8iiPF81c8zCqGzBcwZY18p6RcSf 12 | 9FyXtzwMKkr/G/p0fLLnbQIDAQABo1AwTjAdBgNVHQ4EFgQUacX6Svl01Z1lfkBg 13 | jfskow7hbg0wHwYDVR0jBBgwFoAUacX6Svl01Z1lfkBgjfskow7hbg0wDAYDVR0T 14 | BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAGZmnNP/2AvyluXqNYLall5zkF9qs 15 | nmKa4eFoHyfBylI9kYumSU6iKmlpl7Ni8cvwv8TCq4cSiwUe0HERT40jCeASPgr+ 16 | rdeHs/AnalDskiPo0zYbOmfn1gHgdbHBUaCrlGYZReHURGJeM1vBrH8UzYSiaieG 17 | xVuB+JjI/8OoNKjj4sTaNT3tUO4D3feFAu+IbK6QNkTi+Pf+mKDuvruBx6dsvkU2 18 | IPPTgfql04AERRDeeb/2ZzIfTcvYWzHn8OuSLvzyGS5T1ZmLecCDV2KTSD19pDnz 19 | RngeuvmT1+ZZssAfj8x1gtlSiuGHxaDj2a0WcjmGFUL8jHJd9iPLyCoe+A== 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/cache/DFRedisUtil.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.cache; 2 | 3 | import redis.clients.jedis.JedisPool; 4 | import redis.clients.jedis.JedisPoolConfig; 5 | 6 | public final class DFRedisUtil { 7 | 8 | public static JedisPool createJedisPool(String host, int port, String auth, 9 | int maxTotal, int maxIdle, int minIdle){ 10 | return createJedisPool(host, port, auth, maxTotal, maxIdle, minIdle, 1000*5, 1000*10); 11 | } 12 | 13 | public static JedisPool createJedisPool(String host, int port, String auth, 14 | int maxTotal, int maxIdle, int minIdle, int connTimeoutMilli, int borrowTimeoutMilli){ 15 | JedisPoolConfig config = new JedisPoolConfig(); 16 | //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。 17 | config.setMaxTotal(maxTotal); 18 | //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。 19 | config.setMaxIdle(maxIdle); 20 | config.setMinIdle(minIdle); 21 | //表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException; 22 | config.setMaxWaitMillis(borrowTimeoutMilli); 23 | //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的; 24 | config.setTestOnBorrow(true); 25 | return new JedisPool(config, host, port, connTimeoutMilli, auth); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorDbWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | import fun.lib.actor.api.DFActorDb; 7 | import fun.lib.actor.po.DFDbCfg; 8 | 9 | public final class DFActorDbWrap implements DFActorDb{ 10 | private final DFDbManager dbMgr; 11 | 12 | private String lastError = null; 13 | 14 | protected DFActorDbWrap() { 15 | dbMgr = DFDbManager.get(); 16 | } 17 | @Override 18 | public int initPool(DFDbCfg cfg) { 19 | try { 20 | return dbMgr.initDbPool(cfg); 21 | } catch (Throwable e) { 22 | lastError = e.getMessage(); 23 | } 24 | return -1; 25 | } 26 | @Override 27 | public Connection getConn(int id) { 28 | try { 29 | return dbMgr.getDbConn(id); 30 | } catch (SQLException e) { 31 | lastError = e.getMessage(); 32 | } 33 | return null; 34 | } 35 | @Override 36 | public void closePool(int id) { 37 | dbMgr.closeDbPool(id); 38 | } 39 | @Override 40 | public void closeConn(Connection conn) { 41 | if(conn != null){ 42 | try { 43 | conn.close(); 44 | } catch (Throwable e) { 45 | e.printStackTrace(); 46 | lastError = e.getMessage(); 47 | } 48 | } 49 | } 50 | @Override 51 | public String getLastError() { 52 | return lastError; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorLogWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import com.funtag.util.log.DFLogFactory; 4 | 5 | import fun.lib.actor.api.DFActorLog; 6 | import fun.lib.actor.helper.ActorLogData; 7 | 8 | public final class DFActorLogWrap implements DFActorLog{ 9 | private final DFActorManager mgr; 10 | private final int id; 11 | private final String name; 12 | public DFActorLogWrap(int id, String name) { 13 | this.id = id; 14 | this.name = name; 15 | this.mgr = DFActorManager.get(); 16 | } 17 | 18 | @Override 19 | public void verb(Object msg) { 20 | _log(DFLogFactory.LEVEL_VERB, msg); 21 | } 22 | @Override 23 | public void debug(Object msg) { 24 | _log(DFLogFactory.LEVEL_DEBUG, msg); 25 | } 26 | @Override 27 | public void info(Object msg) { 28 | _log(DFLogFactory.LEVEL_INFO, msg); 29 | } 30 | @Override 31 | public void warn(Object msg) { 32 | _log(DFLogFactory.LEVEL_WARN, msg); 33 | } 34 | @Override 35 | public void error(Object msg) { 36 | _log(DFLogFactory.LEVEL_ERROR, msg); 37 | } 38 | @Override 39 | public void fatal(Object msg) { 40 | _log(DFLogFactory.LEVEL_FATAL, msg); 41 | } 42 | private final void _log(int level, Object msg){ 43 | mgr.send(id, DFActorDefine.ACTOR_ID_LOG, 0, 0, 0, 44 | new ActorLogData(level, msg, name), true, null, null, false); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/db/DFDbMSSrc.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.db; 2 | 3 | import java.sql.Connection; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | public final class DFDbMSSrc { 8 | 9 | private final DFDbSrc dbSrcMaster; 10 | private final List lsSlave; 11 | private final int slaveNum; 12 | 13 | public DFDbMSSrc(DFDbSrc dbSrcMaster, List lsSlave) { 14 | this.dbSrcMaster = dbSrcMaster; 15 | this.lsSlave = lsSlave; 16 | this.slaveNum = lsSlave.size(); 17 | } 18 | 19 | public Connection getConnMaster(){ 20 | if(dbSrcMaster != null){ 21 | return dbSrcMaster.getConn(); 22 | } 23 | return null; 24 | } 25 | 26 | public Connection getConnSlaveRand(final Random rand){ 27 | if(slaveNum > 0){ 28 | final DFDbSrc s = lsSlave.get(rand.nextInt(slaveNum)); 29 | return s.getConn(); 30 | } 31 | return null; 32 | } 33 | 34 | public Connection getConnSlave(int idx){ 35 | if(idx >= 0 && idx < slaveNum){ 36 | final DFDbSrc s = lsSlave.get(idx); 37 | return s.getConn(); 38 | } 39 | return null; 40 | } 41 | 42 | public int getSlaveNum(){ 43 | return slaveNum; 44 | } 45 | 46 | public void close(){ 47 | if(dbSrcMaster != null){ 48 | dbSrcMaster.close(); 49 | } 50 | if(lsSlave != null){ 51 | for(DFDbSrc s : lsSlave){ 52 | s.close(); 53 | } 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/http/DFHttpSvrReq.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api.http; 2 | 3 | import java.util.Iterator; 4 | import java.util.Map.Entry; 5 | 6 | import com.alibaba.fastjson.JSONObject; 7 | 8 | import fun.lib.actor.core.DFHttpSvrRspWrap; 9 | import io.netty.buffer.ByteBuf; 10 | import io.netty.handler.codec.http.HttpMethod; 11 | 12 | public interface DFHttpSvrReq { 13 | 14 | public Iterator> getQueryDataIterator(); 15 | public Object getQueryData(String name); 16 | public Iterator> getHeaderIterator(); 17 | public String getHeaderValue(String name); 18 | public Object getApplicationData(); 19 | public HttpMethod getMethod(); 20 | public String getContentType(); 21 | public int getContentLength(); 22 | public String getUri(); 23 | public boolean isKeepAlive(); 24 | public void release(); 25 | public boolean contentIsStr(); 26 | public boolean isMultipart(); 27 | 28 | 29 | //response 30 | public DFHttpSvrRsp response(int statusCode); 31 | public DFHttpSvrRsp response(String rspData); 32 | public DFHttpSvrRsp response(int statusCode, String rspData); 33 | public DFHttpSvrRsp response(JSONObject rspData); 34 | public DFHttpSvrRsp response(int statusCode, JSONObject rspData); 35 | public DFHttpSvrRsp response(ByteBuf rspData); 36 | public DFHttpSvrRsp response(int statusCode, ByteBuf rspData); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/db/DFDbUtil.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.db; 2 | 3 | import org.apache.tomcat.jdbc.pool.DataSource; 4 | import org.apache.tomcat.jdbc.pool.PoolProperties; 5 | 6 | public final class DFDbUtil { 7 | 8 | public static DataSource createMysqlDbSource(String url, String user, String pwd, 9 | int initSize, int maxActive, int maxWait, int maxIdle, int minIdle){ 10 | PoolProperties p = new PoolProperties(); 11 | p.setDriverClassName("com.mysql.jdbc.Driver"); 12 | p.setUrl(url); 13 | p.setUsername(user); 14 | p.setPassword(pwd); 15 | p.setJmxEnabled(true); 16 | p.setTestWhileIdle(true); 17 | p.setTestOnBorrow(false); 18 | p.setTestOnReturn(false); 19 | p.setValidationQuery("SELECT 1"); 20 | p.setValidationInterval(30000); 21 | p.setTimeBetweenEvictionRunsMillis(30000); 22 | p.setMaxActive(maxActive); 23 | p.setInitialSize(initSize); 24 | p.setMaxWait(maxWait); //conn timeout 25 | p.setRemoveAbandonedTimeout(60); 26 | p.setMinEvictableIdleTimeMillis(30000); 27 | p.setMaxIdle(maxIdle); 28 | p.setMinIdle(minIdle); 29 | p.setLogAbandoned(true); 30 | p.setRemoveAbandoned(true); 31 | p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+ 32 | "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"); 33 | final DataSource dbSrc = new DataSource(); 34 | dbSrc.setPoolProperties(p); 35 | return dbSrc; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/SimpleHttpServer.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.api.cb.CbHttpServer; 4 | import fun.lib.actor.api.http.DFHttpSvrReq; 5 | import fun.lib.actor.core.DFActor; 6 | import fun.lib.actor.core.DFActorDefine; 7 | import fun.lib.actor.core.DFActorManager; 8 | import fun.lib.actor.po.ActorProp; 9 | import fun.lib.actor.po.DFActorManagerConfig; 10 | import fun.lib.actor.po.DFTcpServerCfg; 11 | /** 12 | * 简单httpserver示例 13 | * @author lostsky 14 | * 15 | */ 16 | public final class SimpleHttpServer { 17 | 18 | public static void main(String[] args) { 19 | DFActorManager.get() 20 | .start(EntryActor.class); //启动入口actor,开始消息循环 21 | } 22 | 23 | private static class EntryActor extends DFActor{ 24 | @Override 25 | public void onStart(Object param) { 26 | net.httpSvr(8080, new CbHttpServer() { 27 | @Override 28 | public int onHttpRequest(Object msg) { 29 | DFHttpSvrReq req = (DFHttpSvrReq) msg; 30 | //response 31 | req.response("echo from server, uri="+req.getUri()) 32 | .send(); 33 | return MSG_AUTO_RELEASE; 34 | } 35 | @Override 36 | public void onListenResult(boolean isSucc, String errMsg) { 37 | log.info("listen result: isSucc="+isSucc+", err="+errMsg); 38 | if(!isSucc){ 39 | sys.shutdown(); 40 | } 41 | } 42 | 43 | }); //start http server 44 | } 45 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 46 | super(id, name, isBlockActor); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/Timeout.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.api.cb.CbTimeout; 4 | import fun.lib.actor.core.DFActor; 5 | import fun.lib.actor.core.DFActorManager; 6 | /** 7 | * 定时器使用示例 8 | * @author lostsky 9 | * 10 | */ 11 | public final class Timeout { 12 | 13 | public static void main(String[] args) { 14 | final DFActorManager mgr = DFActorManager.get(); 15 | //启动入口actor,开始消息循环 16 | mgr.start(EntryActor.class); 17 | } 18 | 19 | /** 20 | * 入口actor 21 | * @author lostsky 22 | * 23 | */ 24 | private static class EntryActor extends DFActor{ 25 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 26 | super(id, name, isBlockActor); 27 | // TODO Auto-generated constructor stub 28 | } 29 | @Override 30 | public void onStart(Object param) { 31 | //使用自带日志打印 32 | log.info("EntryActor start, curThread="+Thread.currentThread().getName()); 33 | //启动定时器 34 | timer.timeout(1000, 1); 35 | } 36 | 37 | private int timeoutCount = 0; //计数器 38 | @Override 39 | public void onTimeout(int requestId) { 40 | log.info("onTimeout(Instance call), count="+(++timeoutCount)+", requestId="+requestId+", curThread="+Thread.currentThread().getName()); 41 | timer.timeout(1000, new CbTimeout() { 42 | @Override 43 | public void onTimeout() { 44 | log.info("onTimeout(CbFunc call), count="+(++timeoutCount)+", curThread="+Thread.currentThread().getName()); 45 | timer.timeout(1000, 1); 46 | } 47 | }); 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/kcp/KcpConfig.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.kcp; 2 | 3 | public final class KcpConfig { 4 | 5 | private int recvWnd = 20; 6 | private int sendWnd = 20; 7 | private short fastResendTrig = 1; 8 | private short resendMax = 30; 9 | private int sendTimeout = 50; 10 | private int idleTimeout = 4000; 11 | 12 | public int getIdleTimeout(){ 13 | return this.idleTimeout; 14 | } 15 | public KcpConfig setIdleTimeout(int idleTimeout){ 16 | this.idleTimeout = idleTimeout; 17 | return this; 18 | } 19 | 20 | public int getSendTimeout(){ 21 | return this.sendTimeout; 22 | } 23 | public KcpConfig setSendTimeout(int sendTimeout){ 24 | this.sendTimeout = sendTimeout; 25 | return this; 26 | } 27 | 28 | public short getResendMax(){ 29 | return this.resendMax; 30 | } 31 | public KcpConfig setResendMax(short resendMax){ 32 | this.resendMax = resendMax; 33 | return this; 34 | } 35 | 36 | public short getFastResendTrig(){ 37 | return this.fastResendTrig; 38 | } 39 | public KcpConfig setFastResendTrig(short fastResendTrig){ 40 | this.fastResendTrig = fastResendTrig; 41 | return this; 42 | } 43 | 44 | public int getSendWnd(){ 45 | return this.sendWnd; 46 | } 47 | public KcpConfig setSendWnd(int sendWnd){ 48 | if(sendWnd > 0){ 49 | this.sendWnd = sendWnd; 50 | } 51 | return this; 52 | } 53 | // 54 | public int getRecvWnd(){ 55 | return this.recvWnd; 56 | } 57 | public KcpConfig setRecvWnd(int recvWnd){ 58 | if(recvWnd > 0){ 59 | this.recvWnd = recvWnd; 60 | } 61 | return this; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorMessage.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | public final class DFActorMessage { 4 | 5 | protected int srcId; 6 | protected int dstId; 7 | protected int sessionId; 8 | protected byte subject; 9 | protected int cmd; 10 | protected Object payload; 11 | protected Object context; 12 | protected Object userHandler; 13 | protected Object payload2; 14 | protected boolean isCb = false; 15 | protected String method = null; 16 | 17 | public DFActorMessage(int srcId, int dstId, int sessionId, 18 | int subject, int cmd, Object payload, Object context, Object userHandler, boolean isCb, 19 | Object payload2, String method) { 20 | this.srcId = srcId; 21 | this.dstId = dstId; 22 | this.sessionId = sessionId; 23 | this.subject = (byte)subject; 24 | this.cmd = cmd; 25 | this.payload = payload; 26 | this.context = context; 27 | this.userHandler = userHandler; 28 | this.isCb = isCb; 29 | this.payload2 = payload2; 30 | this.method = method; 31 | } 32 | 33 | protected void reset(int srcId, int dstId, int sessionId, 34 | int subject, int cmd, Object payload, Object context, Object userHandler, boolean isCb, 35 | Object payload2, String method){ 36 | this.srcId = srcId; 37 | this.dstId = dstId; 38 | this.sessionId = sessionId; 39 | this.subject = (byte)subject; 40 | this.cmd = cmd; 41 | this.payload = payload; 42 | this.context = context; 43 | this.userHandler = userHandler; 44 | this.isCb = isCb; 45 | this.payload2 = payload2; 46 | this.method = method; 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFUdpServerCfg.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | import fun.lib.actor.api.DFUdpDecoder; 4 | import io.netty.channel.EventLoopGroup; 5 | 6 | public final class DFUdpServerCfg { 7 | public final int port; 8 | public final int ioThreadNum; 9 | public final boolean isBroadcast; 10 | public final EventLoopGroup ioGroup; 11 | 12 | private int soRecvBuf = 1024*20; 13 | private int soSendBuf = 1024*20; 14 | 15 | private volatile DFUdpDecoder decoder = null; 16 | 17 | public DFUdpServerCfg(int port, int ioThreadNum, boolean isBroadcast) { 18 | this.port = port; 19 | ioThreadNum = Math.max(1, ioThreadNum); 20 | this.ioThreadNum = ioThreadNum; 21 | this.isBroadcast = isBroadcast; 22 | ioGroup = null; 23 | } 24 | public DFUdpServerCfg(int port, boolean isBroadcast, EventLoopGroup ioGroup){ 25 | this.port = port; 26 | this.ioGroup = ioGroup; 27 | this.isBroadcast = isBroadcast; 28 | this.ioThreadNum = 0; 29 | } 30 | 31 | public int getSoSendBuf(){ 32 | return soSendBuf; 33 | } 34 | public DFUdpServerCfg setSoSendBuf(int soSendBuf){ 35 | this.soSendBuf = soSendBuf; 36 | return this; 37 | } 38 | 39 | public int getSoRecvBuf(){ 40 | return soRecvBuf; 41 | } 42 | public DFUdpServerCfg setSoRecvBuf(int soRecvBuf){ 43 | this.soRecvBuf = soRecvBuf; 44 | return this; 45 | } 46 | 47 | public DFUdpDecoder getDecoder() { 48 | return decoder; 49 | } 50 | 51 | public DFUdpServerCfg setDecoder(DFUdpDecoder decoder) { 52 | this.decoder = decoder; 53 | return this; 54 | } 55 | 56 | } 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/kcp/KcpServer.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.kcp; 2 | 3 | import io.netty.channel.socket.DatagramPacket; 4 | 5 | public final class KcpServer { 6 | 7 | private final int id; 8 | private final int threadNum; 9 | private volatile KcpLoop[] arrLoop = null; 10 | private final KcpListener listener; 11 | private final KcpConfig kcpCfg; 12 | 13 | public KcpServer(int id, int threadNum, KcpListener listener, KcpConfig kcpCfg) { 14 | this.id = id; 15 | threadNum = Math.max(1, threadNum); 16 | this.threadNum = threadNum; 17 | this.listener = listener; 18 | this.kcpCfg = kcpCfg; 19 | } 20 | 21 | public int start(){ 22 | int ret = -1; 23 | do { 24 | if(arrLoop != null){ 25 | ret = 1; break; 26 | } 27 | //start loop thread 28 | arrLoop = new KcpLoop[this.threadNum]; 29 | for(int i=0; i-1 && idx entryClassz, Object entryParam, 10 | int entryScheduleUnit, int entryConsumeType 11 | * */ 12 | 13 | private String name = null; 14 | private Class classz = null; 15 | private Object param = null; 16 | private int scheduleMilli = 0; 17 | private int consumeType = DFActorDefine.CONSUME_AUTO; 18 | private boolean isBlock = false; 19 | 20 | private ActorProp(){ 21 | 22 | } 23 | //set 24 | public ActorProp name(String name){ 25 | this.name = name; 26 | return this; 27 | } 28 | public ActorProp classz(Class classz){ 29 | this.classz = classz; 30 | return this; 31 | } 32 | public ActorProp param(Object param){ 33 | this.param = param; 34 | return this; 35 | } 36 | public ActorProp scheduleMilli(int scheduleMilli){ 37 | this.scheduleMilli = scheduleMilli; 38 | return this; 39 | } 40 | public ActorProp consumeType(int consumeType){ 41 | this.consumeType = consumeType; 42 | return this; 43 | } 44 | public ActorProp blockActor(boolean isBlock){ 45 | this.isBlock = isBlock; 46 | return this; 47 | } 48 | 49 | //get 50 | public String getName(){ 51 | return name; 52 | } 53 | public Class getClassz(){ 54 | return classz; 55 | } 56 | public Object getParam(){ 57 | return param; 58 | } 59 | public int getScheduleMilli(){ 60 | return scheduleMilli; 61 | } 62 | public int getConsumeType(){ 63 | return consumeType; 64 | } 65 | public boolean isBlock(){ 66 | return isBlock; 67 | } 68 | //new 69 | public static ActorProp newProp(){ 70 | return new ActorProp(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/helper/ActorLog.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.helper; 2 | 3 | import com.funtag.util.log.DFLogFactory; 4 | import com.funtag.util.log.DFLogger; 5 | 6 | import fun.lib.actor.api.cb.CbActorReq; 7 | import fun.lib.actor.core.DFActor; 8 | import fun.lib.actor.core.DFActorDefine; 9 | 10 | public final class ActorLog extends DFActor{ 11 | 12 | private final DFLogger log = DFLogFactory.create(ActorLog.class); 13 | private final StringBuffer sb = new StringBuffer(); 14 | // 15 | protected ActorLog(Integer id, String name, Boolean isIoActor) { 16 | super(id, name, isIoActor); 17 | // TODO Auto-generated constructor stub 18 | } 19 | 20 | @Override 21 | public int onMessage(int cmd, Object payload, int srcId) { 22 | final ActorLogData data = (ActorLogData) payload; 23 | sb.setLength(0); 24 | final String str = sb.append(data.actorName).append("(").append(srcId).append(")") 25 | .append(": ").append(data.msg).toString(); 26 | switch(data.level){ 27 | case DFLogFactory.LEVEL_VERB: 28 | log.V(str); 29 | break; 30 | case DFLogFactory.LEVEL_DEBUG: 31 | log.D(str); 32 | break; 33 | case DFLogFactory.LEVEL_INFO: 34 | log.I(str); 35 | break; 36 | case DFLogFactory.LEVEL_WARN: 37 | log.W(str); 38 | break; 39 | case DFLogFactory.LEVEL_ERROR: 40 | log.E(str); 41 | break; 42 | case DFLogFactory.LEVEL_FATAL: 43 | log.F(str); 44 | break; 45 | } 46 | return DFActorDefine.MSG_AUTO_RELEASE; 47 | } 48 | 49 | @Override 50 | public void onStart(Object param) { 51 | // TODO Auto-generated method stub 52 | 53 | } 54 | 55 | @Override 56 | public void onSchedule(long dltMilli) { 57 | // TODO Auto-generated method stub 58 | 59 | } 60 | 61 | @Override 62 | public void onTimeout(int requestId) { 63 | // TODO Auto-generated method stub 64 | 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/CallHereBlock.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.api.cb.CallHereContext; 4 | import fun.lib.actor.api.cb.CbCallHereBlock; 5 | import fun.lib.actor.core.DFActor; 6 | import fun.lib.actor.core.DFActorManager; 7 | 8 | /** 9 | * 利用异步回调机制+框架提供的BlockActor,简化io操作代码,在业务actor中编写io操作代码 10 | * 根据此例,可改写MysqlTest.java, MongodbTest.java, RedisTest,java等例子, 11 | * 实现在业务actor里编写block操作代码,增加代码可读性可维护性 12 | * @author lostsky 13 | * 14 | */ 15 | public final class CallHereBlock { 16 | 17 | public static void main(String[] args) { 18 | DFActorManager.get().start(EntryActor.class); 19 | } 20 | 21 | private static class EntryActor extends DFActor{ 22 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 23 | super(id, name, isBlockActor); 24 | // TODO Auto-generated constructor stub 25 | } 26 | @Override 27 | public void onStart(Object param) { 28 | timer.timeout(1000, 0); 29 | } 30 | private int count = 0; 31 | @Override 32 | public void onTimeout(int requestId) { 33 | final int userId = 168; //模拟业务线程要处理一个user信息 34 | sys.callHereBlock(userId, 1001, "reqData_"+(++count), new CbCallHereBlock() { 35 | @Override 36 | public void inBlockActor(int cmd, Object payload, CallHereContext ctx) { 37 | //由框架block线程回调,此处禁止操作业务actor中的数据,会引发数据安全问题 38 | ctx.getLog().info("blockActorRecvData: cmd="+cmd+", payload="+payload+", userId="+userId+", curThread="+Thread.currentThread().getName()); 39 | //执行数据库io等操作 40 | //向业务actor返回结果 41 | ctx.callback(1002, "rspData: ori="+payload); 42 | } 43 | @Override 44 | public void onCallback(int cmd, Object payload) { 45 | //业务actor收到数据库操作结果 46 | log.info("recvBlockRsp, cmd="+cmd+", payload="+payload+", curThread="+Thread.currentThread().getName()); 47 | } 48 | }); 49 | // 50 | timer.timeout(1000, 0); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/HttpsServer.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | import fun.lib.actor.api.cb.CbHttpServer; 3 | import fun.lib.actor.api.http.DFHttpSvrReq; 4 | import fun.lib.actor.core.DFActor; 5 | import fun.lib.actor.core.DFActorDefine; 6 | import fun.lib.actor.core.DFActorManager; 7 | import fun.lib.actor.po.DFTcpServerCfg; 8 | import fun.lib.actor.po.DFSSLConfig; 9 | /** 10 | * HttpsServer示例 11 | * @author lostsky 12 | * 13 | */ 14 | public final class HttpsServer { 15 | 16 | public static void main(String[] args) { 17 | DFActorManager.get() 18 | .start(EntryActor.class); //启动入口actor,开始消息循环 19 | } 20 | 21 | private static class EntryActor extends DFActor{ 22 | @Override 23 | public void onStart(Object param) { 24 | //测试证书&私钥生成命令: openssl req -x509 -newkey rsa:2048 -nodes -days 365 -keyout private.pem -out cert.crt 25 | //证书文件路径 26 | String certPath = "/var/dfactor/cert.crt"; 27 | //私钥文件路径 28 | String pemPath = "/var/dfactor/private.pem"; 29 | 30 | net.httpSvr(DFTcpServerCfg.newCfg(443) 31 | .setSslConfig(DFSSLConfig.newCfg() 32 | .certPath(certPath) 33 | .pemPath(pemPath)), 34 | new CbHttpServer() { 35 | @Override 36 | public int onHttpRequest(Object msg) { 37 | DFHttpSvrReq req = (DFHttpSvrReq) msg; 38 | //response 39 | req.response("echo from ssl server, uri="+req.getUri()) 40 | .send(); 41 | return MSG_AUTO_RELEASE; 42 | } 43 | @Override 44 | public void onListenResult(boolean isSucc, String errMsg) { 45 | log.info("listen result: isSucc="+isSucc+", err="+errMsg); 46 | if(!isSucc){ 47 | sys.shutdown(); 48 | } 49 | }}); 50 | //start http server 51 | } 52 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 53 | super(id, name, isBlockActor); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/msg/proto/DMCluster.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "fun.lib.actor.msg"; 4 | option java_outer_classname = "DMCluster"; 5 | 6 | message NewNodeAsk{ 7 | string cluster_name = 1; 8 | string node_name = 2; 9 | string node_type = 3; 10 | string unique_id = 4; 11 | uint64 tm_start = 5; 12 | // 13 | string salt = 6; 14 | string sign = 7; 15 | // 16 | string host = 8; 17 | int32 port = 9; 18 | int32 udp_port = 10; 19 | int32 ask_count = 11; 20 | } 21 | 22 | message NewNodeRsp{ 23 | string cluster_name = 1; 24 | string unique_id = 2; 25 | int32 result = 3; 26 | string errMsg = 4; 27 | // 28 | string salt = 5; 29 | string sign = 6; 30 | // 31 | int32 ask_count = 7; 32 | } 33 | 34 | message NewNodeSucc{ 35 | string cluster_name = 1; 36 | string unique_id = 2; 37 | string node_name = 3; 38 | string node_type = 4; 39 | string host = 5; 40 | int32 port = 6; 41 | int32 udp_port = 7; 42 | // 43 | string salt = 8; 44 | string sign = 9; 45 | } 46 | 47 | message AskOtherConn{ 48 | string cluster_name = 1; 49 | string unique_id = 2; 50 | string node_name = 3; 51 | string node_type = 4; 52 | string host = 5; 53 | int32 port = 6; 54 | // 55 | string salt = 7; 56 | string sign = 8; 57 | } 58 | 59 | 60 | 61 | message NewNodeLogin{ 62 | string cluster_name = 1; 63 | string unique_id = 2; 64 | string node_name = 3; 65 | string node_type = 4; 66 | string host = 5; 67 | // 68 | string salt = 6; 69 | string sign = 7; 70 | } 71 | 72 | 73 | message UserMsgHead{ 74 | string src_node = 1; 75 | string src_type = 2; 76 | string src_actor = 3; 77 | string dst_actor = 4; 78 | string dst_method = 5; 79 | int32 session_id = 6; 80 | } 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFActorEvent.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class DFActorEvent { 4 | 5 | private final int what; 6 | private final String msg; 7 | 8 | private int extInt1 = 0; 9 | private String extString1 = null; 10 | private int extInt2 = 0; 11 | private String extString2 = null; 12 | 13 | private Object extObj1; 14 | private Object extObj2; 15 | 16 | private Object userHandler; 17 | 18 | public DFActorEvent(int what) { 19 | this.what = what; 20 | msg = null; 21 | } 22 | public DFActorEvent(int what, String msg) { 23 | this.what = what; 24 | this.msg = msg; 25 | } 26 | public DFActorEvent setExtInt1(int extInt1){ 27 | this.extInt1 = extInt1; 28 | return this; 29 | } 30 | public DFActorEvent setExtInt2(int extInt2){ 31 | this.extInt2 = extInt2; 32 | return this; 33 | } 34 | public DFActorEvent setExtString1(String extString1){ 35 | this.extString1 = extString1; 36 | return this; 37 | } 38 | public DFActorEvent setExtString2(String extString2){ 39 | this.extString2 = extString2; 40 | return this; 41 | } 42 | public DFActorEvent setExtObj1(Object extObj1){ 43 | this.extObj1 = extObj1; 44 | return this; 45 | } 46 | public DFActorEvent setExtObj2(Object extObj2){ 47 | this.extObj2 = extObj2; 48 | return this; 49 | } 50 | 51 | public int getWhat() { 52 | return what; 53 | } 54 | public String getMsg() { 55 | return msg; 56 | } 57 | public int getExtInt1() { 58 | return extInt1; 59 | } 60 | public String getExtString1() { 61 | return extString1; 62 | } 63 | public int getExtInt2() { 64 | return extInt2; 65 | } 66 | public String getExtString2() { 67 | return extString2; 68 | } 69 | public Object getExtObj1() { 70 | return extObj1; 71 | } 72 | public Object getExtObj2() { 73 | return extObj2; 74 | } 75 | public Object getUserHandler() { 76 | return userHandler; 77 | } 78 | public void setUserHandler(Object userHandler) { 79 | this.userHandler = userHandler; 80 | } 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFRedisCfg.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class DFRedisCfg { 4 | 5 | private String host = null; 6 | private int port = 0; 7 | private String auth = null; 8 | 9 | private int maxTotal = 10; 10 | private int maxIdle = 4; 11 | private int minIdle = 2; 12 | private int connTimeoutMilli = 5000; 13 | private int borrowTimeoutMilli = 10000; 14 | public final String strId; 15 | 16 | private DFRedisCfg(String host, int port, String auth) { 17 | this.host = host; 18 | this.port = port; 19 | this.auth = auth; 20 | // 21 | this.strId = host+":"+port+"_"+auth; 22 | } 23 | 24 | public DFRedisCfg setMaxTotal(int maxTotal){ 25 | this.maxTotal = Math.max(1, maxTotal); 26 | return this; 27 | } 28 | public DFRedisCfg setMaxIdle(int maxIdle){ 29 | this.maxIdle = Math.max(1, maxIdle); 30 | return this; 31 | } 32 | public DFRedisCfg setMinIdle(int minIdle){ 33 | this.minIdle = Math.max(1, minIdle); 34 | return this; 35 | } 36 | public DFRedisCfg setConnTimeoutMilli(int timeoutMilli){ 37 | this.connTimeoutMilli = Math.max(100, timeoutMilli); 38 | return this; 39 | } 40 | public DFRedisCfg setBorrowTimeoutMilli(int timeoutMilli){ 41 | this.borrowTimeoutMilli = Math.max(100, timeoutMilli); 42 | return this; 43 | } 44 | 45 | 46 | public String getHost() { 47 | return host; 48 | } 49 | 50 | public int getPort() { 51 | return port; 52 | } 53 | 54 | public String getAuth() { 55 | return auth; 56 | } 57 | 58 | public int getMaxTotal() { 59 | return maxTotal; 60 | } 61 | 62 | public int getMaxIdle() { 63 | return maxIdle; 64 | } 65 | 66 | public int getMinIdle() { 67 | return minIdle; 68 | } 69 | 70 | public int getConnTimeoutMilli() { 71 | return connTimeoutMilli; 72 | } 73 | 74 | public int getBorrowTimeoutMilli() { 75 | return borrowTimeoutMilli; 76 | } 77 | 78 | 79 | public static DFRedisCfg newCfg(String host, int port, String auth){ 80 | return new DFRedisCfg(host, port, auth); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFVirtualHostManager.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.LinkedList; 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | import java.util.concurrent.locks.ReentrantReadWriteLock; 9 | import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; 10 | import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; 11 | 12 | public final class DFVirtualHostManager { 13 | 14 | private final static DFVirtualHostManager instance = new DFVirtualHostManager(); 15 | 16 | private DFVirtualHostManager() { 17 | // TODO Auto-generated constructor stub 18 | } 19 | 20 | public static DFVirtualHostManager get(){ 21 | return instance; 22 | } 23 | 24 | private final Map _mapHost = new ConcurrentHashMap<>(); 25 | private final ReentrantReadWriteLock _lock = new ReentrantReadWriteLock(); 26 | private final ReadLock _lockRead = _lock.readLock(); 27 | private final WriteLock _lockWrite = _lock.writeLock(); 28 | 29 | protected void addHost(IVirtualHost host){ 30 | if(_hasShutdown){ 31 | return ; 32 | } 33 | // _lockWrite.lock(); 34 | // try{ 35 | _mapHost.put(host.getPort(), host); 36 | // }finally{ 37 | // _lockWrite.unlock(); 38 | // } 39 | } 40 | 41 | protected IVirtualHost getHost(int port){ 42 | IVirtualHost host = null; 43 | // _lockRead.lock(); 44 | // try{ 45 | host = _mapHost.get(port); 46 | // }finally{ 47 | // _lockRead.unlock(); 48 | // } 49 | return host; 50 | } 51 | 52 | private boolean _hasShutdown = false; 53 | protected void shutdown(){ 54 | if(_hasShutdown){ 55 | return ; 56 | } 57 | _hasShutdown = true; 58 | LinkedList lsHost = new LinkedList<>(); 59 | _lockWrite.lock(); 60 | try{ 61 | Iterator it = _mapHost.values().iterator(); 62 | while(it.hasNext()){ 63 | lsHost.offer(it.next()); 64 | } 65 | _mapHost.clear(); 66 | }finally{ 67 | _lockWrite.unlock(); 68 | } 69 | for(IVirtualHost host : lsHost){ 70 | host.close(); 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFDbCfg.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | public final class DFDbCfg { 4 | 5 | private final String url; 6 | private final String user; 7 | private final String pwd; 8 | private int initSize = 4; 9 | private int maxActive = 10; 10 | private int maxWait = 200; 11 | private int maxIdle = 4; 12 | private int minIdle = 2; 13 | public final String strId; 14 | 15 | private DFDbCfg(String host, int port, String dbName, String user, String pwd) { 16 | //jdbc:mysql://host:port/dbName?useUnicode=true&characterEncoding=UTF-8 17 | this.url = makeUrl(host, port, dbName); 18 | this.user = user; 19 | this.pwd = pwd; 20 | this.strId = host+":"+port+"*?"+dbName+"*?"+user+"*?"+pwd; 21 | } 22 | 23 | //set 24 | public DFDbCfg setInitSize(int initSize){ 25 | this.initSize = initSize; 26 | return this; 27 | } 28 | public DFDbCfg setMaxActive(int maxActive){ 29 | this.maxActive = maxActive; 30 | return this; 31 | } 32 | public DFDbCfg setMaxWait(int maxWait){ 33 | this.maxWait = maxWait; 34 | return this; 35 | } 36 | public DFDbCfg setMaxIdle(int maxIdle){ 37 | this.maxIdle = maxIdle; 38 | return this; 39 | } 40 | public DFDbCfg setMinIdle(int minIdle){ 41 | this.minIdle = minIdle; 42 | return this; 43 | } 44 | 45 | 46 | //get 47 | public String getUrl() { 48 | return url; 49 | } 50 | public String getUser() { 51 | return user; 52 | } 53 | public String getPwd() { 54 | return pwd; 55 | } 56 | public int getInitSize() { 57 | return initSize; 58 | } 59 | public int getMaxActive() { 60 | return maxActive; 61 | } 62 | public int getMaxWait() { 63 | return maxWait; 64 | } 65 | public int getMaxIdle() { 66 | return maxIdle; 67 | } 68 | public int getMinIdle() { 69 | return minIdle; 70 | } 71 | 72 | public static DFDbCfg newCfg(String host, int port, String dbName, String user, String pwd){ 73 | return new DFDbCfg(host, port, dbName, user, pwd); 74 | } 75 | 76 | 77 | public static String makeUrl(String host, int port, String dbName){ 78 | return "jdbc:mysql://"+host+":"+port+"/"+dbName+"?useUnicode=true&characterEncoding=UTF-8"; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/net/DFIpUtil.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.net; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | public final class DFIpUtil { 6 | 7 | private static Pattern ptipv4 = Pattern.compile("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$"); 8 | 9 | public static boolean isIPv4(String ip){ 10 | return ptipv4.matcher(ip).matches(); 11 | } 12 | 13 | public static long ipToNumber(String ip){ 14 | try{ 15 | String[] arr = ip.trim().split("\\."); 16 | long num = 0; 17 | num = num|Integer.parseInt(arr[0]); 18 | num = (num<<8)|Integer.parseInt(arr[1]); 19 | num = (num<<8)|Integer.parseInt(arr[2]); 20 | return (num<<8)|Integer.parseInt(arr[3]); 21 | }catch(Throwable e){ 22 | throw e; 23 | } 24 | } 25 | public static String numberToIp(long ipNum){ 26 | short[] arr = new short[4]; 27 | for(int i=3; i>-1; --i){ 28 | arr[i] = (short) (ipNum&0xFF); 29 | ipNum = ipNum>>8; 30 | } 31 | StringBuilder sb = new StringBuilder(15); //xxx.xxx.xxx.xxx 32 | sb.append(arr[0]) 33 | .append('.').append(arr[1]) 34 | .append('.').append(arr[2]) 35 | .append('.').append(arr[3]); 36 | return sb.toString(); 37 | } 38 | 39 | public static boolean isLanIP(String ip){ 40 | long n = ipToNumber(ip); 41 | return isLanIP(n); 42 | } 43 | 44 | public static boolean isLanIP(long ip){ 45 | if( (ip>=LAN_1_BEGIN&&ip<=LAN_1_END) 46 | || (ip>=LAN_2_BEGIN&&ip<=LAN_2_END) 47 | || (ip>=LAN_3_BEGIN&&ip<=LAN_3_END)){ 48 | return true; 49 | } 50 | return false; 51 | } 52 | 53 | private static final long LAN_1_BEGIN = ipToNumber("10.0.0.0"); 54 | private static final long LAN_1_END = ipToNumber("10.255.255.255"); 55 | private static final long LAN_2_BEGIN = ipToNumber("172.16.0.0"); 56 | private static final long LAN_2_END = ipToNumber("172.31.255.255"); 57 | private static final long LAN_3_BEGIN = ipToNumber("192.168.0.0"); 58 | private static final long LAN_3_END = ipToNumber("192.168.255.255"); 59 | /*10.0.0.0/8:10.0.0.0~10.255.255.255 60 |   172.16.0.0/12:172.16.0.0~172.31.255.255 61 |   192.168.0.0/16:192.168.0.0~192.168.255.255 62 | */ 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFDbManager.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | import com.mongodb.client.MongoDatabase; 7 | 8 | import fun.lib.actor.po.DFDbCfg; 9 | import fun.lib.actor.po.DFMongoCfg; 10 | import fun.lib.actor.po.DFRedisCfg; 11 | import redis.clients.jedis.Jedis; 12 | 13 | public final class DFDbManager { 14 | 15 | private static final DFDbManager instance = new DFDbManager(); 16 | 17 | private final DFRedisManager redisMgr; 18 | private final DFMysqlManager mysqlMgr; 19 | private final DFMongoManager mongoMgr; 20 | 21 | private DFDbManager(){ 22 | redisMgr = new DFRedisManager(); 23 | mysqlMgr = new DFMysqlManager(); 24 | mongoMgr = new DFMongoManager(); 25 | } 26 | protected static DFDbManager get(){ 27 | return instance; 28 | } 29 | 30 | protected void closeAllPool(){ 31 | this.closeAllRedisPool(); 32 | this.closeAllDbPool(); 33 | this.closeAllMongoPool(); 34 | } 35 | 36 | //mongodb 37 | protected int initMongoPool(DFMongoCfg cfg){ 38 | return mongoMgr.initPool(cfg); 39 | } 40 | protected MongoDatabase getMongoDatabase(int id, String dbName){ 41 | return mongoMgr.getDatabase(id, dbName); 42 | } 43 | protected void closeMongoPool(int id){ 44 | mongoMgr.closePool(id); 45 | } 46 | protected void closeAllMongoPool(){ 47 | mongoMgr.closeAllPool(); 48 | } 49 | 50 | //db(mysql) 51 | protected int initDbPool(DFDbCfg cfg) throws Throwable{ 52 | return mysqlMgr.initPool(cfg); 53 | } 54 | protected Connection getDbConn(int id) throws SQLException{ 55 | return mysqlMgr.getConn(id); 56 | } 57 | protected void closeDbPool(int id){ 58 | mysqlMgr.closePool(id); 59 | } 60 | protected void closeAllDbPool(){ 61 | mysqlMgr.closeAllPool(); 62 | } 63 | 64 | //redis 65 | protected int initRedisPool(DFRedisCfg cfg) throws Throwable{ 66 | return redisMgr.initPool(cfg); 67 | } 68 | protected Jedis getRedisConn(int id){ 69 | return redisMgr.getConn(id); 70 | } 71 | protected void closeRedisPool(int id){ 72 | redisMgr.closePool(id); 73 | } 74 | protected void closeAllRedisPool(){ 75 | redisMgr.closeAllPool(); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/RpcLocal.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.api.cb.Cb; 4 | import fun.lib.actor.api.cb.RpcContext; 5 | import fun.lib.actor.api.cb.RpcFuture; 6 | import fun.lib.actor.core.DFActor; 7 | import fun.lib.actor.core.DFActorManager; 8 | /** 9 | * 本地rpc示例,直接调用本进程内actor的自定义方法 10 | * @author lostsky 11 | * 12 | */ 13 | public final class RpcLocal { 14 | 15 | public static void main(String[] args) { 16 | final DFActorManager mgr = DFActorManager.get(); 17 | //启动入口actor,开始消息循环 18 | mgr.start(AskActor.class); 19 | } 20 | 21 | 22 | private static class AskActor extends DFActor{ 23 | public AskActor(Integer id, String name, Boolean isBlockActor) { 24 | super(id, name, isBlockActor); 25 | // TODO Auto-generated constructor stub 26 | } 27 | private int answerId = 0; 28 | @Override 29 | public void onStart(Object param) { 30 | //创建被调用actor 31 | answerId = sys.createActor(AnswerActor.class); 32 | //启动定时器 33 | timer.timeout(1000, 0); 34 | } 35 | @Override 36 | public void onTimeout(int requestId) { 37 | RpcFuture future = sys.rpc(answerId, "doMath", 168, "square"); 38 | if(future.isSendSucc()){ //发送消息成功 可选择添加回调 39 | future.addListener(new Cb() { 40 | @Override 41 | public int onCallback(int cmd, Object payload) { 42 | log.info("recv answer: "+ payload); 43 | return 0; 44 | } 45 | @Override 46 | public int onFailed(int code) { //失败时的回调, 见 RpcError.java 47 | log.error("rcpCall failed, code="+code); 48 | return 0; 49 | } 50 | }, 5000); //设置超时5000毫秒 51 | } 52 | timer.timeout(1000, 0); 53 | } 54 | } 55 | 56 | private static class AnswerActor extends DFActor{ 57 | public AnswerActor(Integer id, String name, Boolean isBlockActor) { 58 | super(id, name, isBlockActor); 59 | } 60 | //被调用方法需满足如下参数列表: public (int,Object) 61 | public void doMath(int cmd, Object payload){ 62 | log.info("recv ask: cmd="+cmd+", payload="+payload); 63 | //响应请求 64 | sys.ret(0, "square("+cmd+")="+cmd*cmd+", now="+System.currentTimeMillis()); 65 | // ctx.response(0, "square("+cmd+")="+cmd*cmd+", now="+System.currentTimeMillis()); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/WebsocketServer.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.api.DFTcpChannel; 4 | import fun.lib.actor.core.DFActor; 5 | import fun.lib.actor.core.DFActorDefine; 6 | import fun.lib.actor.core.DFActorManager; 7 | import fun.lib.actor.po.DFTcpServerCfg; 8 | 9 | /** 10 | * websocket服务示例 11 | * @author lostsky 12 | * 13 | */ 14 | public final class WebsocketServer { 15 | 16 | public static void main(String[] args){ 17 | final DFActorManager mgr = DFActorManager.get(); 18 | //启动入口actor,开始消息循环 19 | mgr.start(Server.class); 20 | } 21 | 22 | private static class Server extends DFActor{ 23 | public Server(Integer id, String name, Boolean isBlockActor) { 24 | super(id, name, isBlockActor); 25 | // TODO Auto-generated constructor stub 26 | } 27 | private final int serverPort = 10001; 28 | @Override 29 | public void onStart(Object param) { 30 | DFTcpServerCfg cfg = new DFTcpServerCfg(serverPort, 1, 1) 31 | .setTcpProtocol(TCP_PROTOCOL_WEBSOCKET) 32 | .setWsUri("test"); //如 ws://127.0.0.1:10001/test 33 | log.info("onStart, ready to listen on port "+serverPort); 34 | //启动端口监听 35 | net.tcpSvr(cfg); 36 | } 37 | @Override 38 | public void onTcpConnOpen(int requestId, DFTcpChannel channel) { 39 | final int channelId = channel.getChannelId(); 40 | log.info("onTcpConnOpen, remote="+channel.getRemoteHost()+":"+channel.getRemotePort() 41 | +", channelId="+channelId); 42 | } 43 | @Override 44 | public void onTcpConnClose(int requestId, DFTcpChannel channel) { 45 | final int channelId = channel.getChannelId(); 46 | log.info("onTcpConnClose, remote="+channel.getRemoteHost()+":"+channel.getRemotePort() 47 | +", channelId="+channelId); 48 | } 49 | @Override 50 | public int onTcpRecvMsg(int requestId, DFTcpChannel channel, Object m) { 51 | String msg = (String) m; 52 | //response 53 | channel.write("echo from server: "+msg); 54 | //消息对象交由框架释放 55 | return MSG_AUTO_RELEASE; 56 | } 57 | @Override 58 | public void onTcpServerListenResult(int requestId, boolean isSucc, String errMsg) { 59 | log.info("onTcpServerListenResult, port="+requestId+", succ="+isSucc+", err="+errMsg); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/deprecated/ActorUdpTest.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.deprecated; 2 | 3 | import java.nio.charset.Charset; 4 | import java.util.ArrayList; 5 | 6 | import fun.lib.actor.api.DFUdpChannel; 7 | import fun.lib.actor.api.cb.CbActorReq; 8 | import fun.lib.actor.api.DFActorUdpDispatcher; 9 | import fun.lib.actor.core.DFActor; 10 | import fun.lib.actor.core.DFActorDefine; 11 | import fun.lib.actor.core.DFActorManager; 12 | import fun.lib.actor.define.DFActorErrorCode; 13 | import fun.lib.actor.po.ActorProp; 14 | import fun.lib.actor.po.DFActorEvent; 15 | import fun.lib.actor.po.DFActorManagerConfig; 16 | import fun.lib.actor.po.DFUdpServerCfg; 17 | import io.netty.buffer.ByteBuf; 18 | import io.netty.buffer.PooledByteBufAllocator; 19 | import io.netty.channel.socket.DatagramPacket; 20 | 21 | public final class ActorUdpTest extends DFActor implements DFActorUdpDispatcher{ 22 | 23 | protected ActorUdpTest(Integer id, String name, Boolean isIoActor) { 24 | super(id, name, isIoActor); 25 | // TODO Auto-generated constructor stub 26 | } 27 | 28 | private DFUdpChannel channel = null; 29 | @Override 30 | public int onMessage(int cmd, Object payload, int srcId) { 31 | 32 | return DFActorDefine.MSG_AUTO_RELEASE; 33 | } 34 | 35 | private final int listenPort = 13500; 36 | @Override 37 | public void onStart(Object param) { 38 | log.debug("onStart"); 39 | 40 | _initKcpListen(); 41 | 42 | sys.timeout(100, 1); 43 | } 44 | 45 | private void _initKcpListen(){ 46 | final DFUdpServerCfg cfg = new DFUdpServerCfg(listenPort, 1, false); 47 | net.udpSvr(cfg, this, 1); 48 | } 49 | 50 | @Override 51 | public void onTimeout(int requestId) { 52 | 53 | // doUdpListenClose(listenPort); 54 | } 55 | 56 | @Override 57 | public int onQueryMsgActorId(Object msg) { 58 | return id; 59 | } 60 | 61 | 62 | public static void main(String[] args) { 63 | // 64 | final DFActorManager mgr = DFActorManager.get(); 65 | DFActorManagerConfig cfg = new DFActorManagerConfig() 66 | .setLogicWorkerThreadNum(4) 67 | .setBlockWorkerThreadNum(0); 68 | 69 | mgr.start(cfg, ActorProp.newProp() 70 | .name("actor_udp_test") 71 | .classz(ActorUdpTest.class) 72 | .param(1000+"")); 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorDefine.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | public final class DFActorDefine { 4 | 5 | public static final int VERSION = 100000; 6 | 7 | public static final int CONSUME_AUTO = 0; 8 | public static final int CONSUME_SINGLE = 1; 9 | // public static final int CONSUME_QUARTER = 2; 10 | public static final int CONSUME_HALF = 2; 11 | public static final int CONSUME_ALL = 3; 12 | 13 | // 14 | public static final int SUBJECT_START = 1; 15 | public static final int SUBJECT_TIMER = 2; 16 | public static final int SUBJECT_SCHEDULE = 3; 17 | public static final int SUBJECT_NET = 4; 18 | public static final int SUBJECT_USER = 5; 19 | public static final int SUBJECT_CLUSTER = 6; 20 | public static final int SUBJECT_RPC = 7; 21 | public static final int SUBJECT_CB_FAILED = 8; 22 | public static final int SUBJECT_NODE_EVENT = 9; 23 | 24 | // 25 | protected static final int NET_TCP_LISTEN_RESULT = 1; 26 | protected static final int NET_TCP_LISTEN_CLOSED = 2; 27 | protected static final int NET_TCP_CONNECT_RESULT = 3; 28 | protected static final int NET_TCP_CONNECT_OPEN = 4; 29 | public static final int NET_TCP_CONNECT_CLOSE = 5; 30 | public static final int NET_TCP_MESSAGE = 6; 31 | public static final int NET_TCP_MESSAGE_TEXT = 7; 32 | public static final int NET_TCP_MESSAGE_CUSTOM = 8; 33 | 34 | protected static final int NET_UDP_LISTEN_RESULT = 9; 35 | protected static final int NET_UDP_LISTEN_CLOSED = 10; 36 | protected static final int NET_UDP_MESSAGE = 11; 37 | 38 | public static final int NET_KCP_MESSAGE = 12; 39 | public static final int NET_KCP_ACTIVE = 13; 40 | public static final int NET_KCP_INACTIVE = 14; 41 | 42 | // 43 | public static final int MSG_AUTO_RELEASE = 0; 44 | public static final int MSG_MANUAL_RELEASE = -2409; 45 | 46 | // 47 | public static final int TCP_DECODE_LENGTH = 1; 48 | public static final int TCP_DECODE_RAW = 2; 49 | public static final int TCP_DECODE_WEBSOCKET = 3; 50 | public static final int TCP_DECODE_HTTP = 4; 51 | 52 | // 53 | protected static final String ACTOR_NAME_LOG = "SYSTEM_LOG_lostsky"; 54 | protected static final String ACTOR_NAME_DEF_PFX = "DFActorDef_"; 55 | protected static final int ACTOR_ID_LOG = 1; 56 | // 57 | public static final int ACTOR_ID_APP_BEGIN = 1000; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/BlockActor.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.api.cb.CbActorReq; 4 | import fun.lib.actor.core.DFActor; 5 | import fun.lib.actor.core.DFActorDefine; 6 | import fun.lib.actor.core.DFActorManager; 7 | import fun.lib.actor.po.ActorProp; 8 | import fun.lib.actor.po.DFActorManagerConfig; 9 | 10 | /** 11 | * block类型actor示例 12 | * @author lostsky 13 | * 14 | */ 15 | public final class BlockActor { 16 | 17 | public static void main(String[] args) { 18 | final DFActorManager mgr = DFActorManager.get(); 19 | //启动配置参数 20 | DFActorManagerConfig cfg = new DFActorManagerConfig() 21 | .setBlockWorkerThreadNum(1); //设置block线程数量 22 | //启动入口actor,开始消息循环 23 | mgr.start(cfg, ActorProp.newProp() 24 | .name("LogicActor") 25 | .classz(LogicActor.class) 26 | .scheduleMilli(1000)); //开启schedule,周期1000ms 27 | } 28 | //逻辑actor 29 | private static class LogicActor extends DFActor{ 30 | public LogicActor(Integer id, String name, Boolean isBlockActor) { 31 | super(id, name, isBlockActor); 32 | // TODO Auto-generated constructor stub 33 | } 34 | @Override 35 | public void onStart(Object param) { 36 | log.info("LogicActor onStart"); 37 | //create block actor 38 | sys.createActor(ActorProp.newProp() 39 | .name("DbActor") 40 | .classz(DbActor.class) 41 | .blockActor(true)); 42 | } 43 | @Override 44 | public void onSchedule(long dltMilli) { 45 | log.info("LogicActor send io task, curThread="+Thread.currentThread().getName()); 46 | //send io task 47 | sys.to("DbActor", 1001, new Integer(1999)); 48 | } 49 | } 50 | 51 | //block actor 52 | private static class DbActor extends DFActor{ 53 | public DbActor(Integer id, String name, Boolean isBlockActor) { 54 | super(id, name, isBlockActor); 55 | // TODO Auto-generated constructor stub 56 | } 57 | @Override 58 | public void onStart(Object param) { 59 | log.info("BlockActor onStart"); 60 | } 61 | @Override 62 | public int onMessage(int cmd, Object payload, int srcId) { 63 | if(cmd == 1001){ //io操作 比如数据库操作 64 | int param = (Integer)payload; 65 | // do io 66 | log.info("do io work! param="+param+", curThread="+Thread.currentThread().getName()); 67 | } 68 | return MSG_AUTO_RELEASE; 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFJsHttpSvrReq.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.util.Iterator; 4 | import java.util.Map.Entry; 5 | 6 | import fun.lib.actor.api.http.DFHttpSvrReq; 7 | import fun.lib.actor.api.http.DFHttpSvrRsp; 8 | import io.netty.buffer.ByteBuf; 9 | import io.netty.handler.codec.http.HttpHeaderNames; 10 | 11 | public final class DFJsHttpSvrReq implements IScriptHttpSvrReq{ 12 | 13 | private final DFHttpSvrReq req; 14 | private DFHttpSvrRsp rsp = null; 15 | private Object dataWrap = null; 16 | 17 | public DFJsHttpSvrReq(DFHttpSvrReq req) { 18 | this.req = req; 19 | } 20 | @Override 21 | public String getMethod() { 22 | return req.getMethod().name(); 23 | } 24 | @Override 25 | public String getUri() { 26 | return req.getUri(); 27 | } 28 | @Override 29 | public String getContentType() { 30 | return req.getContentType(); 31 | } 32 | @Override 33 | public int getContentLength() { 34 | return req.getContentLength(); 35 | } 36 | @Override 37 | public boolean isIsStr() { 38 | return req.contentIsStr(); 39 | } 40 | 41 | @Override 42 | public Object getContent() { 43 | if(dataWrap != null){ 44 | return dataWrap; 45 | } 46 | dataWrap = req.getApplicationData(); 47 | if(dataWrap == null){ //no app data 48 | return null; 49 | } 50 | if(dataWrap instanceof ByteBuf){ 51 | dataWrap = DFJsBuffer.newBuffer((ByteBuf)dataWrap); 52 | } 53 | return dataWrap; 54 | } 55 | @Override 56 | public String header(String key) { 57 | return req.getHeaderValue(key); 58 | } 59 | @Override 60 | public String getUserAgent() { 61 | return req.getHeaderValue(HttpHeaderNames.USER_AGENT.toString()); 62 | } 63 | 64 | 65 | @Override 66 | public DFHttpSvrRsp response(Object data) { 67 | if(rsp == null){ 68 | if(data instanceof Integer){ //status code 69 | rsp = req.response((Integer)data); 70 | }else if(data instanceof String){ 71 | rsp = req.response((String)data); 72 | }else if(data instanceof IScriptBuffer){ 73 | ByteBuf bufOut = ((DFJsBuffer)data).getBuf(); 74 | rsp = req.response(bufOut); 75 | } 76 | } 77 | return rsp; 78 | } 79 | @Override 80 | public Iterator> getFieldIterator() { 81 | return req.getQueryDataIterator(); 82 | } 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFHttpCliRspWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.util.Iterator; 4 | import java.util.Map.Entry; 5 | 6 | import fun.lib.actor.api.http.DFHttpCliRsp; 7 | import io.netty.buffer.ByteBuf; 8 | import io.netty.handler.codec.http.HttpHeaders; 9 | 10 | public final class DFHttpCliRspWrap implements DFHttpCliRsp{ 11 | 12 | private final int statusCode; 13 | private final HttpHeaders headers; 14 | private final ByteBuf dataBuf; 15 | private final IScriptBuffer dataBufScript; 16 | private final String dataStr; 17 | private final String contentType; 18 | private final int contentLen; 19 | private final boolean isBinary; 20 | 21 | public DFHttpCliRspWrap(int statusCode, HttpHeaders headers, String contentType, int contentLen, ByteBuf dataBuf, String dataStr) { 22 | this.statusCode = statusCode; 23 | this.headers = headers; 24 | this.dataBuf = dataBuf; 25 | this.dataStr = dataStr; 26 | this.contentType = contentType; 27 | this.contentLen = contentLen; 28 | if(this.dataBuf != null){ 29 | isBinary = true; 30 | dataBufScript = DFJsBuffer.newBuffer(this.dataBuf); 31 | }else{ 32 | isBinary = false; 33 | dataBufScript = null; 34 | } 35 | } 36 | 37 | @Override 38 | public boolean isBinary(){ 39 | return isBinary; 40 | } 41 | @Override 42 | public int getContentLength(){ 43 | return contentLen; 44 | } 45 | @Override 46 | public ByteBuf getContentBuf(){ 47 | return dataBuf; 48 | } 49 | @Override 50 | public String getContentStr(){ 51 | return dataStr; 52 | } 53 | 54 | @Override 55 | public Object getContent() { 56 | if(!isBinary){ //string 57 | return dataStr; 58 | }else{ //buf 59 | return dataBufScript; 60 | } 61 | } 62 | 63 | @Override 64 | public String getContentType(){ 65 | return contentType; 66 | } 67 | @Override 68 | public Iterator> getHeaderIterator(){ 69 | if(headers != null){ 70 | return headers.iteratorAsString(); 71 | } 72 | return null; 73 | } 74 | @Override 75 | public String header(String name){ 76 | if(headers != null){ 77 | return headers.get(name); 78 | } 79 | return null; 80 | } 81 | @Override 82 | public int getStatus() { 83 | return statusCode; 84 | } 85 | @Override 86 | public void release() { 87 | if(dataBuf != null){ 88 | dataBuf.release(dataBuf.refCnt()); 89 | } 90 | } 91 | 92 | @Override 93 | public boolean isIsStr() { 94 | return !isBinary; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/MongodbTest.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import com.mongodb.client.MongoDatabase; 4 | 5 | import fun.lib.actor.api.cb.CbActorReq; 6 | import fun.lib.actor.api.cb.CbActorRsp; 7 | import fun.lib.actor.api.cb.Cb; 8 | import fun.lib.actor.api.cb.CbTimeout; 9 | import fun.lib.actor.core.DFActor; 10 | import fun.lib.actor.core.DFActorManager; 11 | import fun.lib.actor.po.DFMongoCfg; 12 | 13 | /** 14 | * 配合BlockActor操作mongodb示例 15 | * @author lostsky 16 | * 17 | */ 18 | public final class MongodbTest { 19 | 20 | public static void main(String[] args) { 21 | DFActorManager.get().start(EntryActor.class); 22 | } 23 | 24 | 25 | private static class EntryActor extends DFActor{ 26 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 27 | super(id, name, isBlockActor); 28 | // TODO Auto-generated constructor stub 29 | } 30 | @Override 31 | public void onStart(Object param) { 32 | DFMongoCfg cfg = DFMongoCfg.newCfg() 33 | .addAddress("127.0.0.1", //mongodb host 34 | 27017); //mongodb port 35 | int poolId = mongo.initPool(cfg); 36 | //create dbActor to do dbStuff 37 | final int dbActor = sys.createActor(DbActor.class, poolId); 38 | 39 | //timeout 40 | CbTimeout cb = new CbTimeout() { 41 | @Override 42 | public void onTimeout() { 43 | //send db stuff to dbActor 44 | sys.call(dbActor, 0, null, new Cb() { 45 | @Override 46 | public int onCallback(int cmd, Object payload) { 47 | log.info(payload.toString()); 48 | return 0; 49 | } 50 | @Override 51 | public int onFailed(int code) { 52 | log.error("call failed: "+code); 53 | return 0; 54 | } 55 | }); 56 | // 57 | timer.timeout(2000, this); 58 | } 59 | }; 60 | timer.timeout(1000, cb); 61 | } 62 | } 63 | 64 | //use for db stuff 65 | private static class DbActor extends DFActor{ 66 | public DbActor(Integer id, String name, Boolean isBlockActor) { 67 | super(id, name, isBlockActor); 68 | // TODO Auto-generated constructor stub 69 | } 70 | private int poolId = 0; 71 | @Override 72 | public void onStart(Object param) { 73 | poolId = (int) param; 74 | } 75 | @Override 76 | public int onMessage(int cmd, Object payload, int srcId) { 77 | MongoDatabase db = mongo.getDatabase(poolId, "db_test"); 78 | sys.ret(0, "recv mongodb rsp, dbName="+db.getName()); 79 | return 0; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/HttpServerBenchmark.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import java.net.InetSocketAddress; 4 | 5 | import fun.lib.actor.api.DFTcpChannel; 6 | import fun.lib.actor.api.cb.CbHttpServer; 7 | import fun.lib.actor.api.http.DFHttpDispatcher; 8 | import fun.lib.actor.api.http.DFHttpSvrReq; 9 | import fun.lib.actor.core.DFActor; 10 | import fun.lib.actor.core.DFActorManager; 11 | import fun.lib.actor.po.DFTcpServerCfg; 12 | 13 | public final class HttpServerBenchmark { 14 | 15 | public static void main(String[] args) { 16 | final DFActorManager mgr = DFActorManager.get(); 17 | //启动入口actor,开始消息循环 18 | mgr.start(EntryActor.class); 19 | } 20 | 21 | 22 | private static class EntryActor extends DFActor{ 23 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 24 | super(id, name, isBlockActor); 25 | } 26 | private int[] arrProcId = null; 27 | private int reqCount = 0; 28 | @Override 29 | public void onStart(Object param) { 30 | final int cpuNum = Runtime.getRuntime().availableProcessors(); 31 | log.info("cpuNum = "+cpuNum); 32 | arrProcId = new int[cpuNum]; 33 | for(int i=0; i 0){ 60 | sys.toNodeByType("game", "EntryActor", NODE_IDX, "reqByType from "+ARR_NODE_NAME[NODE_IDX]); 61 | } 62 | }else{ //向全部结点广播 63 | int nodeNum = sys.getAllNodeNum(); 64 | if(nodeNum > 0){ 65 | sys.toAllNode("EntryActor", NODE_IDX, "reqForAll from "+ARR_NODE_NAME[NODE_IDX]); 66 | } 67 | } 68 | timer.timeout(2000, 0); 69 | } 70 | } 71 | @Override 72 | public int onClusterMessage(String srcType, String srcNode, String srcActor, int cmd, Object payload) { 73 | log.info(ARR_NODE_NAME[NODE_IDX]+"::onClusterMessage, from="+srcNode+", cmd="+cmd+", payload="+payload); 74 | return 0; 75 | } 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/ClusterNodeEvent.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.api.cb.CbNode; 4 | import fun.lib.actor.core.DFActor; 5 | import fun.lib.actor.core.DFActorManager; 6 | import fun.lib.actor.po.ActorProp; 7 | import fun.lib.actor.po.DFActorClusterConfig; 8 | import fun.lib.actor.po.DFActorManagerConfig; 9 | import fun.lib.actor.po.DFNode; 10 | 11 | /** 12 | * 监听集群内结点事件示例 13 | * 一共启动4个结点,3种类型 14 | * @author lostsky 15 | * 16 | */ 17 | 18 | public final class ClusterNodeEvent { 19 | 20 | private static int IDX_NODE = 3; //0~3 21 | private static final String[] ARR_NODE_NAME = {"game-1", "game-2", "db-1", "chat-1"}; 22 | private static final String[] ARR_NODE_TYPE = {"game", "game", "db", "chat"}; 23 | 24 | public static void main(String[] args){ 25 | String nodeName = ARR_NODE_NAME[IDX_NODE]; 26 | String nodeType = ARR_NODE_TYPE[IDX_NODE]; 27 | DFActorClusterConfig cfgCluster = 28 | DFActorClusterConfig.newCfg(nodeName) //结点名字,一个结点在集群内名字必须唯一(可不设置,默认会自动生成唯一名字) 29 | .setNodeType(nodeType); 30 | DFActorManagerConfig cfgStart = new DFActorManagerConfig() 31 | .setClusterConfig(cfgCluster); //设置集群配置,开启集群功能 32 | //设置业务入口actor,集群初始化和发现完毕后将启动该actor 33 | ActorProp prop = ActorProp.newProp() 34 | .classz(EntryActor.class) 35 | .name("EntryActor"); 36 | DFActorManager.get().start(cfgStart, prop); 37 | } 38 | 39 | private static class EntryActor extends DFActor{ 40 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 41 | super(id, name, isBlockActor); 42 | // TODO Auto-generated constructor stub 43 | } 44 | @Override 45 | public void onStart(Object param) { 46 | if(IDX_NODE == 0){ 47 | //监听所有结点的事件 48 | sys.listenNodeAll(new CbNode() { 49 | @Override 50 | public void onNodeRemove(DFNode node) { 51 | log.info("listenAllCb, nodeRemove: "+node); 52 | } 53 | @Override 54 | public void onNodeAdd(DFNode node) { 55 | log.info("listenAllCb, nodeAdd: "+node); 56 | } 57 | }); 58 | //监听"db"类型结点的事件 59 | sys.listenNodeByType("db", new CbNode() { 60 | @Override 61 | public void onNodeRemove(DFNode node) { 62 | log.info("listenByType, nodeRemove: "+node); 63 | } 64 | @Override 65 | public void onNodeAdd(DFNode node) { 66 | log.info("listenByType, nodeAdd: "+node); 67 | } 68 | }); 69 | //监听名字为"chat-1"结点的事件 70 | sys.listenNodeByName("chat-1", new CbNode() { 71 | @Override 72 | public void onNodeRemove(DFNode node) { 73 | log.info("listenByName, nodeRemove: "+node); 74 | } 75 | @Override 76 | public void onNodeAdd(DFNode node) { 77 | log.info("listenByName, nodeAdd: "+node); 78 | } 79 | }); 80 | } 81 | 82 | } 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/RpcCluster.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import fun.lib.actor.api.cb.Cb; 4 | import fun.lib.actor.api.cb.RpcContext; 5 | import fun.lib.actor.api.cb.RpcFuture; 6 | import fun.lib.actor.core.DFActor; 7 | import fun.lib.actor.core.DFActorManager; 8 | import fun.lib.actor.po.ActorProp; 9 | import fun.lib.actor.po.DFActorClusterConfig; 10 | import fun.lib.actor.po.DFActorManagerConfig; 11 | 12 | 13 | /** 14 | * 集群内结点之间rpc通信示例 15 | * @author lostsky 16 | * 17 | */ 18 | public final class RpcCluster { 19 | private static int NODE_IDX = 0; // 0:以game-1身份启动 1:以game-2身份启动 20 | private static final String[] ARR_NODE_NAME = {"game-1", "game-2"}; 21 | private static final String[] ARR_ACTOR_NAME = {"AskActor", "AnswerActor"}; 22 | 23 | public static void main(String[] args) { 24 | String nodeName = ARR_NODE_NAME[NODE_IDX]; //当前启动结点名字 25 | DFActorClusterConfig cfgCluster = 26 | DFActorClusterConfig.newCfg(nodeName); //结点名字,一个结点在集群内名字必须唯一(可不设置,默认会自动生成唯一名字) 27 | 28 | DFActorManagerConfig cfgStart = new DFActorManagerConfig() 29 | .setClusterConfig(cfgCluster); //设置集群配置,开启集群功能 30 | //设置业务入口actor,集群初始化和发现完毕后将启动该actor 31 | ActorProp prop = ActorProp.newProp() 32 | .classz(NODE_IDX==0?AskActor.class:AnswerActor.class) 33 | .name(ARR_ACTOR_NAME[NODE_IDX]); 34 | DFActorManager.get().start(cfgStart, prop); 35 | } 36 | 37 | private static class AskActor extends DFActor{ 38 | public AskActor(Integer id, String name, Boolean isBlockActor) { 39 | super(id, name, isBlockActor); 40 | timer.timeout(2000, 0); 41 | } 42 | @Override 43 | public void onTimeout(int requestId) { 44 | if(sys.isNodeOnline(ARR_NODE_NAME[1])){ //game-2 is online 45 | RpcFuture future = sys.rpcNode(ARR_NODE_NAME[1], ARR_ACTOR_NAME[1], "doMath", 168, "square"); 46 | if(future.isSendSucc()){ //调用发送成功,可添加结果监听 47 | future.addListener(new Cb() { 48 | @Override 49 | public int onCallback(int cmd, Object payload) { 50 | log.info("rpcResponse: "+payload); 51 | return 0; 52 | } 53 | @Override 54 | public int onFailed(int code) { //调用失败的回调(发送失败 or 回调超时) 见 RpcError.java 55 | log.error("rpcCall failed, code="+code); 56 | return 0; 57 | } 58 | }, 5000); //设置回调超时5000毫秒 59 | } 60 | } 61 | timer.timeout(2000, 0); 62 | } 63 | } 64 | 65 | private static class AnswerActor extends DFActor{ 66 | public AnswerActor(Integer id, String name, Boolean isBlockActor) { 67 | super(id, name, isBlockActor); 68 | } 69 | 70 | //被调用方法需满足如下参数列表: public (int,Object) 71 | public void doMath(int cmd, Object payload){ 72 | log.info("recv ask, cmd="+cmd+", payload="+payload+", srcNode="+sys.getCurSrcNode()+", srcActor="+sys.getCurSrcActor()); 73 | //响应请求 74 | sys.ret(0, "result: square("+cmd+")="+ cmd*cmd); 75 | } 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/api/DFActorNet.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.api; 2 | import java.net.InetAddress; 3 | import java.net.InetSocketAddress; 4 | 5 | import fun.lib.actor.api.cb.CbHttpClient; 6 | import fun.lib.actor.api.cb.CbHttpServer; 7 | import fun.lib.actor.api.http.DFHttpDispatcher; 8 | import fun.lib.actor.po.DFTcpClientCfg; 9 | import fun.lib.actor.po.DFTcpServerCfg; 10 | import fun.lib.actor.po.DFUdpServerCfg; 11 | import io.netty.buffer.ByteBuf; 12 | 13 | public interface DFActorNet { 14 | /** 15 | * 建立tcp监听 16 | * @param cfg 监听参数 17 | */ 18 | public void tcpSvr(DFTcpServerCfg cfg); 19 | /** 20 | * 建立tcp监听 21 | * @param cfg 监听参数 22 | * @param dispatcher 网络消息及事件分发器 23 | */ 24 | public void tcpSvr(DFTcpServerCfg cfg, Object dispatcher); 25 | /** 26 | * 建立tcp监听 27 | * @param port 监听端口号 28 | */ 29 | public void tcpSvr(int port); 30 | /** 31 | * 建立tcp监听 32 | * @param port 监听端口号 33 | * @param dispatcher 网络消息及事件分发器 34 | */ 35 | public void tcpSvr(int port, Object dispatcher); 36 | /** 37 | * 建立tcp监听 38 | * @param port 监听端口号 39 | * @param protocol 协议类型,如DFActorDefine.TCP_DECODE_HTTP 40 | */ 41 | public void tcpSvr(int port, int protocol); 42 | 43 | /** 44 | * 关闭指定端口的监听 45 | * @param port 要关闭监听的端口号 46 | */ 47 | public void closeTcpSvr(int port); 48 | 49 | /** 50 | * 启动http监听 51 | * @param port 端口号 52 | * @param handler 处理器 53 | */ 54 | public void httpSvr(int port, CbHttpServer handler); 55 | /** 56 | * 启动http监听 57 | * @param cfg 监听参数 58 | * @param handler 处理器 59 | */ 60 | public void httpSvr(DFTcpServerCfg cfg, CbHttpServer handler); 61 | /** 62 | * 启动http监听 63 | * @param port 端口号 64 | * @param handler 处理器 65 | * @param dispatcher 消息分发器 66 | */ 67 | public void httpSvr(int port, CbHttpServer handler, DFHttpDispatcher dispatcher); 68 | /** 69 | * 启动http监听 70 | * @param cfg 监听参数 71 | * @param handler 处理器 72 | * @param dispatcher 消息分发器 73 | */ 74 | public void httpSvr(DFTcpServerCfg cfg, CbHttpServer handler, DFHttpDispatcher dispatcher); 75 | 76 | 77 | public void httpCli(DFTcpClientCfg cfg, CbHttpClient handler); 78 | 79 | /** 80 | * 建立tcp连接 81 | * @param cfg 连接参数 82 | * @param requestId 该连接的标识 83 | * @return 0 84 | */ 85 | public int tcpCli(final DFTcpClientCfg cfg, final int requestId); 86 | /** 87 | * 建立tcp连接 88 | * @param cfg 连接参数 89 | * @param requestId 该连接的标识 90 | * @param dispatcher 分发器 91 | * @return 0 92 | */ 93 | public int tcpCli(final DFTcpClientCfg cfg, final int requestId, final DFActorTcpDispatcher dispatcher); 94 | //udp 95 | public void udpSvr(final DFUdpServerCfg cfg, DFActorUdpDispatcher listener, final int requestId); 96 | public void closeUdpSvr(int port); 97 | 98 | public int udpCli(ByteBuf buf, InetSocketAddress addr); 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFJsBuffer.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.UnpooledByteBufAllocator; 5 | import io.netty.util.CharsetUtil; 6 | 7 | public final class DFJsBuffer implements IScriptBuffer{ 8 | 9 | private final ByteBuf buf; 10 | private DFJsBuffer(int capacity) { 11 | buf = UnpooledByteBufAllocator.DEFAULT.heapBuffer(capacity); 12 | } 13 | private DFJsBuffer(ByteBuf buf){ 14 | this.buf = buf; 15 | } 16 | 17 | protected static DFJsBuffer newBuffer(int capacity){ 18 | return new DFJsBuffer(capacity); 19 | } 20 | protected static DFJsBuffer newBuffer(ByteBuf buf){ 21 | return new DFJsBuffer(buf); 22 | } 23 | 24 | protected ByteBuf getBuf(){ 25 | return buf; 26 | } 27 | 28 | protected void readBytes(byte[] bytes){ 29 | buf.readBytes(bytes); 30 | } 31 | 32 | @Override 33 | public int leftRead() { 34 | return buf.readableBytes(); 35 | } 36 | @Override 37 | public boolean writeInt(int num) { 38 | if(buf.writableBytes() >= 4){ 39 | buf.writeInt(num); 40 | return true; 41 | } 42 | return false; 43 | } 44 | @Override 45 | public boolean writeShort(int num) { 46 | if(buf.writableBytes() >= 2){ 47 | buf.writeShort(num); 48 | return true; 49 | } 50 | return false; 51 | } 52 | @Override 53 | public boolean writeByte(int num) { 54 | if(buf.writableBytes() >= 1){ 55 | buf.writeByte(num); 56 | return true; 57 | } 58 | return false; 59 | } 60 | @Override 61 | public boolean writeStr(String src, int len) { 62 | byte[] bufStr = src.getBytes(CharsetUtil.UTF_8); 63 | int lenStr = bufStr.length; 64 | buf.writeBytes(bufStr, 0, Math.min(lenStr, buf.writableBytes())); 65 | return true; 66 | } 67 | 68 | @Override 69 | public boolean writeBytes(IScriptBuffer src) { 70 | ByteBuf bufSrc = ((DFJsBuffer) src).getBuf(); 71 | if(buf.writableBytes() >= bufSrc.readableBytes()){ 72 | buf.writeBytes(bufSrc); 73 | return true; 74 | } 75 | return false; 76 | } 77 | 78 | @Override 79 | public int readInt() { 80 | return buf.readInt(); 81 | } 82 | @Override 83 | public int readShort() { 84 | return buf.readShort(); 85 | } 86 | @Override 87 | public int readByte() { 88 | return buf.readByte(); 89 | } 90 | @Override 91 | public String readStr(int len) { 92 | return (String) buf.readCharSequence(len, CharsetUtil.UTF_8); 93 | } 94 | 95 | @Override 96 | public void release() { 97 | if(buf.refCnt() > 0){ 98 | buf.release(); 99 | } 100 | } 101 | 102 | @Override 103 | public int getInt(int idx) { 104 | return buf.getInt(idx); 105 | } 106 | @Override 107 | public int getShort(int idx) { 108 | return buf.getShort(idx); 109 | } 110 | @Override 111 | public int getByte(int idx) { 112 | return buf.getByte(idx); 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/ClusterSimple.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | import fun.lib.actor.core.DFActor; 3 | import fun.lib.actor.core.DFActorManager; 4 | import fun.lib.actor.helper.DFActorLogLevel; 5 | import fun.lib.actor.po.ActorProp; 6 | import fun.lib.actor.po.DFActorClusterConfig; 7 | import fun.lib.actor.po.DFActorManagerConfig; 8 | 9 | 10 | /** 11 | * 集群功能简单示例 12 | * 模拟集群的两个结点"game-1"和"game-2"互相发现,互发消息 13 | * @author lostsky 14 | * 15 | */ 16 | 17 | public final class ClusterSimple { 18 | 19 | private static int NODE_IDX = 0; // 0:以game-1身份启动 1:以game-2身份启动 20 | private static final String[] ARR_NODE_NAME = {"game-1", "game-2"}; 21 | 22 | 23 | public static void main(String[] args) { 24 | String nodeName = ARR_NODE_NAME[NODE_IDX]; //当前启动结点名字 25 | DFActorClusterConfig cfgCluster = 26 | DFActorClusterConfig.newCfg(nodeName); //结点名字,一个结点在集群内名字必须唯一(可不设置,默认会自动生成唯一名字) 27 | //以下为可选参数,根据实际应用情况设置 28 | // .setClusterName("MyGameCluster") //集群名字,只有集群名字相同的结点才会互相发现并连接 29 | // .setNodeType("game"); //结点类型(可以给某一类功能的结点取同一个类型名字,实现诸如广播等功能) 30 | // .setSecretKey("1234567") //结点间通信秘钥,可防止其它未授权结点连接,只有秘钥相同的结点才能互相通信 31 | // .addSpecifyIP("192.168.123.7"); //添加指定服务器地址(可以使结点发现更快速) 32 | // .setIPRange("192.168.123.5", "192.168.123.16"); //使用ip地址段的方式来发现结点 33 | //如果既未指定服务器地址,也未设置ip地址段,则结点会向全局域网内的服务器广播搜索 34 | 35 | DFActorManagerConfig cfgStart = new DFActorManagerConfig() 36 | .setClusterConfig(cfgCluster); //设置集群配置,开启集群功能 37 | //设置业务入口actor,集群初始化和发现完毕后将启动该actor 38 | ActorProp prop = ActorProp.newProp() 39 | .classz(EntryActor.class) 40 | .name("EntryActor"); 41 | DFActorManager.get().start(cfgStart, prop); 42 | } 43 | 44 | private static class EntryActor extends DFActor{ 45 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 46 | super(id, name, isBlockActor); 47 | // TODO Auto-generated constructor stub 48 | } 49 | @Override 50 | public void onStart(Object param) { 51 | log.info("onStart"); 52 | if(NODE_IDX == 0){ //由game-1结点定时向game-2发送消息 53 | timer.timeout(1000, 10001); 54 | } 55 | } 56 | @Override 57 | public void onTimeout(int requestId) { 58 | if(NODE_IDX == 0){ //game-1 ask, game-2 answer 59 | //检测game-2是否已经加入集群 60 | String selfNode = ARR_NODE_NAME[NODE_IDX]; 61 | String dstNode = ARR_NODE_NAME[(NODE_IDX+1)%2]; 62 | if(sys.isNodeOnline(dstNode)){ //game-2已经加入集群,发送消息 63 | sys.toNode(dstNode, "EntryActor", NODE_IDX, "ask from "+selfNode+", tm="+System.currentTimeMillis()); 64 | } 65 | timer.timeout(1000, 10001); 66 | } 67 | } 68 | @Override 69 | public int onClusterMessage(String srcType, String srcNode, String srcActor, int cmd, Object payload) { 70 | log.info("onClusterMessage, from="+srcNode+", cmd="+cmd+", payload="+payload); 71 | if(NODE_IDX == 1){ //game-2收到game-1消息,回复 72 | sys.ret(1, "answer from game-2, tm="+System.currentTimeMillis()); 73 | } 74 | return 0; 75 | } 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/system/DFSysUtil.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.system; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.io.InputStreamReader; 8 | import java.io.OutputStreamWriter; 9 | import java.io.PrintWriter; 10 | import java.util.List; 11 | import java.util.UUID; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | public final class DFSysUtil { 15 | 16 | public static final int OS_UNKNOWN = 0; 17 | public static final int OS_LINUX = 1; 18 | public static final int OS_WINDOWS = 2; 19 | public static final int OS_MAC = 3; 20 | 21 | private static int _osType = OS_UNKNOWN; 22 | static{ 23 | final String osName = System.getProperty("os.name"); 24 | if(osName != null){ 25 | final String osNameLow = osName.toLowerCase(); 26 | if(osNameLow.contains("linux")){ 27 | _osType = OS_LINUX; 28 | }else if(osNameLow.contains("windows")){ 29 | _osType = OS_WINDOWS; 30 | } 31 | } 32 | } 33 | 34 | public static int getOSType(){ 35 | return _osType; 36 | } 37 | 38 | public static boolean isLinux(){ 39 | return _osType==OS_LINUX?true:false; 40 | } 41 | 42 | 43 | public static int execShellCmd(final List cmds, final List out, final int timeoutSec){ 44 | if(!DFSysUtil.isLinux()){ 45 | return -4; 46 | } 47 | 48 | File dirBin = new File("/bin"); 49 | Process p = null; 50 | try { 51 | p = Runtime.getRuntime().exec("/bin/bash", null, dirBin); 52 | } catch (IOException e) { 53 | e.printStackTrace(); 54 | return -1; 55 | } 56 | if(p != null){ 57 | BufferedReader br = null; 58 | if(out != null){ 59 | br = new BufferedReader(new InputStreamReader(p.getInputStream())); 60 | } 61 | PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(p.getOutputStream())), true); 62 | //exec cmd 63 | // pw.println("pwd"); 64 | // pw.println("cd ~/javatest"); 65 | for(String cmd : cmds){ 66 | pw.println(cmd); 67 | } 68 | pw.println("exit"); 69 | // 70 | if(br != null){ 71 | String line = null; 72 | try { 73 | while((line=br.readLine()) != null){ 74 | if(out != null){ 75 | out.add(line); 76 | } 77 | } 78 | } catch (IOException e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | 83 | try { 84 | boolean bExit = p.waitFor(timeoutSec, TimeUnit.SECONDS); 85 | if(bExit){ 86 | return 0; 87 | } 88 | return 1; 89 | } catch (InterruptedException e) { 90 | e.printStackTrace(); 91 | return -2; 92 | }finally{ 93 | if(br != null){ 94 | try { 95 | br.close(); 96 | } catch (IOException e) { 97 | // TODO Auto-generated catch block 98 | e.printStackTrace(); 99 | } 100 | } 101 | pw.close(); 102 | p.destroy(); 103 | } 104 | } 105 | return -3; 106 | } 107 | 108 | 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/IScriptAPI.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import com.google.protobuf.GeneratedMessageV3.Builder; 4 | 5 | import fun.lib.actor.api.http.DFHttpCliReq; 6 | 7 | public interface IScriptAPI { 8 | 9 | //sys function 10 | public int newActor(Object template, Object name, Object param, Object initCfg); 11 | public int to(Object dst, int cmd, Object payload); 12 | public int call(Object dst, int cmd, Object payload, Object cb); 13 | public int ret(int cmd, Object payload); 14 | public void timeout(int delay, Object requestId); 15 | public int rpc(Object dstActor, String dstMethod, int cmd, Object payload, Object cb); 16 | public int cpuNum(); 17 | 18 | //cluster 19 | public int toNode(String dstNode, String dstActor, int cmd, Object payload); 20 | public int toTypeNode(String type, String dstActor, int cmd, Object payload); 21 | public int toAllNode(String dstActor, int cmd, Object payload); 22 | public int rpcNode(String dstNode, String dstActor, String dstMethod, int cmd, Object payload, Object cb); 23 | public boolean isNode(); 24 | public String getNodeName(); 25 | public String getNodeType(); 26 | public int listenNode(String type, Object val, Object cb); 27 | public boolean isNodeOnline(String nodeName); 28 | 29 | //buf function 30 | public IScriptBuffer newBuf(int capacity); 31 | //proto function 32 | public Object bufToProto(IScriptBuffer buf, String className); 33 | public IScriptBuffer protoToBuf(Builder builder); 34 | public Object getProtoBuilder(String className); 35 | //lock function 36 | public boolean lockWrite(Object var, Object func); 37 | public boolean lockRead(Object var, Object func); 38 | //tcp function 39 | public boolean tcpSvr(Object cfg, Object func); 40 | public boolean tcpCli(Object cfg, Object func); 41 | public boolean tcpSend(Integer channelId, Object msg); 42 | public void tcpChange(Integer channelId, Object msgHandler, Object statusHandler); 43 | 44 | //http function 45 | public boolean httpSvr(Object cfg, Object cb); 46 | public void httpCli(Object cfg, Object cb); 47 | public DFHttpCliReq newHttpReq(); 48 | 49 | //mysql function 50 | public int mysqlInitPool(Object cfg); 51 | public int mysqlGetConn(int poolId, Object cb); 52 | 53 | //redis function 54 | public int redisInitPool(Object cfg); 55 | public int redisGetConn(int poolId, Object cb); 56 | 57 | //mongodb function 58 | public int mongoInitPool(Object cfg); 59 | public int mongoGetDb(int poolId, String db, Object cb); 60 | 61 | //string <-> buf 62 | public String bufToStr(Object buf); 63 | public IScriptBuffer strToBuf(String src); 64 | 65 | public void exit(); 66 | 67 | //log function 68 | public void logV(Object msg); 69 | public void logD(Object msg); 70 | public void logI(Object msg); 71 | public void logW(Object msg); 72 | public void logE(Object msg); 73 | public void logF(Object msg); 74 | 75 | //reflect function 76 | public Object objByName(String name); 77 | public Object callObjMethod(Object obj, String method, Object...param); 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/funtag/util/log/DFLogFactory.java: -------------------------------------------------------------------------------- 1 | package com.funtag.util.log; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Calendar; 5 | 6 | public final class DFLogFactory { 7 | 8 | public static final int LEVEL_VERB = 1; 9 | public static final int LEVEL_DEBUG = 2; 10 | public static final int LEVEL_INFO = 3; 11 | public static final int LEVEL_WARN = 4; 12 | public static final int LEVEL_ERROR = 5; 13 | public static final int LEVEL_FATAL = 6; 14 | 15 | public static DFLogger create(final Class c){ 16 | return new DFLogger() { 17 | private SimpleDateFormat _sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 18 | private final String className = c.getSimpleName(); 19 | private final StringBuffer sbLog = new StringBuffer(); 20 | private void getTimePfx(final StringBuffer sb){ 21 | sb.setLength(0); 22 | sb.append(_sdf.format(Calendar.getInstance().getTime())); 23 | sb.append("["); 24 | sb.append(className); 25 | sb.append("]"); 26 | } 27 | @Override 28 | public void V(String msg) { 29 | if(DFLogFactory._logLevel <= LEVEL_VERB){ 30 | sbLog.setLength(0); 31 | getTimePfx(sbLog); 32 | sbLog.append("[V]"); 33 | sbLog.append(msg); 34 | System.out.println(sbLog.toString()); 35 | } 36 | } 37 | @Override 38 | public void D(String msg) { 39 | if(DFLogFactory._logLevel <= LEVEL_DEBUG){ 40 | sbLog.setLength(0); 41 | getTimePfx(sbLog); 42 | sbLog.append("[D]"); 43 | sbLog.append(msg); 44 | System.out.println(sbLog.toString()); 45 | } 46 | } 47 | @Override 48 | public void I(String msg) { 49 | if(DFLogFactory._logLevel <= LEVEL_INFO){ 50 | sbLog.setLength(0); 51 | getTimePfx(sbLog); 52 | sbLog.append("[I]"); 53 | sbLog.append(msg); 54 | System.out.println(sbLog.toString()); 55 | } 56 | } 57 | @Override 58 | public void W(String msg) { 59 | if(DFLogFactory._logLevel <= LEVEL_WARN){ 60 | sbLog.setLength(0); 61 | getTimePfx(sbLog); 62 | sbLog.append("[W]"); 63 | sbLog.append(msg); 64 | System.out.println(sbLog.toString()); 65 | } 66 | } 67 | @Override 68 | public void E(String msg) { 69 | if(DFLogFactory._logLevel <= LEVEL_ERROR){ 70 | sbLog.setLength(0); 71 | getTimePfx(sbLog); 72 | sbLog.append("[E]"); 73 | sbLog.append(msg); 74 | System.out.println(sbLog.toString()); 75 | } 76 | } 77 | @Override 78 | public void F(String msg) { 79 | sbLog.setLength(0); 80 | getTimePfx(sbLog); 81 | sbLog.append("[F]"); 82 | sbLog.append(msg); 83 | System.out.println(sbLog.toString()); 84 | } 85 | }; 86 | } 87 | 88 | private static volatile int _logLevel = LEVEL_INFO; 89 | 90 | public static boolean setLogLevel(int level){ 91 | if(level <= LEVEL_FATAL && level >= LEVEL_VERB){ 92 | _logLevel = level; 93 | return true; 94 | } 95 | return false; 96 | } 97 | 98 | } 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/MysqlTest.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import java.sql.Connection; 4 | import java.sql.ResultSet; 5 | import java.sql.Statement; 6 | 7 | import fun.lib.actor.api.cb.CbActorReq; 8 | import fun.lib.actor.api.cb.CbActorRsp; 9 | import fun.lib.actor.api.cb.Cb; 10 | import fun.lib.actor.api.cb.CbTimeout; 11 | import fun.lib.actor.core.DFActor; 12 | import fun.lib.actor.core.DFActorManager; 13 | import fun.lib.actor.po.DFDbCfg; 14 | 15 | /** 16 | * 配合BlockActor操作mysql示例 17 | * @author lostsky 18 | * 19 | */ 20 | public final class MysqlTest { 21 | 22 | public static void main(String[] args) { 23 | DFActorManager.get().start(EntryActor.class); 24 | } 25 | 26 | private static class EntryActor extends DFActor{ 27 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 28 | super(id, name, isBlockActor); 29 | // TODO Auto-generated constructor stub 30 | } 31 | 32 | @Override 33 | public void onStart(Object param) { 34 | DFDbCfg cfg = DFDbCfg.newCfg( 35 | "127.0.0.1", //db host 36 | 3306, //db port 37 | "db_test", //db name 38 | "user", //db username 39 | "pwd"); //db password 40 | int poolId = db.initPool(cfg); 41 | //create io actor 42 | final int ioActor = sys.createActor(IoActor.class, poolId); 43 | //start timer 44 | CbTimeout cb = new CbTimeout() { 45 | @Override 46 | public void onTimeout() { 47 | //send db task to ioActor 48 | sys.call(ioActor, 0, null, new Cb() { 49 | @Override 50 | public int onCallback(int cmd, Object payload) { 51 | log.info(payload.toString()); 52 | return 0; 53 | } 54 | @Override 55 | public int onFailed(int code) { 56 | log.error("call failed: "+code); 57 | return 0; 58 | } 59 | }); 60 | // 61 | timer.timeout(2000, this); 62 | } 63 | }; 64 | timer.timeout(1000, cb); 65 | } 66 | } 67 | 68 | //ioActor, use for db operation 69 | private static class IoActor extends DFActor{ 70 | public IoActor(Integer id, String name, Boolean isBlockActor) { 71 | super(id, name, isBlockActor); 72 | // TODO Auto-generated constructor stub 73 | } 74 | private int poolId = 0; 75 | @Override 76 | public void onStart(Object param) { 77 | poolId = (int) param; 78 | } 79 | @Override 80 | public int onMessage(int cmd, Object payload, int srcId) { 81 | //do db stuff 82 | String rsp = null; 83 | Connection conn = db.getConn(poolId); 84 | try{ 85 | if(conn != null){ 86 | Statement stmt = conn.createStatement(); 87 | ResultSet rs = stmt.executeQuery("SELECT NOW()"); 88 | rs.next(); 89 | String dt = rs.getString(1); 90 | rsp = "recv rsp from db, now=" + dt; 91 | } 92 | }catch(Throwable e){ 93 | e.printStackTrace(); 94 | }finally{ 95 | db.closeConn(conn); 96 | } 97 | //callback logicActor 98 | sys.ret(0, rsp); 99 | return 0; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/kcp/KcpLoop.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.kcp; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.concurrent.LinkedBlockingQueue; 6 | import io.netty.channel.socket.DatagramPacket; 7 | 8 | public final class KcpLoop implements Runnable{ 9 | 10 | private final int id; 11 | private final LinkedBlockingQueue queueRecv; 12 | private final KcpListener listener; 13 | private final KcpConfigInner kcpCfg; 14 | 15 | public KcpLoop(int id, KcpListener listener, KcpConfig kcpCfgOri) { 16 | this.id = id; 17 | this.listener = listener; 18 | queueRecv = new LinkedBlockingQueue<>(); 19 | kcpCfg = KcpConfigInner.copyConfig(kcpCfgOri); 20 | } 21 | 22 | private final HashMap mapKcp = new HashMap<>(); 23 | 24 | @Override 25 | public void run() { 26 | this.onLoop = true; 27 | DatagramPacket pack = null; 28 | Kcp kcp = null; 29 | long tmStart = 0; 30 | long tmNow = 0; 31 | final long intervalDef = 10; 32 | long interval = 0; 33 | int recvCount = 0; 34 | int connId = 0; 35 | // 36 | while(this.onLoop){ 37 | try{ 38 | tmStart = System.currentTimeMillis(); 39 | //proc recv 40 | recvCount = 0; 41 | pack = queueRecv.poll(); 42 | while(pack != null){ 43 | connId = pack.content().readInt(); 44 | kcp = mapKcp.get(connId); 45 | if(kcp == null){ //new conn 46 | kcp = new Kcp(listener, kcpCfg, pack.sender(), connId, tmStart); 47 | mapKcp.put(connId, kcp); 48 | //notify 49 | listener.onChannelActive(kcp, connId); 50 | } 51 | kcp.onReceiveRaw(pack); 52 | // 53 | if(++recvCount < 1000){ 54 | pack = queueRecv.poll(); 55 | }else{ 56 | break; 57 | } 58 | } 59 | //proc update 60 | tmNow = System.currentTimeMillis(); 61 | final Iterator itKcp = mapKcp.values().iterator(); 62 | while(itKcp.hasNext()){ 63 | kcp = itKcp.next(); 64 | if(!kcp.isClosed()){ 65 | kcp.onUpdate(tmNow); 66 | }else{ 67 | itKcp.remove(); 68 | } 69 | } 70 | //wait 71 | interval = intervalDef - System.currentTimeMillis() + tmStart; 72 | if(interval > 5){ 73 | // pack = queueRecv.poll(interval, TimeUnit.MILLISECONDS); 74 | Thread.sleep(interval); 75 | } 76 | }catch(Throwable e){ 77 | e.printStackTrace(); 78 | } 79 | } 80 | // 81 | this.release(); 82 | } 83 | 84 | private void release(){ 85 | while(!queueRecv.isEmpty()){ 86 | final DatagramPacket pack = queueRecv.poll(); 87 | pack.release(); 88 | } 89 | final Iterator itKcp = mapKcp.values().iterator(); 90 | while(itKcp.hasNext()){ 91 | itKcp.next().release(); 92 | } 93 | } 94 | 95 | public int onReceive(DatagramPacket pack){ 96 | if(onLoop){ 97 | if(queueRecv.offer(pack)){ 98 | return 0; 99 | } 100 | } 101 | pack.release(); 102 | return 1; 103 | } 104 | private volatile boolean onLoop = false; 105 | 106 | public void stop(){ 107 | this.onLoop = false; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFMongoManager.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.LinkedList; 6 | import java.util.concurrent.locks.ReentrantReadWriteLock; 7 | import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; 8 | import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; 9 | import com.mongodb.MongoClient; 10 | import com.mongodb.MongoClientOptions; 11 | import com.mongodb.MongoCredential; 12 | import com.mongodb.client.MongoDatabase; 13 | 14 | import fun.lib.actor.po.DFMongoCfg; 15 | 16 | public final class DFMongoManager { 17 | 18 | protected DFMongoManager() { 19 | // TODO Auto-generated constructor stub 20 | } 21 | 22 | private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 23 | private final ReadLock lockRead = lock.readLock(); 24 | private final WriteLock lockWrite = lock.writeLock(); 25 | private final HashMap mapPool = new HashMap<>(); 26 | private int idCount = 1; 27 | 28 | protected int initPool(DFMongoCfg cfg){ 29 | MongoClient cli = null; 30 | MongoCredential credential = cfg.getCredential(); 31 | MongoClientOptions options = cfg.getOptions(); 32 | if(credential != null && options != null){ 33 | cli = new MongoClient(cfg.getAllAddress(), credential, options); 34 | }else if(credential != null){ 35 | cli = new MongoClient(cfg.getAllAddress(), credential, MongoClientOptions.builder().build()); 36 | }else if(options != null){ 37 | cli = new MongoClient(cfg.getAllAddress(), options); 38 | }else{ 39 | cli = new MongoClient(cfg.getAllAddress()); 40 | } 41 | // 42 | int curId = idCount; 43 | lockWrite.lock(); 44 | try{ 45 | mapPool.put(curId, cli); 46 | if(idCount >= Integer.MAX_VALUE){ 47 | idCount = 1; 48 | }else{ 49 | ++idCount; 50 | } 51 | }finally{ 52 | lockWrite.unlock(); 53 | } 54 | return curId; 55 | } 56 | 57 | protected MongoDatabase getDatabase(int id, String dbName){ 58 | MongoDatabase db = null; 59 | lockRead.lock(); 60 | try{ 61 | MongoClient cli = mapPool.get(id); 62 | if(cli != null){ 63 | db = cli.getDatabase(dbName); 64 | } 65 | }finally{ 66 | lockRead.unlock(); 67 | } 68 | return db; 69 | } 70 | 71 | protected void closePool(int id){ 72 | MongoClient cli = null; 73 | lockWrite.lock(); 74 | try{ 75 | cli = mapPool.remove(id); 76 | }finally{ 77 | lockWrite.unlock(); 78 | } 79 | if(cli != null){ 80 | cli.close(); 81 | cli = null; 82 | } 83 | } 84 | 85 | protected void closeAllPool(){ 86 | LinkedList lsTmp = new LinkedList<>(); 87 | lockWrite.lock(); 88 | try{ 89 | Iterator it = mapPool.values().iterator(); 90 | while(it.hasNext()){ 91 | lsTmp.offer(it.next()); 92 | it.remove(); 93 | } 94 | }finally{ 95 | lockWrite.unlock(); 96 | } 97 | // 98 | Iterator it = lsTmp.iterator(); 99 | while(it.hasNext()){ 100 | it.next().close(); 101 | it.remove(); 102 | } 103 | } 104 | 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/test/java/fun/lib/actor/example/HttpServerDispatcher.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.example; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import fun.lib.actor.api.DFTcpChannel; 8 | import fun.lib.actor.api.cb.CbHttpServer; 9 | import fun.lib.actor.api.http.DFHttpDispatcher; 10 | import fun.lib.actor.api.http.DFHttpSvrReq; 11 | import fun.lib.actor.core.DFActor; 12 | import fun.lib.actor.core.DFActorDefine; 13 | import fun.lib.actor.core.DFActorManager; 14 | 15 | /** 16 | * 根据http请求路径分配不同actor处理逻辑的示例 17 | * @author lostsky 18 | * 19 | */ 20 | public final class HttpServerDispatcher { 21 | 22 | public static void main(String[] args) { 23 | DFActorManager.get().start(EntryActor.class); 24 | } 25 | 26 | private static class EntryActor extends DFActor implements DFHttpDispatcher{ 27 | 28 | private Map mapUri = new HashMap<>(); 29 | @Override 30 | public void onStart(Object param) { 31 | int actorId = sys.createActor("/index", IndexActor.class); 32 | mapUri.put("/index", actorId); 33 | actorId = sys.createActor("/user", UserActor.class); 34 | mapUri.put("/user", actorId); 35 | // 36 | net.httpSvr(8080, new CbHttpServer() { 37 | @Override 38 | public int onHttpRequest(Object msg) { 39 | DFHttpSvrReq req = (DFHttpSvrReq) msg; 40 | //response 41 | req.response("echo from server, entryModule, reqUri="+req.getUri()+", curThread="+Thread.currentThread().getName()) 42 | .send(); 43 | return 0; 44 | } 45 | @Override 46 | public void onListenResult(boolean isSucc, String errMsg) { 47 | log.info("listen result: isSucc="+isSucc+", err="+errMsg); 48 | if(!isSucc){ 49 | sys.shutdown(); 50 | } 51 | } 52 | }, this); //start http server 53 | } 54 | @Override 55 | public int onQueryMsgActorId(int port, InetSocketAddress addrRemote, Object msg) { 56 | DFHttpSvrReq req = (DFHttpSvrReq) msg; 57 | Integer actorId = mapUri.get(req.getUri()); 58 | if(actorId != null && actorId != 0){ //有处理actor的映射 59 | return actorId; 60 | } 61 | return id; //默认转发给本actor 62 | } 63 | 64 | public EntryActor(Integer id, String name, Boolean isBlockActor) { 65 | super(id, name, isBlockActor); 66 | } 67 | } 68 | 69 | private static class IndexActor extends DFActor{ 70 | @Override 71 | public int onTcpRecvMsg(int requestId, DFTcpChannel channel, Object msg) { 72 | DFHttpSvrReq req = (DFHttpSvrReq) msg; 73 | //response 74 | req.response("echo from server, indexModule, reqUri="+req.getUri()+", curThread="+Thread.currentThread().getName()) 75 | .send(); 76 | return 0; 77 | } 78 | public IndexActor(Integer id, String name, Boolean isBlockActor) { 79 | super(id, name, isBlockActor); 80 | } 81 | } 82 | 83 | private static class UserActor extends DFActor{ 84 | @Override 85 | public int onTcpRecvMsg(int requestId, DFTcpChannel channel, Object msg) { 86 | DFHttpSvrReq req = (DFHttpSvrReq) msg; 87 | //response 88 | req.response("echo from server, userModule, reqUri="+req.getUri()+", curThread="+Thread.currentThread().getName()) 89 | .send(); 90 | return 0; 91 | } 92 | public UserActor(Integer id, String name, Boolean isBlockActor) { 93 | super(id, name, isBlockActor); 94 | } 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFActorClusterConfig.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | import java.util.LinkedList; 4 | 5 | public final class DFActorClusterConfig { 6 | 7 | private DFActorClusterConfig(){ 8 | 9 | } 10 | private DFActorClusterConfig(String nodeName){ 11 | setNodeName(nodeName); 12 | } 13 | 14 | private String nodeName = null; 15 | private String nodeType = "cluster.node.test"; 16 | private int ioThreadNum = 1; 17 | private String secretKey = "lostsky3000winthegame_dada"; 18 | // 19 | private int basePort = 30203; 20 | private String clusterName = "cluster.name.test"; 21 | private IPRange ipRange = null; 22 | private LinkedList lsSpecifyIp = null; 23 | private boolean pingTest = false; 24 | 25 | // 26 | public String getClusterName(){ 27 | return this.clusterName; 28 | } 29 | public DFActorClusterConfig setClusterName(String name){ 30 | if(name != null && name.length() > 0){ 31 | this.clusterName = name; 32 | } 33 | return this; 34 | } 35 | 36 | public int getBasePort(){ 37 | return this.basePort; 38 | } 39 | public DFActorClusterConfig setBasePort(int port){ 40 | this.basePort = port; 41 | return this; 42 | } 43 | 44 | public IPRange getIPRange(){ 45 | return this.ipRange; 46 | } 47 | public DFActorClusterConfig setIPRange(String ipBegin, String ipEnd){ 48 | this.ipRange = new IPRange(ipBegin, ipEnd); 49 | return this; 50 | } 51 | 52 | public LinkedList getSpecifyIPList(){ 53 | return this.lsSpecifyIp; 54 | } 55 | public DFActorClusterConfig addSpecifyIP(String ip){ 56 | if(lsSpecifyIp == null){ 57 | lsSpecifyIp = new LinkedList<>(); 58 | } 59 | lsSpecifyIp.add(ip); 60 | ipRange = null; 61 | return this; 62 | } 63 | public DFActorClusterConfig addSpecifyIPList(String[] arrIP){ 64 | if(lsSpecifyIp == null){ 65 | lsSpecifyIp = new LinkedList<>(); 66 | } 67 | int num = arrIP.length; 68 | for(int i=0; i 0){ 95 | this.nodeName = nodeName; 96 | } 97 | return this; 98 | } 99 | public String getNodeType(){ 100 | return this.nodeType; 101 | } 102 | public DFActorClusterConfig setNodeType(String nodeType){ 103 | if(nodeType != null && nodeType.length() > 0){ 104 | this.nodeType = nodeType; 105 | } 106 | return this; 107 | } 108 | 109 | public String getSecretKey(){ 110 | return this.secretKey; 111 | } 112 | public DFActorClusterConfig setSecretKey(String secretKey){ 113 | if(secretKey != null && secretKey.length() > 0){ 114 | this.secretKey = secretKey; 115 | } 116 | return this; 117 | } 118 | 119 | // 120 | public static DFActorClusterConfig newCfg(String nodeName){ 121 | return new DFActorClusterConfig(nodeName); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFWSRequestHandler.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.ChannelFutureListener; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.channel.ChannelPipeline; 9 | import io.netty.channel.SimpleChannelInboundHandler; 10 | import io.netty.handler.codec.http.DefaultFullHttpResponse; 11 | import io.netty.handler.codec.http.FullHttpRequest; 12 | import io.netty.handler.codec.http.FullHttpResponse; 13 | import io.netty.handler.codec.http.HttpHeaderNames; 14 | import io.netty.handler.codec.http.HttpMethod; 15 | import io.netty.handler.codec.http.HttpRequest; 16 | import io.netty.handler.codec.http.HttpResponseStatus; 17 | import io.netty.handler.codec.http.HttpUtil; 18 | import io.netty.handler.codec.http.HttpVersion; 19 | import io.netty.handler.ssl.SslHandler; 20 | import io.netty.util.CharsetUtil; 21 | 22 | public class DFWSRequestHandler extends SimpleChannelInboundHandler { //1 23 | 24 | private final String _wsUri; 25 | 26 | public DFWSRequestHandler(final String wsUri) { 27 | _wsUri = wsUri; 28 | } 29 | 30 | @Override 31 | protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { 32 | // Handle a bad request 33 | if (!req.decoderResult().isSuccess()) { 34 | _sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST)); 35 | return; 36 | } 37 | // Allow only GET methods 38 | if (req.method() != HttpMethod.GET) { 39 | _sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN)); 40 | return; 41 | } 42 | 43 | // Send the index page 44 | final String uri = req.uri(); 45 | if (_wsUri.equals(uri)) { 46 | // String webSocketLocation = _getWebSocketLocation(ctx.pipeline(), req, _wsUri); 47 | // ByteBuf content = WebSocketServerIndexPage.getContent(webSocketLocation); 48 | // FullHttpResponse res = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content); 49 | // 50 | // res.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/html; charset=UTF-8"); 51 | // HttpHeaders.setContentLength(res, content.readableBytes()); 52 | // 53 | // _sendHttpResponse(ctx, req, res); 54 | 55 | ctx.fireChannelRead(req.setUri(_wsUri).retain()); 56 | } else { 57 | _sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND)); 58 | } 59 | 60 | 61 | 62 | } 63 | @Override 64 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 65 | cause.printStackTrace(); 66 | ctx.close(); 67 | } 68 | 69 | private void _sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse rsp) { 70 | // Generate an error page if response getStatus code is not OK (200). 71 | if (rsp.status().code() != 200) { 72 | ByteBuf buf = Unpooled.copiedBuffer(rsp.status().toString(), CharsetUtil.UTF_8); 73 | rsp.content().writeBytes(buf); 74 | buf.release(); 75 | HttpUtil.setContentLength(rsp, rsp.content().readableBytes()); 76 | } 77 | // Send the response and close the connection if necessary. 78 | ChannelFuture f = ctx.channel().writeAndFlush(rsp); 79 | if (!HttpUtil.isKeepAlive(req) || rsp.status().code() != 200) { 80 | f.addListener(ChannelFutureListener.CLOSE); 81 | } 82 | } 83 | 84 | private static String _getWebSocketLocation(ChannelPipeline cp, HttpRequest req, String path) { 85 | String protocol = "ws"; 86 | if (cp.get(SslHandler.class) != null) { 87 | // SSL in use so use Secure WebSockets 88 | protocol = "wss"; 89 | } 90 | return protocol + "://" + req.headers().get(HttpHeaderNames.HOST) + path; 91 | } 92 | 93 | 94 | } 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFDbResultSet.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | import java.util.Collection; 4 | import java.util.Iterator; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | import java.util.ListIterator; 8 | 9 | public final class DFDbResultSet implements List{ 10 | private final LinkedList _lsRaw = new LinkedList<>(); 11 | private int _size = 0; 12 | public DFDbResultSet() { 13 | // TODO Auto-generated constructor stub 14 | } 15 | 16 | public void setSize(int size){ 17 | this._size = size; 18 | } 19 | public int getSize(){ 20 | return this._size; 21 | } 22 | 23 | @Override 24 | public int size() { 25 | // TODO Auto-generated method stub 26 | return _lsRaw.size(); 27 | } 28 | 29 | @Override 30 | public boolean isEmpty() { 31 | return _lsRaw.isEmpty(); 32 | } 33 | 34 | @Override 35 | public boolean contains(Object o) { 36 | // TODO Auto-generated method stub 37 | return _lsRaw.contains(o); 38 | } 39 | 40 | @Override 41 | public Iterator iterator() { 42 | // TODO Auto-generated method stub 43 | return _lsRaw.iterator(); 44 | } 45 | 46 | @Override 47 | public Object[] toArray() { 48 | // TODO Auto-generated method stub 49 | return _lsRaw.toArray(); 50 | } 51 | 52 | @Override 53 | public T[] toArray(T[] a) { 54 | // TODO Auto-generated method stub 55 | return _lsRaw.toArray(a); 56 | } 57 | 58 | @Override 59 | public boolean add(T e) { 60 | // TODO Auto-generated method stub 61 | return _lsRaw.add(e); 62 | } 63 | 64 | @Override 65 | public boolean remove(Object o) { 66 | // TODO Auto-generated method stub 67 | return _lsRaw.remove(o); 68 | } 69 | 70 | @Override 71 | public boolean containsAll(Collection c) { 72 | // TODO Auto-generated method stub 73 | return _lsRaw.containsAll(c); 74 | } 75 | 76 | @Override 77 | public boolean addAll(Collection c) { 78 | // TODO Auto-generated method stub 79 | return _lsRaw.addAll(c); 80 | } 81 | 82 | @Override 83 | public boolean addAll(int index, Collection c) { 84 | // TODO Auto-generated method stub 85 | return _lsRaw.addAll(index, c); 86 | } 87 | 88 | @Override 89 | public boolean removeAll(Collection c) { 90 | // TODO Auto-generated method stub 91 | return _lsRaw.removeAll(c); 92 | } 93 | 94 | @Override 95 | public boolean retainAll(Collection c) { 96 | // TODO Auto-generated method stub 97 | return _lsRaw.retainAll(c); 98 | } 99 | 100 | @Override 101 | public void clear() { 102 | _lsRaw.clear(); 103 | } 104 | 105 | @Override 106 | public T get(int index) { 107 | // TODO Auto-generated method stub 108 | return _lsRaw.get(index); 109 | } 110 | 111 | @Override 112 | public T set(int index, T element) { 113 | // TODO Auto-generated method stub 114 | return _lsRaw.set(index, element); 115 | } 116 | 117 | @Override 118 | public void add(int index, T element) { 119 | // TODO Auto-generated method stub 120 | _lsRaw.add(index, element); 121 | } 122 | 123 | @Override 124 | public T remove(int index) { 125 | // TODO Auto-generated method stub 126 | return _lsRaw.remove(index); 127 | } 128 | 129 | @Override 130 | public int indexOf(Object o) { 131 | // TODO Auto-generated method stub 132 | return _lsRaw.indexOf(o); 133 | } 134 | 135 | @Override 136 | public int lastIndexOf(Object o) { 137 | // TODO Auto-generated method stub 138 | return _lsRaw.lastIndexOf(o); 139 | } 140 | 141 | @Override 142 | public ListIterator listIterator() { 143 | // TODO Auto-generated method stub 144 | return _lsRaw.listIterator(); 145 | } 146 | 147 | @Override 148 | public ListIterator listIterator(int index) { 149 | // TODO Auto-generated method stub 150 | return _lsRaw.listIterator(index); 151 | } 152 | 153 | @Override 154 | public List subList(int fromIndex, int toIndex) { 155 | // TODO Auto-generated method stub 156 | return _lsRaw.subList(fromIndex, toIndex); 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFHttpSyncHandler.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.concurrent.CountDownLatch; 5 | import java.util.concurrent.locks.Condition; 6 | import java.util.concurrent.locks.ReentrantLock; 7 | 8 | import fun.lib.actor.api.http.DFHttpCliRsp; 9 | import fun.lib.actor.api.http.DFHttpContentType; 10 | import io.netty.buffer.ByteBuf; 11 | import io.netty.channel.ChannelHandlerContext; 12 | import io.netty.channel.ChannelInboundHandlerAdapter; 13 | import io.netty.channel.ChannelPromise; 14 | import io.netty.handler.codec.http.FullHttpResponse; 15 | import io.netty.handler.codec.http.HttpHeaderNames; 16 | import io.netty.handler.codec.http.HttpHeaders; 17 | import io.netty.handler.codec.http.HttpUtil; 18 | import io.netty.util.CharsetUtil; 19 | import io.netty.util.ReferenceCountUtil; 20 | 21 | public final class DFHttpSyncHandler extends ChannelInboundHandlerAdapter{ 22 | 23 | private volatile ChannelHandlerContext _ctx = null; 24 | private final CountDownLatch _cdActive; 25 | protected DFHttpSyncHandler(CountDownLatch cdActive) { 26 | _cdActive = cdActive; 27 | } 28 | 29 | @Override 30 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 31 | _ctx = ctx; 32 | super.channelActive(ctx); 33 | _cdActive.countDown(); 34 | } 35 | 36 | @Override 37 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 38 | _ctx = null; 39 | super.channelInactive(ctx); 40 | } 41 | 42 | @Override 43 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 44 | try{ 45 | if(msg instanceof FullHttpResponse){ 46 | FullHttpResponse rsp = (FullHttpResponse) msg; 47 | HttpHeaders headers = rsp.headers(); 48 | long contentLen = HttpUtil.getContentLength(rsp); 49 | String contentType = headers.get(HttpHeaderNames.CONTENT_TYPE); 50 | // 51 | DFHttpCliRsp dfRsp = null; 52 | ByteBuf buf = rsp.content(); 53 | //parse msg 54 | boolean isString = contentIsString(contentType); 55 | if(isString){ //String 56 | String str = null; 57 | if(buf != null){ 58 | str = (String) buf.readCharSequence(buf.readableBytes(), CharsetUtil.UTF_8); 59 | } 60 | dfRsp = new DFHttpCliRspWrap(rsp.status().code(), headers, 61 | contentType, (int) contentLen, 62 | null, str); 63 | }else{ //binary 64 | dfRsp = new DFHttpCliRspWrap(rsp.status().code(), headers, 65 | contentType, (int) contentLen, 66 | buf, null); 67 | } 68 | // 69 | _recvData = dfRsp; 70 | if(!isString && buf != null){ 71 | buf.retain(); 72 | } 73 | } 74 | }finally{ 75 | if(_recvPromise != null){ 76 | _recvPromise.setSuccess(); 77 | } 78 | ReferenceCountUtil.release(msg); 79 | } 80 | } 81 | 82 | private volatile Object _recvData = null; 83 | protected Object getRecvData(){ 84 | return _recvData; 85 | } 86 | protected void release(){ 87 | if(_recvData != null){ 88 | DFHttpCliRspWrap wrap = (DFHttpCliRspWrap) _recvData; 89 | wrap.release(); 90 | _recvData = null; 91 | } 92 | } 93 | private volatile ChannelPromise _recvPromise = null; 94 | protected ChannelPromise sendMsg(Object msg){ 95 | if(_ctx != null){ 96 | _recvPromise = _ctx.writeAndFlush(msg).channel().newPromise(); 97 | } 98 | return _recvPromise; 99 | } 100 | protected ChannelHandlerContext getContext(){ 101 | return _ctx; 102 | } 103 | private boolean contentIsString(String contentType){ 104 | if(contentType != null && 105 | ( 106 | contentType.equals(DFHttpContentType.TEXT_HTML) 107 | ||contentType.equals(DFHttpContentType.JSON) 108 | || contentType.equals(DFHttpContentType.XML) 109 | || contentType.equals(DFHttpContentType.TEXT_PLAIN) 110 | )){ 111 | 112 | return true; 113 | } 114 | return false; 115 | } 116 | 117 | @Override 118 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 119 | cause.printStackTrace(); 120 | ctx.close(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFRedisManager.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.util.HashMap; 4 | import java.util.Iterator; 5 | import java.util.concurrent.locks.ReentrantReadWriteLock; 6 | import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; 7 | import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; 8 | import com.funtag.util.cache.DFRedisUtil; 9 | import fun.lib.actor.po.DFRedisCfg; 10 | import redis.clients.jedis.Jedis; 11 | import redis.clients.jedis.JedisPool; 12 | 13 | public final class DFRedisManager { 14 | protected DFRedisManager() { 15 | // TODO Auto-generated constructor stub 16 | } 17 | 18 | private final ReentrantReadWriteLock lockRedis = new ReentrantReadWriteLock(); 19 | private final ReadLock lockRedisRead = lockRedis.readLock(); 20 | private final WriteLock lockRedisWrite = lockRedis.writeLock(); 21 | private final HashMap mapRedis = new HashMap<>(); 22 | private final HashMap mapRedisId = new HashMap<>(); 23 | 24 | private int redisIdCount = 1; 25 | protected int initPool(DFRedisCfg cfg) throws Throwable{ 26 | lockRedisRead.lock(); 27 | try{ 28 | Integer existId = mapRedisId.get(cfg.strId); 29 | if(existId != null){ //pool exist 30 | return existId; 31 | } 32 | }finally{ 33 | lockRedisRead.unlock(); 34 | } 35 | // 36 | JedisPool pool = DFRedisUtil.createJedisPool( 37 | cfg.getHost(), cfg.getPort(), cfg.getAuth(), 38 | cfg.getMaxTotal(), cfg.getMaxIdle(), cfg.getMinIdle(), 39 | cfg.getConnTimeoutMilli(), cfg.getBorrowTimeoutMilli()); 40 | //test connection 41 | boolean testFail = false; 42 | Jedis conn = null; 43 | Throwable eOut = null; 44 | try{ 45 | conn = pool.getResource(); 46 | conn.ping(); 47 | }catch(Throwable e){ 48 | testFail = true; 49 | eOut = e; 50 | }finally{ 51 | if(conn != null){ 52 | conn.close(); 53 | } 54 | if(testFail && pool != null){ 55 | pool.close(); 56 | } 57 | } 58 | if(eOut != null){ 59 | throw eOut; 60 | } 61 | // 62 | RedisPoolWrap wrap = new RedisPoolWrap(pool, cfg.strId); 63 | lockRedisWrite.lock(); 64 | try{ 65 | int curId = redisIdCount; 66 | mapRedis.put(curId, wrap); 67 | mapRedisId.put(cfg.strId, curId); 68 | if(redisIdCount >= Integer.MAX_VALUE){ 69 | redisIdCount = 1; 70 | }else{ 71 | ++redisIdCount; 72 | } 73 | return curId; 74 | }finally{ 75 | lockRedisWrite.unlock(); 76 | } 77 | } 78 | protected Jedis getConn(int id){ 79 | Jedis j = null; 80 | lockRedisRead.lock(); 81 | try{ 82 | final RedisPoolWrap pool = mapRedis.get(id); 83 | if(pool != null){ 84 | j = pool.getConn(); 85 | } 86 | }catch(Throwable e){ 87 | e.printStackTrace(); 88 | } 89 | finally{ 90 | lockRedisRead.unlock(); 91 | } 92 | return j; 93 | } 94 | protected void closePool(int id){ 95 | RedisPoolWrap wrap = null; 96 | lockRedisWrite.lock(); 97 | try{ 98 | wrap = mapRedis.remove(id); 99 | if(wrap != null){ 100 | mapRedisId.remove(wrap.strId); 101 | } 102 | }finally{ 103 | lockRedisWrite.unlock(); 104 | } 105 | if(wrap != null){ 106 | wrap.close(); 107 | } 108 | } 109 | protected void closeAllPool(){ 110 | lockRedisWrite.lock(); 111 | try{ 112 | Iterator it = mapRedis.values().iterator(); 113 | while(it.hasNext()){ 114 | RedisPoolWrap wrap = it.next(); 115 | wrap.close(); 116 | } 117 | mapRedis.clear(); 118 | mapRedisId.clear(); 119 | }finally{ 120 | lockRedisWrite.unlock(); 121 | } 122 | } 123 | 124 | class RedisPoolWrap{ 125 | private JedisPool pool = null; 126 | private final String strId; 127 | public RedisPoolWrap(JedisPool p, String strId) { 128 | pool = p; 129 | this.strId = strId; 130 | } 131 | private Jedis getConn(){ 132 | Jedis j = null; 133 | if(pool != null){ 134 | try{ 135 | j = pool.getResource(); 136 | }catch(Throwable e){ 137 | throw e; 138 | } 139 | } 140 | return j; 141 | } 142 | private void close(){ 143 | if(pool != null){ 144 | pool.close(); 145 | pool = null; 146 | } 147 | } 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFTcpClientCfg.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | import fun.lib.actor.api.DFActorTcpDispatcher; 4 | import fun.lib.actor.api.DFTcpDecoder; 5 | import fun.lib.actor.api.DFTcpEncoder; 6 | import fun.lib.actor.core.DFActorDefine; 7 | 8 | public final class DFTcpClientCfg { 9 | public final String host; 10 | public final int port; 11 | // 12 | private volatile int soRecvBufLen = 4096; 13 | private volatile int soSendBufLen = 4096; 14 | private volatile boolean tcpNoDelay = true; 15 | private volatile boolean keepAlive = true; 16 | private volatile long _connTimeout = 5000; 17 | 18 | private volatile int tcpProtocol = DFActorDefine.TCP_DECODE_RAW; 19 | private volatile int tcpMsgMaxLength = 1024*64; 20 | 21 | private volatile DFTcpDecoder decoder = null; 22 | private volatile DFTcpEncoder encoder = null; 23 | // 24 | private volatile Object userHandler = null; 25 | private volatile DFSSLConfig sslCfg = null; 26 | 27 | private volatile Object reqData = null; 28 | private volatile String wsUri = null; 29 | /** 30 | * 31 | * @param host 目标主机地址 32 | * @param port 目标端口 33 | */ 34 | public DFTcpClientCfg(String host, int port) { 35 | this.host = host; 36 | this.port = port; 37 | } 38 | 39 | public long getConnTimeout(){ 40 | return _connTimeout; 41 | } 42 | public DFTcpClientCfg setConnTimeout(long timeoutMilli){ 43 | _connTimeout = timeoutMilli; 44 | return this; 45 | } 46 | 47 | // 48 | public int getSoRecvBufLen(){ 49 | return soRecvBufLen; 50 | } 51 | public DFTcpClientCfg setSoRecvBufLen(int len){ 52 | this.soRecvBufLen = len; 53 | return this; 54 | } 55 | public int getSoSendBufLen(){ 56 | return soSendBufLen; 57 | } 58 | public DFTcpClientCfg setSoSendBufLen(int len){ 59 | this.soSendBufLen = len; 60 | return this; 61 | } 62 | 63 | public boolean isTcpNoDelay(){ 64 | return tcpNoDelay; 65 | } 66 | public DFTcpClientCfg setTcpNoDelay(boolean tcpNoDelay){ 67 | this.tcpNoDelay = tcpNoDelay; 68 | return this; 69 | } 70 | public boolean isKeepAlive(){ 71 | return keepAlive; 72 | } 73 | public DFTcpClientCfg setKeepAlive(boolean keepAlive){ 74 | this.keepAlive = keepAlive; 75 | return this; 76 | } 77 | 78 | public Object getReqData() { 79 | return reqData; 80 | } 81 | 82 | public DFTcpClientCfg setReqData(Object reqData) { 83 | this.reqData = reqData; 84 | return this; 85 | } 86 | 87 | public int getTcpProtocol(){ 88 | return tcpProtocol; 89 | } 90 | public DFTcpClientCfg setTcpProtocol(int tcpProtocol){ 91 | if(tcpProtocol == DFActorDefine.TCP_DECODE_LENGTH 92 | || tcpProtocol == DFActorDefine.TCP_DECODE_RAW 93 | || tcpProtocol == DFActorDefine.TCP_DECODE_HTTP 94 | || tcpProtocol == DFActorDefine.TCP_DECODE_WEBSOCKET 95 | ){ //valid 96 | 97 | }else{ //invalid 98 | tcpProtocol = DFActorDefine.TCP_DECODE_RAW; 99 | } 100 | this.tcpProtocol = tcpProtocol; 101 | return this; 102 | } 103 | public int getTcpMsgMaxLength(){ 104 | return tcpMsgMaxLength; 105 | } 106 | public DFTcpClientCfg setTcpMsgMaxLength(int maxLength){ 107 | this.tcpMsgMaxLength = maxLength; 108 | return this; 109 | } 110 | 111 | public DFTcpDecoder getDecoder() { 112 | return decoder; 113 | } 114 | public DFTcpClientCfg setDecoder(DFTcpDecoder decoder) { 115 | this.decoder = decoder; 116 | return this; 117 | } 118 | 119 | public DFTcpEncoder getEncoder() { 120 | return encoder; 121 | } 122 | 123 | public DFTcpClientCfg setEncoder(DFTcpEncoder encoder) { 124 | this.encoder = encoder; 125 | return this; 126 | } 127 | 128 | public DFTcpClientCfg setWsUri(String uri){ 129 | this.wsUri = uri; 130 | return this; 131 | } 132 | public String getWsUri(){ 133 | return this.wsUri; 134 | } 135 | 136 | public Object getUserHandler() { 137 | return userHandler; 138 | } 139 | 140 | public DFTcpClientCfg setUserHandler(Object userHandler) { 141 | this.userHandler = userHandler; 142 | return this; 143 | } 144 | 145 | public DFSSLConfig getSslCfg() { 146 | return sslCfg; 147 | } 148 | 149 | public DFTcpClientCfg setSslCfg(DFSSLConfig sslCfg) { 150 | this.sslCfg = sslCfg; 151 | return this; 152 | } 153 | 154 | // 155 | public static DFTcpClientCfg newCfg(String host, int port){ 156 | return new DFTcpClientCfg(host, port); 157 | } 158 | } 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFMysqlManager.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | import java.sql.Statement; 6 | import java.util.HashMap; 7 | import java.util.Iterator; 8 | import java.util.LinkedList; 9 | import java.util.concurrent.locks.ReentrantReadWriteLock; 10 | import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; 11 | import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; 12 | import org.apache.tomcat.jdbc.pool.DataSource; 13 | 14 | import com.funtag.util.db.DFDbUtil; 15 | 16 | import fun.lib.actor.po.DFDbCfg; 17 | 18 | public final class DFMysqlManager { 19 | 20 | protected DFMysqlManager() { 21 | // TODO Auto-generated constructor stub 22 | } 23 | 24 | private final ReentrantReadWriteLock lockDb = new ReentrantReadWriteLock(); 25 | private final ReadLock lockDbRead = lockDb.readLock(); 26 | private final WriteLock lockDbWrite = lockDb.writeLock(); 27 | private final HashMap mapDb = new HashMap<>(); 28 | private final HashMap mapDbId = new HashMap<>(); 29 | 30 | private int idCount = 1; 31 | 32 | protected int initPool(DFDbCfg cfg) throws Throwable{ 33 | lockDbRead.lock(); 34 | try{ 35 | Integer idExist = mapDbId.get(cfg.strId); 36 | if(idExist != null){ //exist 37 | return idExist; 38 | } 39 | }finally{ 40 | lockDbRead.unlock(); 41 | } 42 | // 43 | DataSource dbSrc = DFDbUtil.createMysqlDbSource(cfg.getUrl(), cfg.getUser(), cfg.getPwd(), 44 | cfg.getInitSize(), cfg.getMaxActive(), cfg.getMaxWait(), cfg.getMaxIdle(), cfg.getMinIdle()); 45 | //conn test 46 | boolean testFail = false; 47 | Connection conn = null; 48 | Throwable eOut = null; 49 | try{ 50 | conn = dbSrc.getConnection(); 51 | Statement stmt = conn.createStatement(); 52 | stmt.executeQuery("select 1"); 53 | }catch(Throwable e){ 54 | testFail = true; 55 | eOut = e; 56 | }finally{ 57 | if(conn != null){ 58 | conn.close(); 59 | } 60 | if(testFail){ 61 | if(dbSrc != null){ 62 | dbSrc.close(); dbSrc = null; 63 | } 64 | } 65 | } 66 | if(eOut != null){ 67 | throw eOut; 68 | } 69 | // 70 | DbPoolWrap wrap = new DbPoolWrap(dbSrc, cfg.strId); 71 | lockDbWrite.lock(); 72 | try{ 73 | int curId = idCount; 74 | mapDb.put(curId, wrap); 75 | mapDbId.put(cfg.strId, curId); 76 | if(idCount >= Integer.MAX_VALUE){ 77 | idCount = 1; 78 | }else{ 79 | ++idCount; 80 | } 81 | return curId; 82 | }finally{ 83 | lockDbWrite.unlock(); 84 | } 85 | } 86 | protected Connection getConn(int id) throws SQLException{ 87 | Connection conn = null; 88 | lockDbRead.lock(); 89 | try{ 90 | final DbPoolWrap wrap = mapDb.get(id); 91 | if(wrap != null){ 92 | conn = wrap.getConn(); 93 | } 94 | }finally{ 95 | lockDbRead.unlock(); 96 | } 97 | return conn; 98 | } 99 | protected void closePool(int id){ 100 | DbPoolWrap wrap = null; 101 | lockDbWrite.lock(); 102 | try{ 103 | wrap = mapDb.remove(id); 104 | if(wrap != null){ 105 | mapDbId.remove(wrap.strId); 106 | } 107 | }finally{ 108 | lockDbWrite.unlock(); 109 | } 110 | if(wrap != null){ 111 | wrap.close(); 112 | } 113 | } 114 | protected void closeAllPool(){ 115 | LinkedList lsTmp = new LinkedList<>(); 116 | lockDbWrite.lock(); 117 | try{ 118 | Iterator it = mapDb.values().iterator(); 119 | while(it.hasNext()){ 120 | lsTmp.offer(it.next()); 121 | } 122 | mapDb.clear(); 123 | mapDbId.clear(); 124 | }finally{ 125 | lockDbWrite.unlock(); 126 | } 127 | // 128 | Iterator it = lsTmp.iterator(); 129 | while(it.hasNext()){ 130 | it.next().close(); 131 | it.remove(); 132 | } 133 | } 134 | 135 | class DbPoolWrap{ 136 | private DataSource dbSrc = null; 137 | private final String strId; 138 | private DbPoolWrap(DataSource src,String strId) { 139 | dbSrc = src; 140 | this.strId = strId; 141 | } 142 | private Connection getConn() throws SQLException{ 143 | Connection conn = null; 144 | if(dbSrc != null){ 145 | try { 146 | return dbSrc.getConnection(); 147 | } catch (SQLException e) { 148 | throw e; 149 | } 150 | } 151 | return conn; 152 | } 153 | private void close(){ 154 | if(dbSrc != null){ 155 | dbSrc.close(); 156 | dbSrc = null; 157 | } 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFActorManagerConfig.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | import fun.lib.actor.core.DFActorDefine; 4 | import fun.lib.actor.helper.DFActorLogLevel; 5 | 6 | public final class DFActorManagerConfig { 7 | 8 | private volatile int logicWorkerThreadNum = Math.max(2, Runtime.getRuntime().availableProcessors()); 9 | private volatile int logicWorkerThreadNumMax = logicWorkerThreadNum; 10 | private volatile int logicQueueWait = 10; 11 | 12 | private volatile int logLevel = DFActorLogLevel.DEBUG; 13 | private volatile int timerThreadNum = 1; 14 | private volatile int clientIoThreadNum = 1; 15 | 16 | private volatile int blockWorkerThreadNum = 1; 17 | private volatile int blockWorkerThreadNumMax = blockWorkerThreadNum; 18 | private volatile int blockQueueWait = 10; 19 | 20 | private volatile boolean useSysLog = true; 21 | private volatile int sysLogConsumeType = DFActorDefine.CONSUME_AUTO; 22 | 23 | private volatile int timerTickPerWheel = 10000; 24 | 25 | private volatile DFActorClusterConfig clusterCfg = null; 26 | 27 | public DFActorManagerConfig() { 28 | // TODO Auto-generated constructor stub 29 | } 30 | 31 | public int getSysLogConsumeType(){ 32 | return sysLogConsumeType; 33 | } 34 | public DFActorManagerConfig setSysLogConsumeType(int consumeType){ 35 | if(consumeType>=DFActorDefine.CONSUME_AUTO && 36 | consumeType<=DFActorDefine.CONSUME_ALL){ 37 | sysLogConsumeType = consumeType; 38 | } 39 | return this; 40 | } 41 | 42 | public int getBlockWorkerThreadNum(){ 43 | return blockWorkerThreadNum; 44 | } 45 | public int getBlockWorkerThreadNumMax(){ 46 | return blockWorkerThreadNumMax; 47 | } 48 | public int getBlockQueueWait(){ 49 | return this.blockQueueWait; 50 | } 51 | public DFActorManagerConfig setBlockWorkerThreadNum(int blockWorkerThreadNum){ 52 | this.blockWorkerThreadNum = blockWorkerThreadNum; 53 | this.blockWorkerThreadNumMax = this.blockWorkerThreadNum; 54 | return this; 55 | } 56 | public DFActorManagerConfig setBlockWorkerThreadNumMax(int blockWorkerThreadNumMax){ 57 | this.blockWorkerThreadNumMax = blockWorkerThreadNumMax; 58 | return this; 59 | } 60 | public DFActorManagerConfig setBlockQueueWait(int queueWait){ 61 | this.blockQueueWait = Math.max(0, queueWait); 62 | return this; 63 | } 64 | 65 | public int getClientIoThreadNum(){ 66 | return clientIoThreadNum; 67 | } 68 | public DFActorManagerConfig setClientIoThreadNum(int clientIoThreadNum){ 69 | this.clientIoThreadNum = clientIoThreadNum; 70 | return this; 71 | } 72 | 73 | public int getTimerThreadNum(){ 74 | return timerThreadNum; 75 | } 76 | public DFActorManagerConfig setTimerThreadNum(int timerThreadNum){ 77 | this.timerThreadNum = timerThreadNum; 78 | return this; 79 | } 80 | 81 | public int getLogicWorkerThreadNum() { 82 | return logicWorkerThreadNum; 83 | } 84 | public int getLogicWorkerThreadNumMax() { 85 | return logicWorkerThreadNumMax; 86 | } 87 | public int getLogicQueueWait(){ 88 | return this.logicQueueWait; 89 | } 90 | public DFActorManagerConfig setLogicWorkerThreadNum(int logicWorkerThreadNum) { 91 | this.logicWorkerThreadNum = logicWorkerThreadNum; 92 | this.logicWorkerThreadNumMax = this.logicWorkerThreadNum; 93 | return this; 94 | } 95 | public DFActorManagerConfig setLogicWorkerThreadNumMax(int logicWorkerThreadNumMax) { 96 | this.logicWorkerThreadNumMax = logicWorkerThreadNumMax; 97 | return this; 98 | } 99 | public DFActorManagerConfig setLogicQueueWait(int queueWait) { 100 | this.logicQueueWait = Math.max(0, queueWait); 101 | return this; 102 | } 103 | 104 | 105 | public boolean isUseSysLog() { 106 | return useSysLog; 107 | } 108 | public DFActorManagerConfig setUseSysLog(boolean useSysLog) { 109 | this.useSysLog = useSysLog; 110 | return this; 111 | } 112 | 113 | 114 | public int getTimerTickPerWheel() { 115 | return timerTickPerWheel; 116 | } 117 | 118 | public DFActorManagerConfig setTimerTickPerWheel(int timerTickPerWheel) { 119 | this.timerTickPerWheel = timerTickPerWheel; 120 | return this; 121 | } 122 | 123 | public int getLogLevel() { 124 | return logLevel; 125 | } 126 | public DFActorManagerConfig setLogLevel(int logLevel) { 127 | this.logLevel = logLevel; 128 | return this; 129 | } 130 | 131 | public DFActorClusterConfig getClusterConfig(){ 132 | return clusterCfg; 133 | } 134 | public DFActorManagerConfig setClusterConfig(DFActorClusterConfig cfg){ 135 | this.clusterCfg = cfg; 136 | return this; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFHttpSvrRspWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | import com.alibaba.fastjson.JSONObject; 6 | 7 | import fun.lib.actor.api.DFTcpChannel; 8 | import fun.lib.actor.api.http.DFHttpContentType; 9 | import fun.lib.actor.api.http.DFHttpHeader; 10 | import fun.lib.actor.api.http.DFHttpSvrRsp; 11 | import io.netty.buffer.ByteBuf; 12 | import io.netty.buffer.Unpooled; 13 | import io.netty.channel.ChannelFutureListener; 14 | import io.netty.handler.codec.http.DefaultHttpResponse; 15 | import io.netty.handler.codec.http.FullHttpResponse; 16 | import io.netty.handler.codec.http.HttpHeaderNames; 17 | import io.netty.handler.codec.http.HttpHeaderValues; 18 | import io.netty.handler.codec.http.HttpResponse; 19 | import io.netty.handler.codec.http.HttpResponseStatus; 20 | import io.netty.handler.codec.http.HttpStatusClass; 21 | import io.netty.handler.codec.http.HttpVersion; 22 | import io.netty.handler.codec.http.LastHttpContent; 23 | 24 | public final class DFHttpSvrRspWrap implements DFHttpSvrRsp{ 25 | 26 | private volatile boolean hasSend = false; 27 | private HttpResponse response = null; 28 | private final DFTcpChannel channel; 29 | private ByteBuf _bufContent = null; 30 | 31 | protected DFHttpSvrRspWrap(DFTcpChannel channel, int statusCode) { 32 | this.channel = channel; 33 | response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(statusCode)); 34 | } 35 | protected DFHttpSvrRspWrap(int statusCode) { 36 | this(null, statusCode); 37 | } 38 | 39 | protected DFHttpSvrRspWrap(DFTcpChannel channel, String strData){ 40 | this(channel, 200, strData); 41 | contentType(DFHttpContentType.TEXT_PLAIN); //default is text 42 | } 43 | protected DFHttpSvrRspWrap(String strData){ 44 | this(null, 200, strData); 45 | contentType(DFHttpContentType.TEXT_PLAIN); //default is text 46 | } 47 | protected DFHttpSvrRspWrap(DFTcpChannel channel, JSONObject json){ 48 | this(channel, 200, json); 49 | } 50 | protected DFHttpSvrRspWrap(JSONObject json){ 51 | this(null, 200, json); 52 | } 53 | protected DFHttpSvrRspWrap(DFTcpChannel channel, int statusCode, JSONObject json){ 54 | this(channel, statusCode, json.toJSONString()); 55 | contentType(DFHttpContentType.JSON); 56 | } 57 | protected DFHttpSvrRspWrap(int statusCode, JSONObject json){ 58 | this(null, statusCode, json.toJSONString()); 59 | contentType(DFHttpContentType.JSON); 60 | } 61 | protected DFHttpSvrRspWrap(DFTcpChannel channel, int statusCode, String strData){ 62 | this.channel = channel; 63 | try { 64 | byte[] arrBuf = strData.getBytes("utf-8"); 65 | _bufContent = Unpooled.wrappedBuffer(arrBuf); 66 | response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(statusCode)); 67 | if(statusCode == 500){ 68 | contentType("text/html;charset=utf-8"); 69 | } 70 | } catch (UnsupportedEncodingException e) { 71 | e.printStackTrace(); 72 | } 73 | } 74 | 75 | protected DFHttpSvrRspWrap(DFTcpChannel channel, ByteBuf buf){ 76 | this(channel, 200, buf); 77 | } 78 | protected DFHttpSvrRspWrap(DFTcpChannel channel, int statusCode, ByteBuf buf){ 79 | this.channel = channel; 80 | response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf(statusCode)); 81 | contentType(DFHttpContentType.OCTET_STREAM); 82 | _bufContent = buf; 83 | } 84 | 85 | // 86 | @Override 87 | public DFHttpSvrRsp header(String key, String val){ 88 | response.headers().set(key, val); 89 | return this; 90 | } 91 | @Override 92 | public DFHttpSvrRsp contentType(String contentType){ 93 | header(HttpHeaderNames.CONTENT_TYPE.toString(), contentType); 94 | return this; 95 | } 96 | @Override 97 | public DFHttpSvrRsp userAgent(String userAgent){ 98 | header(HttpHeaderNames.USER_AGENT.toString(), userAgent); 99 | return this; 100 | } 101 | @Override 102 | public void send(){ 103 | if(hasSend){ 104 | return ; 105 | } 106 | hasSend = true; 107 | if(channel != null){ 108 | DFTcpChannelWrap chWrap = (DFTcpChannelWrap) channel; 109 | chWrap.writeNoFlush(this); 110 | if(_bufContent != null){ 111 | response.headers().add(HttpHeaderNames.CONTENT_LENGTH, _bufContent.readableBytes()); 112 | chWrap.writeNoFlush(_bufContent); 113 | } 114 | channel.write(LastHttpContent.EMPTY_LAST_CONTENT); 115 | } 116 | } 117 | 118 | protected boolean hasSend(){ 119 | return this.hasSend; 120 | } 121 | 122 | // 123 | protected HttpResponse getRawResponse(){ 124 | return response; 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/po/DFTcpServerCfg.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.po; 2 | 3 | import fun.lib.actor.api.DFTcpDecoder; 4 | import fun.lib.actor.api.DFTcpEncoder; 5 | import fun.lib.actor.core.DFActorDefine; 6 | import io.netty.channel.EventLoopGroup; 7 | 8 | public final class DFTcpServerCfg { 9 | public final int port; 10 | public final int workerThreadNum; 11 | public final int bossThreadNum; 12 | public final EventLoopGroup ioGroup; 13 | // 14 | private volatile int soRecvBufLen = 2048; 15 | private volatile int soSendBufLen = 2048; 16 | private volatile boolean tcpNoDelay = true; 17 | private volatile boolean keepAlive = true; 18 | private volatile int soBackLog = 1024; 19 | 20 | private volatile int tcpProtocol = DFActorDefine.TCP_DECODE_RAW; 21 | private volatile int tcpMsgMaxLength = 1024*64; 22 | 23 | private volatile String wsUri = ""; 24 | 25 | private volatile DFTcpDecoder decoder = null; 26 | private volatile DFTcpEncoder encoder = null; 27 | 28 | private volatile Object userHandler = null; 29 | 30 | private volatile DFSSLConfig sslConfig = null; 31 | /** 32 | * 33 | * @param port 监听端口 34 | * @param workerThreadNum 通信层处理消息的线程数 35 | * @param bossThreadNum 通信层处理连接的线程数 36 | */ 37 | public DFTcpServerCfg(int port, int workerThreadNum, int bossThreadNum) { 38 | this.port = port; 39 | if(workerThreadNum < 1){ 40 | workerThreadNum = 1; 41 | } 42 | this.workerThreadNum = workerThreadNum; 43 | this.bossThreadNum = bossThreadNum; 44 | ioGroup = null; 45 | } 46 | public DFTcpServerCfg(int port) { 47 | this(port, Math.min(4, Runtime.getRuntime().availableProcessors()), 1); 48 | } 49 | public DFTcpServerCfg(int port, EventLoopGroup ioGroup){ 50 | this.port = port; 51 | this.ioGroup = ioGroup; 52 | this.workerThreadNum = 0; 53 | this.bossThreadNum = 0; 54 | } 55 | 56 | public String getWsUri(){ 57 | return wsUri; 58 | } 59 | public DFTcpServerCfg setWsUri(String wsUri){ 60 | this.wsUri = wsUri; 61 | return this; 62 | } 63 | // 64 | public int getSoRecvBufLen(){ 65 | return soRecvBufLen; 66 | } 67 | public DFTcpServerCfg setSoRecvBufLen(int len){ 68 | this.soRecvBufLen = len; 69 | return this; 70 | } 71 | public int getSoSendBufLen(){ 72 | return soSendBufLen; 73 | } 74 | public DFTcpServerCfg setSoSendBufLen(int len){ 75 | this.soSendBufLen = len; 76 | return this; 77 | } 78 | public int getSoBackLog(){ 79 | return soBackLog; 80 | } 81 | public DFTcpServerCfg setSoBackLog(int backLog){ 82 | this.soBackLog = backLog; 83 | return this; 84 | } 85 | 86 | public boolean isTcpNoDelay(){ 87 | return tcpNoDelay; 88 | } 89 | public DFTcpServerCfg setTcpNoDelay(boolean tcpNoDelay){ 90 | this.tcpNoDelay = tcpNoDelay; 91 | return this; 92 | } 93 | public boolean isKeepAlive(){ 94 | return keepAlive; 95 | } 96 | public DFTcpServerCfg setKeepAlive(boolean keepAlive){ 97 | this.keepAlive = keepAlive; 98 | return this; 99 | } 100 | 101 | public int getTcpProtocol(){ 102 | return tcpProtocol; 103 | } 104 | public DFTcpServerCfg setTcpProtocol(int tcpProtocol){ 105 | if(tcpProtocol == DFActorDefine.TCP_DECODE_LENGTH 106 | ||tcpProtocol == DFActorDefine.TCP_DECODE_RAW 107 | ||tcpProtocol == DFActorDefine.TCP_DECODE_WEBSOCKET 108 | ||tcpProtocol == DFActorDefine.TCP_DECODE_HTTP 109 | ){ //valid 110 | 111 | }else{ //invalid 112 | tcpProtocol = DFActorDefine.TCP_DECODE_RAW; 113 | } 114 | this.tcpProtocol = tcpProtocol; 115 | return this; 116 | } 117 | public int getTcpMsgMaxLength(){ 118 | return tcpMsgMaxLength; 119 | } 120 | public DFTcpServerCfg setTcpMsgMaxLength(int maxLength){ 121 | this.tcpMsgMaxLength = maxLength; 122 | return this; 123 | } 124 | public DFTcpDecoder getDecoder() { 125 | return decoder; 126 | } 127 | public DFTcpServerCfg setDecoder(DFTcpDecoder decoder) { 128 | this.decoder = decoder; 129 | return this; 130 | } 131 | public DFTcpEncoder getEncoder() { 132 | return encoder; 133 | } 134 | public DFTcpServerCfg setEncoder(DFTcpEncoder encoder) { 135 | this.encoder = encoder; 136 | return this; 137 | } 138 | public Object getUserHandler() { 139 | return userHandler; 140 | } 141 | public DFTcpServerCfg setUserHandler(Object userHandler) { 142 | this.userHandler = userHandler; 143 | return this; 144 | } 145 | public DFSSLConfig getSslConfig(){ 146 | return sslConfig; 147 | } 148 | public DFTcpServerCfg setSslConfig(DFSSLConfig cfg) { 149 | this.sslConfig = cfg; 150 | return this; 151 | } 152 | 153 | // 154 | public static DFTcpServerCfg newCfg(int port){ 155 | return new DFTcpServerCfg(port); 156 | } 157 | } 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /src/main/java/fun/lib/actor/core/DFActorNetWrap.java: -------------------------------------------------------------------------------- 1 | package fun.lib.actor.core; 2 | 3 | import java.net.InetAddress; 4 | import java.net.InetSocketAddress; 5 | 6 | import fun.lib.actor.api.DFActorNet; 7 | import fun.lib.actor.api.DFActorTcpDispatcher; 8 | import fun.lib.actor.api.DFActorUdpDispatcher; 9 | import fun.lib.actor.api.cb.CbHttpClient; 10 | import fun.lib.actor.api.cb.CbHttpServer; 11 | import fun.lib.actor.api.http.DFHttpDispatcher; 12 | import fun.lib.actor.po.DFTcpClientCfg; 13 | import fun.lib.actor.po.DFTcpServerCfg; 14 | import fun.lib.actor.po.DFUdpServerCfg; 15 | import io.netty.buffer.ByteBuf; 16 | 17 | public final class DFActorNetWrap implements DFActorNet{ 18 | 19 | private final int id; 20 | private final DFActorManager _mgr; 21 | 22 | public DFActorNetWrap(int id) { 23 | this.id = id; 24 | _mgr = DFActorManager.get(); 25 | } 26 | 27 | //tcp server 28 | @Override 29 | public void tcpSvr(DFTcpServerCfg cfg){ 30 | final DFSocketManager mgr = DFSocketManager.get(); 31 | mgr.doTcpListen(cfg, id, cfg.port); 32 | } 33 | public void tcpSvr(DFTcpServerCfg cfg, Object dispatcher) { 34 | final DFSocketManager mgr = DFSocketManager.get(); 35 | mgr.doTcpListen(cfg, id, dispatcher, cfg.port); 36 | } 37 | @Override 38 | public void tcpSvr(int port) { 39 | DFTcpServerCfg cfg = new DFTcpServerCfg(port) 40 | .setTcpProtocol(DFActorDefine.TCP_DECODE_LENGTH); 41 | final DFSocketManager mgr = DFSocketManager.get(); 42 | mgr.doTcpListen(cfg, id, port); 43 | } 44 | @Override 45 | public void tcpSvr(int port, Object dispatcher) { 46 | DFTcpServerCfg cfg = new DFTcpServerCfg(port) 47 | .setTcpProtocol(DFActorDefine.TCP_DECODE_LENGTH); 48 | final DFSocketManager mgr = DFSocketManager.get(); 49 | mgr.doTcpListen(cfg, id, dispatcher, cfg.port); 50 | } 51 | @Override 52 | public void tcpSvr(int port, int protocol) { 53 | DFTcpServerCfg cfg = new DFTcpServerCfg(port) 54 | .setTcpProtocol(protocol); 55 | final DFSocketManager mgr = DFSocketManager.get(); 56 | mgr.doTcpListen(cfg, id, cfg.port); 57 | } 58 | //http 59 | @Override 60 | public void httpSvr(int port, CbHttpServer handler) { 61 | DFTcpServerCfg cfg = new DFTcpServerCfg(port) 62 | .setTcpProtocol(DFActorDefine.TCP_DECODE_HTTP) 63 | .setUserHandler(handler); 64 | final DFSocketManager mgr = DFSocketManager.get(); 65 | mgr.doTcpListen(cfg, id, port); 66 | } 67 | @Override 68 | public void httpSvr(int port, CbHttpServer handler, DFHttpDispatcher dispatcher) { 69 | DFTcpServerCfg cfg = new DFTcpServerCfg(port) 70 | .setTcpProtocol(DFActorDefine.TCP_DECODE_HTTP) 71 | .setUserHandler(handler); 72 | final DFSocketManager mgr = DFSocketManager.get(); 73 | mgr.doTcpListen(cfg, id, dispatcher, port); 74 | } 75 | @Override 76 | public void httpSvr(DFTcpServerCfg cfg, CbHttpServer handler) { 77 | cfg.setTcpProtocol(DFActorDefine.TCP_DECODE_HTTP) 78 | .setUserHandler(handler); 79 | final DFSocketManager mgr = DFSocketManager.get(); 80 | mgr.doTcpListen(cfg, id, cfg.port); 81 | } 82 | @Override 83 | public void httpSvr(DFTcpServerCfg cfg, CbHttpServer handler, DFHttpDispatcher dispatcher) { 84 | cfg.setTcpProtocol(DFActorDefine.TCP_DECODE_HTTP) 85 | .setUserHandler(handler); 86 | final DFSocketManager mgr = DFSocketManager.get(); 87 | mgr.doTcpListen(cfg, id, dispatcher, cfg.port); 88 | } 89 | 90 | //close tcp server 91 | public final void closeTcpSvr(int port){ 92 | final DFSocketManager mgr = DFSocketManager.get(); 93 | mgr.doTcpListenClose(port); 94 | } 95 | //tcp client 96 | public final int tcpCli(final DFTcpClientCfg cfg, final int requestId){ 97 | return _mgr.doTcpConnect(cfg, id, requestId); 98 | } 99 | public final int tcpCli(final DFTcpClientCfg cfg, final int requestId, final DFActorTcpDispatcher dispatcher){ 100 | return _mgr.doTcpConnect(cfg, id, dispatcher, requestId); 101 | } 102 | //udp server 103 | public final void udpSvr(final DFUdpServerCfg cfg, DFActorUdpDispatcher listener, final int requestId){ 104 | final DFSocketManager mgr = DFSocketManager.get(); 105 | mgr.doUdpListen(cfg, id, listener, requestId); 106 | } 107 | public final void closeUdpSvr(int port){ 108 | final DFSocketManager mgr = DFSocketManager.get(); 109 | mgr.doUdpListenClose(port); 110 | } 111 | //http client 112 | @Override 113 | public void httpCli(DFTcpClientCfg cfg, CbHttpClient handler) { 114 | cfg.setTcpProtocol(DFActorDefine.TCP_DECODE_HTTP) 115 | .setUserHandler(handler); 116 | _mgr.doTcpConnect(cfg, id, 0); 117 | } 118 | 119 | @Override 120 | public int udpCli(ByteBuf buf, InetSocketAddress addr) { 121 | return _mgr.doUdpSend(buf, addr); 122 | } 123 | 124 | 125 | } 126 | --------------------------------------------------------------------------------