mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
feat: akka remote impl
This commit is contained in:
parent
b0b2c24571
commit
676388a988
@ -4,9 +4,13 @@ import akka.actor.ActorRef;
|
|||||||
import akka.actor.ActorSystem;
|
import akka.actor.ActorSystem;
|
||||||
import akka.actor.DeadLetter;
|
import akka.actor.DeadLetter;
|
||||||
import akka.actor.Props;
|
import akka.actor.Props;
|
||||||
|
import akka.routing.RoundRobinPool;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.typesafe.config.Config;
|
import com.typesafe.config.Config;
|
||||||
import com.typesafe.config.ConfigFactory;
|
import com.typesafe.config.ConfigFactory;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import tech.powerjob.common.RemoteConstant;
|
||||||
|
import tech.powerjob.common.serialize.JsonUtils;
|
||||||
import tech.powerjob.remote.framework.actor.ActorInfo;
|
import tech.powerjob.remote.framework.actor.ActorInfo;
|
||||||
import tech.powerjob.remote.framework.actor.HandlerInfo;
|
import tech.powerjob.remote.framework.actor.HandlerInfo;
|
||||||
import tech.powerjob.remote.framework.base.Address;
|
import tech.powerjob.remote.framework.base.Address;
|
||||||
@ -25,6 +29,7 @@ import java.util.Map;
|
|||||||
* @author tjq
|
* @author tjq
|
||||||
* @since 2022/12/31
|
* @since 2022/12/31
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class AkkaCSInitializer implements CSInitializer {
|
public class AkkaCSInitializer implements CSInitializer {
|
||||||
|
|
||||||
private ActorSystem actorSystem;
|
private ActorSystem actorSystem;
|
||||||
@ -50,6 +55,8 @@ public class AkkaCSInitializer implements CSInitializer {
|
|||||||
Config akkaBasicConfig = ConfigFactory.load(AkkaConstant.AKKA_CONFIG);
|
Config akkaBasicConfig = ConfigFactory.load(AkkaConstant.AKKA_CONFIG);
|
||||||
Config akkaFinalConfig = ConfigFactory.parseMap(overrideConfig).withFallback(akkaBasicConfig);
|
Config akkaFinalConfig = ConfigFactory.parseMap(overrideConfig).withFallback(akkaBasicConfig);
|
||||||
|
|
||||||
|
log.info("[PowerJob-AKKA] try to start AKKA System by config: {}", akkaFinalConfig);
|
||||||
|
|
||||||
// 启动时绑定当前的 actorSystemName
|
// 启动时绑定当前的 actorSystemName
|
||||||
String actorSystemName = AkkaConstant.fetchActorSystemName(config.getServerType(), true);
|
String actorSystemName = AkkaConstant.fetchActorSystemName(config.getServerType(), true);
|
||||||
this.actorSystem = ActorSystem.create(actorSystemName, akkaFinalConfig);
|
this.actorSystem = ActorSystem.create(actorSystemName, akkaFinalConfig);
|
||||||
@ -66,7 +73,18 @@ public class AkkaCSInitializer implements CSInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindHandlers(List<ActorInfo> actorInfos) {
|
public void bindHandlers(List<ActorInfo> actorInfos) {
|
||||||
// TODO: 考虑如何优雅绑定(实在不行就暴力绑定到一个 actor 上,反正可以切协议)
|
int cores = Runtime.getRuntime().availableProcessors();
|
||||||
|
actorInfos.forEach(actorInfo -> {
|
||||||
|
String rootPath = actorInfo.getAnno().path();
|
||||||
|
AkkaMappingService.ActorConfig actorConfig = AkkaMappingService.parseActorName(rootPath);
|
||||||
|
|
||||||
|
log.info("[PowerJob-AKKA] start to process actor[path={},config={}]", rootPath, JsonUtils.toJSONString(actorConfig));
|
||||||
|
|
||||||
|
actorSystem.actorOf(AkkaProxyActor.props(actorInfo)
|
||||||
|
.withDispatcher(actorConfig.getDispatcherName())
|
||||||
|
.withRouter(new RoundRobinPool(cores)), actorConfig.getActorName());
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package tech.powerjob.remote.akka;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建 Actor Mapping
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2023/1/7
|
||||||
|
*/
|
||||||
|
public class AkkaMappingService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actor's RootPath -> Akka Actor Name
|
||||||
|
*/
|
||||||
|
private static final Map<String, ActorConfig> RP_2_ACTOR_CFG = Maps.newHashMap();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// TODO: 迁移时写入规则
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String DEFAULT_DISPATCH_NAME = "common-dispatcher";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 actor 的 rootPath 获取 Akka Actor Name,不存在改写则使用当前路径
|
||||||
|
* @param actorRootPath actorRootPath
|
||||||
|
* @return actorName
|
||||||
|
*/
|
||||||
|
public static ActorConfig parseActorName(String actorRootPath) {
|
||||||
|
return RP_2_ACTOR_CFG.getOrDefault(actorRootPath,
|
||||||
|
new ActorConfig()
|
||||||
|
.setActorName(actorRootPath)
|
||||||
|
.setDispatcherName(DEFAULT_DISPATCH_NAME)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public static class ActorConfig {
|
||||||
|
private String actorName;
|
||||||
|
private String dispatcherName;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package tech.powerjob.remote.akka;
|
package tech.powerjob.remote.akka;
|
||||||
|
|
||||||
import akka.actor.AbstractActor;
|
import akka.actor.AbstractActor;
|
||||||
|
import akka.actor.Props;
|
||||||
import akka.japi.pf.ReceiveBuilder;
|
import akka.japi.pf.ReceiveBuilder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import tech.powerjob.common.exception.PowerJobException;
|
import tech.powerjob.common.exception.PowerJobException;
|
||||||
@ -24,6 +25,10 @@ public class AkkaProxyActor extends AbstractActor {
|
|||||||
private final Receive receive;
|
private final Receive receive;
|
||||||
private final ActorInfo actorInfo;
|
private final ActorInfo actorInfo;
|
||||||
|
|
||||||
|
public static Props props(ActorInfo actorInfo) {
|
||||||
|
return Props.create(AkkaProxyActor.class, () -> new AkkaProxyActor(actorInfo));
|
||||||
|
}
|
||||||
|
|
||||||
public AkkaProxyActor(ActorInfo actorInfo) {
|
public AkkaProxyActor(ActorInfo actorInfo) {
|
||||||
this.actorInfo = actorInfo;
|
this.actorInfo = actorInfo;
|
||||||
final ReceiveBuilder receiveBuilder = receiveBuilder();
|
final ReceiveBuilder receiveBuilder = receiveBuilder();
|
||||||
@ -36,7 +41,7 @@ public class AkkaProxyActor extends AbstractActor {
|
|||||||
}
|
}
|
||||||
final Class<?> bindClz = powerSerializeClz.get();
|
final Class<?> bindClz = powerSerializeClz.get();
|
||||||
receiveBuilder.match(bindClz, req -> onReceiveProcessorReportTaskStatusReq(req, handlerInfo));
|
receiveBuilder.match(bindClz, req -> onReceiveProcessorReportTaskStatusReq(req, handlerInfo));
|
||||||
log.info("[PowerJobProxyActor] bind handler[{}] to [{}]", location, bindClz);
|
log.info("[PowerJob-AKKA] bind handler[{}] to [{}]", location, bindClz);
|
||||||
});
|
});
|
||||||
this.receive = receiveBuilder.build();
|
this.receive = receiveBuilder.build();
|
||||||
}
|
}
|
||||||
@ -54,7 +59,7 @@ public class AkkaProxyActor extends AbstractActor {
|
|||||||
getSender().tell(ret, getSelf());
|
getSender().tell(ret, getSelf());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[TaskTrackerProxyActor] process failed!", e);
|
log.error("[PowerJob-AKKA] process failed!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,6 @@ public class AkkaTroubleshootingActor extends AbstractActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onReceiveDeadLetter(DeadLetter dl) {
|
public void onReceiveDeadLetter(DeadLetter dl) {
|
||||||
log.warn("[TroubleshootingActor] receive DeadLetter: {}", dl);
|
log.warn("[PowerJob-AKKA] receive DeadLetter: {}", dl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,4 +109,25 @@ akka {
|
|||||||
# Set to 1 for as fair as possible.
|
# Set to 1 for as fair as possible.
|
||||||
throughput = 5
|
throughput = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##################### default config #####################
|
||||||
|
common-dispatcher {
|
||||||
|
# Dispatcher is the name of the event-based dispatcher
|
||||||
|
type = Dispatcher
|
||||||
|
# What kind of ExecutionService to use
|
||||||
|
executor = "fork-join-executor"
|
||||||
|
# Configuration for the fork join pool
|
||||||
|
fork-join-executor {
|
||||||
|
# Min number of threads to cap factor-based parallelism number to
|
||||||
|
parallelism-min = 2
|
||||||
|
# Parallelism (threads) ... ceil(available processors * factor)
|
||||||
|
parallelism-factor = 4.0
|
||||||
|
# Max number of threads to cap factor-based parallelism number to
|
||||||
|
parallelism-max = 64
|
||||||
|
}
|
||||||
|
# Throughput defines the maximum number of messages to be
|
||||||
|
# processed per actor before the thread jumps to the next actor.
|
||||||
|
# Set to 1 for as fair as possible.
|
||||||
|
throughput = 10
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user