diff --git a/README_zhCN.md b/README_zhCN.md
index aaf56372..3fe70d47 100644
--- a/README_zhCN.md
+++ b/README_zhCN.md
@@ -1,5 +1,9 @@
# [English](./README.md) | 简体中文
+
+祝大家兔年吉祥,新的一年身体健康,万事如意,阖家欢乐,幸福安康!
+
+
@@ -34,8 +38,7 @@ PowerJob(原OhMyScheduler)是全新一代分布式调度与计算框架,
PowerJob 的设计目标为企业级的分布式任务调度平台,即成为公司内部的**任务调度中间件**。整个公司统一部署调度中心 powerjob-server,旗下所有业务线应用只需要依赖 `powerjob-worker` 即可接入调度中心获取任务调度与分布式计算能力。
### 在线试用
-* 试用地址:[try.powerjob.tech](http://try.powerjob.tech/#/welcome?appName=powerjob-agent-test&password=123)
-* [建议先阅读使用教程了解 PowerJob 的概念和基本用法](https://www.yuque.com/powerjob/guidence/trial)
+* [点击查看试用说明和教程](https://www.yuque.com/powerjob/guidence/trial)
### 同类产品对比
| | QuartZ | xxl-job | SchedulerX 2.0 | PowerJob |
diff --git a/docker-compose.yml b/docker-compose.yml
index d12faee8..cdec2914 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,14 +5,12 @@
version: '3'
services:
powerjob-mysql:
- build:
- context: ./others
environment:
MYSQL_ROOT_HOST: "%"
MYSQL_ROOT_PASSWORD: No1Bug2Please3!
restart: always
container_name: powerjob-mysql
- image: powerjob/powerjob-mysql:4.1.1
+ image: powerjob/powerjob-mysql:latest
ports:
- "3307:3306"
volumes:
@@ -21,7 +19,7 @@ services:
powerjob-server:
container_name: powerjob-server
- image: tjqq/powerjob-server:latest
+ image: powerjob/powerjob-server:latest
restart: always
depends_on:
- powerjob-mysql
@@ -36,7 +34,7 @@ services:
powerjob-worker-samples:
container_name: powerjob-worker-samples
- image: tjqq/powerjob-worker-samples:latest
+ image: powerjob/powerjob-worker-samples:latest
restart: always
depends_on:
- powerjob-mysql
diff --git a/others/dev/build_test_env.sh b/others/dev/build_test_env.sh
new file mode 100755
index 00000000..b14f4bb1
--- /dev/null
+++ b/others/dev/build_test_env.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# 构建 PowerJob 测试环境
+
+echo "================== 关闭全部服务 =================="
+docker-compose down
+echo "================== 构建 jar =================="
+cd `dirname $0`/../.. || exit
+# mvn clean package -Pdev -DskipTests -U -e -pl powerjob-server,powerjob-worker-agent -am
+# -U:强制检查snapshot库 -pl:指定需要构建的模块,多模块逗号分割 -am:同时构建依赖模块,一般与pl连用 -Pxxx:指定使用的配置文件
+mvn clean package -Pdev -DskipTests
+echo "================== 拷贝 jar =================="
+/bin/cp -rf powerjob-server/powerjob-server-starter/target/*.jar powerjob-server/docker/powerjob-server.jar
+/bin/cp -rf powerjob-worker-agent/target/*.jar powerjob-worker-agent/powerjob-agent.jar
+ls -l powerjob-server/docker/powerjob-server.jar
+ls -l powerjob-worker-agent/powerjob-agent.jar
+
+cd others/dev
+docker-compose build
+docker-compose up
\ No newline at end of file
diff --git a/others/dev/docker-compose.yml b/others/dev/docker-compose.yml
new file mode 100644
index 00000000..2a6d55e3
--- /dev/null
+++ b/others/dev/docker-compose.yml
@@ -0,0 +1,75 @@
+# 构建 PowerJob 测试环境
+
+version: '3'
+services:
+ powerjob-mysql:
+ build:
+ context: ../
+ environment:
+ MYSQL_ROOT_HOST: "%"
+ MYSQL_ROOT_PASSWORD: No1Bug2Please3!
+ restart: always
+ container_name: powerjob-mysql
+ image: powerjob/powerjob-mysql:test_env
+ ports:
+ - "3309:3306"
+ volumes:
+ - ~/powerjob-data/powerjob-mysql:/var/lib/mysql
+ command: --lower_case_table_names=1
+
+ powerjob-server:
+ build:
+ context: ../../powerjob-server/docker
+ container_name: powerjob-server
+ image: powerjob/powerjob-server:test_env
+ restart: always
+ depends_on:
+ - powerjob-mysql
+ environment:
+ PARAMS: "--spring.profiles.active=product --oms.mongodb.enable=false --spring.datasource.core.jdbc-url=jdbc:mysql://powerjob-mysql:3306/powerjob-daily?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"
+ JVMOPTIONS: "-Xmx1024m"
+ ports:
+ - "7700:7700"
+ - "10086:10086"
+ - "10010:10010"
+ volumes:
+ - ~/powerjob-data/powerjob-server:/root/powerjob/server/
+
+ powerjob-worker-agent:
+ build:
+ context: ../../powerjob-worker-agent
+ container_name: powerjob-worker-agent
+ image: powerjob/powerjob-worker-agent:test_env
+ restart: always
+ depends_on:
+ - powerjob-mysql
+ - powerjob-server
+ ports:
+ - "5002:5005"
+ - "10002:10000"
+ - "27777:27777"
+ volumes:
+ - ~/powerjob-data/powerjob-worker-agent:/root
+ entrypoint:
+ - "sh"
+ - "-c"
+ - "./wait-for-it.sh powerjob-server:7700 --strict -- java -Xmx768m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10000 -Dcom.sun.management.jmxremote.rmi.port=10000 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar /powerjob-agent.jar --app powerjob-worker-samples --server powerjob-server:7700"
+
+ powerjob-worker-agent2:
+ container_name: powerjob-worker-agent2
+ image: powerjob/powerjob-worker-agent:test_env
+ restart: always
+ depends_on:
+ - powerjob-mysql
+ - powerjob-server
+ ports:
+ - "5003:5005"
+ - "10003:10000"
+ - "27778:27777"
+ volumes:
+ - ~/powerjob-data/powerjob-worker-agent2:/root
+ entrypoint:
+ - "sh"
+ - "-c"
+ - "./wait-for-it.sh powerjob-server:7700 --strict -- java -Xmx768m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10000 -Dcom.sun.management.jmxremote.rmi.port=10000 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar /powerjob-agent.jar --app powerjob-worker-samples --server powerjob-server:7700"
+
diff --git a/others/script/build_docker.sh b/others/dev/publish_docker.sh
similarity index 74%
rename from others/script/build_docker.sh
rename to others/dev/publish_docker.sh
index 4149668e..ee295e3d 100755
--- a/others/script/build_docker.sh
+++ b/others/dev/publish_docker.sh
@@ -33,11 +33,19 @@ read -r -p "是否重新构建镜像(y/n):" rebuild
if [ "$rebuild" = "y" ] || [ "$rebuild" = "Y" ]; then
echo "================== 删除旧镜像 =================="
docker rmi -f tjqq/powerjob-server:$version
+ docker rmi -f powerjob/powerjob-server:$version
docker rmi -f tjqq/powerjob-agent:$version
+ docker rmi -f powerjob/powerjob-agent:$version
+ docker rmi -f powerjob/powerjob-mysql:$version
+ docker rmi -f powerjob/powerjob-worker-samples:$version
echo "================== 构建 powerjob-server 镜像 =================="
docker build -t tjqq/powerjob-server:$version powerjob-server/docker/. || exit
echo "================== 构建 powerjob-agent 镜像 =================="
docker build -t tjqq/powerjob-agent:$version powerjob-worker-agent/. || exit
+ echo "================== 构建 powerjob-mysql 镜像 =================="
+ docker build -t powerjob/powerjob-mysql:$version others/. || exit
+ echo "================== 构建 powerjob-worker-samples 镜像 =================="
+ docker build -t powerjob/powerjob-worker-samples:$version powerjob-worker-samples/. || exit
read -r -p "是否正式发布该镜像(y/n):" needrelease
if [ "$needrelease" = "y" ] || [ "$needrelease" = "Y" ]; then
@@ -47,6 +55,25 @@ if [ "$rebuild" = "y" ] || [ "$rebuild" = "Y" ]; then
docker push tjqq/powerjob-server:$version
echo "================== 正在推送 agent 镜像到中央仓库 =================="
docker push tjqq/powerjob-agent:$version
+ echo "================== 正在推送 powerjob-mysql 镜像到中央仓库 =================="
+ docker push powerjob/powerjob-mysql:$version
+ echo "================== 正在推送 samples 镜像到中央仓库 =================="
+ docker push powerjob/powerjob-worker-samples:$version
+ echo "================== 双写推送 =================="
+ docker tag tjqq/powerjob-server:$version powerjob/powerjob-server:$version
+ docker push powerjob/powerjob-server:$version
+ docker tag tjqq/powerjob-agent:$version powerjob/powerjob-agent:$version
+ docker push powerjob/powerjob-agent:$version
+ echo "================== 更新 LATEST 版本 =================="
+ docker tag powerjob/powerjob-server:$version powerjob/powerjob-server:latest
+ docker push powerjob/powerjob-server:latest
+ docker tag powerjob/powerjob-agent:$version powerjob/powerjob-agent:latest
+ docker push powerjob/powerjob-agent:latest
+ docker tag powerjob/powerjob-mysql:$version powerjob/powerjob-mysql:latest
+ docker push powerjob/powerjob-mysql:latest
+ docker tag powerjob/powerjob-worker-samples:$version powerjob/powerjob-worker-samples:latest
+ docker push powerjob/powerjob-worker-samples:latest
+ echo "================== Docker 推送完毕 =================="
fi
fi
fi
diff --git a/pom.xml b/pom.xml
index 8514171c..8381f0a0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
tech.powerjob
powerjob
- 3.0.0
+ 4.0.0
pom
powerjob
http://www.powerjob.tech
@@ -44,6 +44,7 @@
powerjob-worker-spring-boot-starter
powerjob-worker-samples
powerjob-official-processors
+ powerjob-remote
diff --git a/powerjob-client/pom.xml b/powerjob-client/pom.xml
index 94a23dc2..ab5656df 100644
--- a/powerjob-client/pom.xml
+++ b/powerjob-client/pom.xml
@@ -5,18 +5,18 @@
powerjob
tech.powerjob
- 3.0.0
+ 4.0.0
4.0.0
powerjob-client
- 4.2.1
+ 4.3.0
jar
5.9.1
1.2.83
- 4.2.1
+ 4.3.0
3.2.4
diff --git a/powerjob-common/pom.xml b/powerjob-common/pom.xml
index 06b86c42..a0966360 100644
--- a/powerjob-common/pom.xml
+++ b/powerjob-common/pom.xml
@@ -5,12 +5,12 @@
powerjob
tech.powerjob
- 3.0.0
+ 4.0.0
4.0.0
powerjob-common
- 4.2.1
+ 4.3.0
jar
@@ -19,7 +19,6 @@
2.11.0
31.1-jre
3.14.9
- 2.6.12
5.3.0
2.14.0-rc1
5.9.0
@@ -54,18 +53,6 @@
${okhttp.version}
-
-
- com.typesafe.akka
- akka-remote_2.13
- ${akka.version}
-
-
- com.typesafe.akka
- akka-slf4j_2.13
- ${akka.version}
-
-
commons-io
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/OmsConstant.java b/powerjob-common/src/main/java/tech/powerjob/common/OmsConstant.java
index 129ac429..f589e869 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/OmsConstant.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/OmsConstant.java
@@ -8,6 +8,11 @@ package tech.powerjob.common;
*/
public class OmsConstant {
+ /**
+ * package name
+ */
+ public static final String PACKAGE = "tech.powerjob";
+
public static final int SERVER_DEFAULT_AKKA_PORT = 10086;
public static final int SERVER_DEFAULT_HTTP_PORT = 10010;
@@ -17,6 +22,10 @@ public class OmsConstant {
public static final String NONE = "N/A";
public static final String COMMA = ",";
+
+ public static final String AND = "&";
+
+ public static final String EQUAL = "=";
public static final String LINE_SEPARATOR = "\r\n";
public static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type";
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/PowerJobDKey.java b/powerjob-common/src/main/java/tech/powerjob/common/PowerJobDKey.java
index 5e1cf0da..aa27ea48 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/PowerJobDKey.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/PowerJobDKey.java
@@ -23,6 +23,17 @@ public class PowerJobDKey {
*/
public static final String IGNORED_NETWORK_INTERFACE_REGEX = "powerjob.network.interface.ignored";
+ /**
+ * Enables compression during data transfer, such as gzip under the HTTP protocol. default value is 'false'
+ * Note that enabling compression reduces network usage, but increases CPU consumption
+ */
+ public static final String TRANSPORTER_USE_COMPRESSING = "powerjob.transporter.compression.enabled";
+
+ /**
+ * keep-alive connection timeout(in seconds), value <= 0 means disable keepalive. default value is 75
+ */
+ public static final String TRANSPORTER_KEEP_ALIVE_TIMEOUT = "powerjob.transporter.keepalive.timeout";
+
public static final String WORKER_STATUS_CHECK_PERIOD = "powerjob.worker.status-check.normal.period";
/**
@@ -30,6 +41,8 @@ public class PowerJobDKey {
* It's VERY dangerous
*/
public static final String WORKER_ALLOWED_FORCE_STOP_THREAD = "powerjob.worker.allowed-force-stop-thread";
+
+ public static final String WORKER_WORK_SPACE = "powerjob.worker.workspace";
/**
* ms
*/
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/PowerSerializable.java b/powerjob-common/src/main/java/tech/powerjob/common/PowerSerializable.java
index 48a59ab5..e8dd990f 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/PowerSerializable.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/PowerSerializable.java
@@ -9,12 +9,4 @@ import java.io.Serializable;
* @since 2020/4/16
*/
public interface PowerSerializable extends Serializable {
-
- /**
- * request path for http or other protocol, like '/worker/stopInstance'
- * @return null for non-http request object or no-null path for http request needed object
- */
- default String path() {
- return null;
- }
}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/ProtocolConstant.java b/powerjob-common/src/main/java/tech/powerjob/common/ProtocolConstant.java
deleted file mode 100644
index 9136ce35..00000000
--- a/powerjob-common/src/main/java/tech/powerjob/common/ProtocolConstant.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package tech.powerjob.common;
-
-/**
- * HttpProtocolConstant
- *
- * @author tjq
- * @since 2021/2/8
- */
-public class ProtocolConstant {
-
- public static final String SERVER_PATH_HEARTBEAT = "/server/heartbeat";
- public static final String SERVER_PATH_STATUS_REPORT = "/server/statusReport";
- public static final String SERVER_PATH_LOG_REPORT = "/server/logReport";
-
- public static final String WORKER_PATH_DISPATCH_JOB = "/worker/runJob";
- public static final String WORKER_PATH_STOP_INSTANCE = "/worker/stopInstance";
- public static final String WORKER_PATH_QUERY_INSTANCE_INFO = "/worker/queryInstanceInfo";
-}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/RemoteConstant.java b/powerjob-common/src/main/java/tech/powerjob/common/RemoteConstant.java
index dbc6c8a4..0ee242df 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/RemoteConstant.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/RemoteConstant.java
@@ -12,25 +12,93 @@ public class RemoteConstant {
/* ************************ AKKA WORKER ************************ */
public static final int DEFAULT_WORKER_PORT = 27777;
- public static final String WORKER_ACTOR_SYSTEM_NAME = "oms";
-
- public static final String TASK_TRACKER_ACTOR_NAME = "task_tracker";
- public static final String PROCESSOR_TRACKER_ACTOR_NAME = "processor_tracker";
- public static final String WORKER_ACTOR_NAME = "worker";
- public static final String TROUBLESHOOTING_ACTOR_NAME = "troubleshooting";
-
- public static final String WORKER_AKKA_CONFIG_NAME = "oms-worker.akka.conf";
-
-
- /* ************************ AKKA SERVER ************************ */
- public static final String SERVER_ACTOR_SYSTEM_NAME = "oms-server";
-
- public static final String SERVER_ACTOR_NAME = "server_actor";
- public static final String SERVER_FRIEND_ACTOR_NAME = "friend_actor";
- public static final String SERVER_AKKA_CONFIG_NAME = "oms-server.akka.conf";
-
/* ************************ OTHERS ************************ */
public static final String EMPTY_ADDRESS = "N/A";
public static final long DEFAULT_TIMEOUT_MS = 5000;
+
+ /* ************************ SERVER-self_side (s4s == server for server side) ************************ */
+ public static final String S4S_PATH = "friend";
+
+ /**
+ * server 集群间的心跳处理
+ */
+ public static final String S4S_HANDLER_PING = "ping";
+ /**
+ * 处理其他 server 的执行请求
+ */
+ public static final String S4S_HANDLER_PROCESS = "process";
+
+ /* ************************ SERVER-worker_side(s4w == server for worker side) ************************ */
+ public static final String S4W_PATH = "server";
+ /**
+ * server 处理在线日志
+ */
+ public static final String S4W_HANDLER_REPORT_LOG = "reportLog";
+ /**
+ * server 处理 worker 心跳
+ */
+ public static final String S4W_HANDLER_WORKER_HEARTBEAT = "workerHeartbeat";
+
+ /**
+ * server 处理 TaskTracker 上报的任务实例状态
+ */
+ public static final String S4W_HANDLER_REPORT_INSTANCE_STATUS = "reportInstanceStatus";
+
+ /**
+ * server 查询任务的可执行集群
+ */
+ public static final String S4W_HANDLER_QUERY_JOB_CLUSTER = "queryJobCluster";
+
+ /**
+ * server 处理 worker 请求部署容器命令
+ */
+ public static final String S4W_HANDLER_WORKER_NEED_DEPLOY_CONTAINER = "queryContainer";
+
+ /* ************************ Worker-TaskTracker ************************ */
+ public static final String WTT_PATH = "taskTracker";
+
+ /**
+ * server 任务执行命令
+ */
+ public static final String WTT_HANDLER_RUN_JOB = "runJob";
+ /**
+ * server 停止任务实例命令
+ */
+ public static final String WTT_HANDLER_STOP_INSTANCE = "stopInstance";
+
+ /**
+ * sever 查询任务状态
+ */
+ public static final String WTT_HANDLER_QUERY_INSTANCE_STATUS = "queryInstanceStatus";
+
+ /**
+ * PT 上报任务状态,包含执行结果
+ */
+ public static final String WTT_HANDLER_REPORT_TASK_STATUS = "reportTaskStatus";
+ /**
+ * PT 上报自身状态
+ */
+ public static final String WTT_HANDLER_REPORT_PROCESSOR_TRACKER_STATUS = "reportProcessorTrackerStatus";
+
+ /**
+ * Map 任务
+ */
+ public static final String WTT_HANDLER_MAP_TASK = "mapTask";
+
+ /* ************************ Worker-ProcessorTracker ************************ */
+ public static final String WPT_PATH = "processorTracker";
+
+ public static final String WPT_HANDLER_START_TASK = "startTask";
+
+ public static final String WPT_HANDLER_STOP_INSTANCE = "stopInstance";
+
+ /* ************************ Worker-NORMAL ************************ */
+
+ public static final String WORKER_PATH = "worker";
+
+ public static final String WORKER_HANDLER_DEPLOY_CONTAINER = "deployContainer";
+
+ public static final String WORKER_HANDLER_DESTROY_CONTAINER = "destroyContainer";
+
}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/request/ServerDiscoveryRequest.java b/powerjob-common/src/main/java/tech/powerjob/common/request/ServerDiscoveryRequest.java
new file mode 100644
index 00000000..34a7d6bd
--- /dev/null
+++ b/powerjob-common/src/main/java/tech/powerjob/common/request/ServerDiscoveryRequest.java
@@ -0,0 +1,59 @@
+package tech.powerjob.common.request;
+
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import org.apache.commons.lang3.StringUtils;
+import tech.powerjob.common.enums.Protocol;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * 服务发现请求
+ *
+ * @author tjq
+ * @since 2023/1/21
+ */
+@Setter
+@Accessors(chain = true)
+public class ServerDiscoveryRequest implements Serializable {
+
+ private Long appId;
+
+ private String protocol;
+
+ private String currentServer;
+
+ private String clientVersion;
+
+ public Map toMap() {
+ Map ret = new HashMap<>();
+ ret.put("appId", appId);
+ ret.put("protocol", protocol);
+ if (StringUtils.isNotEmpty(currentServer)) {
+ ret.put("currentServer", currentServer);
+ }
+ if (StringUtils.isNotEmpty(clientVersion)) {
+ ret.put("clientVersion", clientVersion);
+ }
+ return ret;
+ }
+
+ public Long getAppId() {
+ return appId;
+ }
+
+ public String getProtocol() {
+ return Optional.ofNullable(protocol).orElse(Protocol.AKKA.name());
+ }
+
+ public String getCurrentServer() {
+ return currentServer;
+ }
+
+ public String getClientVersion() {
+ return clientVersion;
+ }
+}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/request/ServerQueryInstanceStatusReq.java b/powerjob-common/src/main/java/tech/powerjob/common/request/ServerQueryInstanceStatusReq.java
index 6cf1a985..a37dfbf2 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/request/ServerQueryInstanceStatusReq.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/request/ServerQueryInstanceStatusReq.java
@@ -1,10 +1,9 @@
package tech.powerjob.common.request;
-import tech.powerjob.common.PowerSerializable;
-import tech.powerjob.common.ProtocolConstant;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
+import tech.powerjob.common.PowerSerializable;
/**
* 服务器查询实例运行状态,需要返回详细的运行数据
@@ -18,8 +17,4 @@ import lombok.NoArgsConstructor;
public class ServerQueryInstanceStatusReq implements PowerSerializable {
private Long instanceId;
- @Override
- public String path() {
- return ProtocolConstant.WORKER_PATH_QUERY_INSTANCE_INFO;
- }
}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/request/ServerScheduleJobReq.java b/powerjob-common/src/main/java/tech/powerjob/common/request/ServerScheduleJobReq.java
index 364aba55..ac8df503 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/request/ServerScheduleJobReq.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/request/ServerScheduleJobReq.java
@@ -1,8 +1,7 @@
package tech.powerjob.common.request;
-import tech.powerjob.common.PowerSerializable;
-import tech.powerjob.common.ProtocolConstant;
import lombok.Data;
+import tech.powerjob.common.PowerSerializable;
import java.util.List;
@@ -98,9 +97,4 @@ public class ServerScheduleJobReq implements PowerSerializable {
* 日志配置
*/
private String logConfig;
-
- @Override
- public String path() {
- return ProtocolConstant.WORKER_PATH_DISPATCH_JOB;
- }
}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/request/ServerStopInstanceReq.java b/powerjob-common/src/main/java/tech/powerjob/common/request/ServerStopInstanceReq.java
index 000eb993..765e6f07 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/request/ServerStopInstanceReq.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/request/ServerStopInstanceReq.java
@@ -1,10 +1,9 @@
package tech.powerjob.common.request;
-import tech.powerjob.common.PowerSerializable;
-import tech.powerjob.common.ProtocolConstant;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
+import tech.powerjob.common.PowerSerializable;
/**
@@ -18,9 +17,4 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
public class ServerStopInstanceReq implements PowerSerializable {
private Long instanceId;
-
- @Override
- public String path() {
- return ProtocolConstant.WORKER_PATH_STOP_INSTANCE;
- }
}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/serialize/JsonUtils.java b/powerjob-common/src/main/java/tech/powerjob/common/serialize/JsonUtils.java
index 6809fa4c..77ca831c 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/serialize/JsonUtils.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/serialize/JsonUtils.java
@@ -3,10 +3,11 @@ package tech.powerjob.common.serialize;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.extern.slf4j.Slf4j;
-import tech.powerjob.common.exception.PowerJobException;
import org.apache.commons.lang3.exception.ExceptionUtils;
+import tech.powerjob.common.exception.PowerJobException;
import java.io.IOException;
@@ -19,13 +20,11 @@ import java.io.IOException;
@Slf4j
public class JsonUtils {
- private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
-
- static {
- OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
- //
- OBJECT_MAPPER.configure(JsonParser.Feature.IGNORE_UNDEFINED, true);
- }
+ private static final JsonMapper JSON_MAPPER = JsonMapper.builder()
+ .configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true)
+ .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
+ .configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
+ .build();
private JsonUtils(){
@@ -33,15 +32,16 @@ public class JsonUtils {
public static String toJSONString(Object obj) {
try {
- return OBJECT_MAPPER.writeValueAsString(obj);
- }catch (Exception ignore) {
+ return JSON_MAPPER.writeValueAsString(obj);
+ }catch (Exception e) {
+ log.error("[PowerJob] toJSONString failed", e);
}
return null;
}
public static String toJSONStringUnsafe(Object obj) {
try {
- return OBJECT_MAPPER.writeValueAsString(obj);
+ return JSON_MAPPER.writeValueAsString(obj);
}catch (Exception e) {
throw new PowerJobException(e);
}
@@ -49,31 +49,32 @@ public class JsonUtils {
public static byte[] toBytes(Object obj) {
try {
- return OBJECT_MAPPER.writeValueAsBytes(obj);
- }catch (Exception ignore) {
+ return JSON_MAPPER.writeValueAsBytes(obj);
+ }catch (Exception e) {
+ log.error("[PowerJob] serialize failed", e);
}
return null;
}
public static T parseObject(String json, Class clz) throws JsonProcessingException {
- return OBJECT_MAPPER.readValue(json, clz);
+ return JSON_MAPPER.readValue(json, clz);
}
public static T parseObject(byte[] b, Class clz) throws IOException {
- return OBJECT_MAPPER.readValue(b, clz);
+ return JSON_MAPPER.readValue(b, clz);
}
public static T parseObject(byte[] b, TypeReference typeReference) throws IOException {
- return OBJECT_MAPPER.readValue(b, typeReference);
+ return JSON_MAPPER.readValue(b, typeReference);
}
public static T parseObject(String json, TypeReference typeReference) throws IOException {
- return OBJECT_MAPPER.readValue(json, typeReference);
+ return JSON_MAPPER.readValue(json, typeReference);
}
public static T parseObjectIgnoreException(String json, Class clz) {
try {
- return OBJECT_MAPPER.readValue(json, clz);
+ return JSON_MAPPER.readValue(json, clz);
}catch (Exception e) {
log.error("unable to parse json string to object,current string:{}",json,e);
return null;
@@ -83,7 +84,7 @@ public class JsonUtils {
public static T parseObjectUnsafe(String json, Class clz) {
try {
- return OBJECT_MAPPER.readValue(json, clz);
+ return JSON_MAPPER.readValue(json, clz);
}catch (Exception e) {
ExceptionUtils.rethrow(e);
}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/utils/CollectionUtils.java b/powerjob-common/src/main/java/tech/powerjob/common/utils/CollectionUtils.java
new file mode 100644
index 00000000..2ac86ef4
--- /dev/null
+++ b/powerjob-common/src/main/java/tech/powerjob/common/utils/CollectionUtils.java
@@ -0,0 +1,33 @@
+package tech.powerjob.common.utils;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * CollectionUtils
+ *
+ * @author tjq
+ * @since 2023/1/20
+ */
+public class CollectionUtils {
+
+ /**
+ * Return {@code true} if the supplied Collection is {@code null} or empty.
+ * Otherwise, return {@code false}.
+ * @param collection the Collection to check
+ * @return whether the given Collection is empty
+ */
+ public static boolean isEmpty(Collection> collection) {
+ return (collection == null || collection.isEmpty());
+ }
+
+ /**
+ * Return {@code true} if the supplied Map is {@code null} or empty.
+ * Otherwise, return {@code false}.
+ * @param map the Map to check
+ * @return whether the given Map is empty
+ */
+ public static boolean isEmpty(Map, ?> map) {
+ return (map == null || map.isEmpty());
+ }
+}
diff --git a/powerjob-common/src/main/java/tech/powerjob/common/utils/JavaUtils.java b/powerjob-common/src/main/java/tech/powerjob/common/utils/JavaUtils.java
index 4b0b0c24..efff1973 100644
--- a/powerjob-common/src/main/java/tech/powerjob/common/utils/JavaUtils.java
+++ b/powerjob-common/src/main/java/tech/powerjob/common/utils/JavaUtils.java
@@ -42,14 +42,20 @@ public class JavaUtils {
if (connection instanceof JarURLConnection) {
return getImplementationVersion(((JarURLConnection) connection).getJarFile());
}
- try (JarFile jarFile = new JarFile(new File(codeSourceLocation.toURI()))) {
+ final File file = new File(codeSourceLocation.toURI());
+ // idea 场景,查找版本失败
+ if (!file.exists() || file.isDirectory()) {
+ return "UNKNOWN";
+ }
+ try (JarFile jarFile = new JarFile(file)) {
return getImplementationVersion(jarFile);
}
}
catch (Throwable t) {
log.warn("[JavaUtils] determinePackageVersion for clz[{}] failed, msg: {}", clz.getSimpleName(), t.toString());
+ // windows 下无权限访问会一直报错一直重试,需要在此兼容
+ return "UNKNOWN";
}
- return null;
}
private static String getImplementationVersion(JarFile jarFile) throws IOException {
return jarFile.getManifest().getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION);
diff --git a/powerjob-official-processors/pom.xml b/powerjob-official-processors/pom.xml
index 41229d45..f84021bb 100644
--- a/powerjob-official-processors/pom.xml
+++ b/powerjob-official-processors/pom.xml
@@ -5,12 +5,12 @@
powerjob
tech.powerjob
- 3.0.0
+ 4.0.0
4.0.0
powerjob-official-processors
- 1.2.2
+ 1.3.0
jar
@@ -20,10 +20,11 @@
5.9.1
1.2.9
- 4.2.1
+ 4.3.0
5.2.9.RELEASE
2.1.214
8.0.28
+ 5.3.23
1.2.83
@@ -75,6 +76,13 @@
provided
+
+
+ org.springframework
+ spring-context
+ ${spring.version}
+ provided
+
org.springframework
diff --git a/powerjob-official-processors/src/main/java/tech/powerjob/official/processors/impl/script/AbstractScriptProcessor.java b/powerjob-official-processors/src/main/java/tech/powerjob/official/processors/impl/script/AbstractScriptProcessor.java
index 935df2ca..768160e2 100644
--- a/powerjob-official-processors/src/main/java/tech/powerjob/official/processors/impl/script/AbstractScriptProcessor.java
+++ b/powerjob-official-processors/src/main/java/tech/powerjob/official/processors/impl/script/AbstractScriptProcessor.java
@@ -1,5 +1,6 @@
package tech.powerjob.official.processors.impl.script;
+import tech.powerjob.worker.common.utils.PowerFileUtils;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.log.OmsLogger;
@@ -34,7 +35,7 @@ public abstract class AbstractScriptProcessor extends CommonBasicProcessor {
protected static final String SH_SHELL = "/bin/sh";
protected static final String CMD_SHELL = "cmd.exe";
- private static final String WORKER_DIR = System.getProperty("user.home") + "/powerjob/worker/official_script_processor/";
+ private static final String WORKER_DIR = PowerFileUtils.workspace() + "/official_script_processor/";
@Override
protected ProcessResult process0(TaskContext context) throws Exception {
diff --git a/powerjob-official-processors/src/main/java/tech/powerjob/official/processors/impl/sql/SpringDatasourceSqlProcessor.java b/powerjob-official-processors/src/main/java/tech/powerjob/official/processors/impl/sql/SpringDatasourceSqlProcessor.java
index 120feb54..b8cf0b10 100644
--- a/powerjob-official-processors/src/main/java/tech/powerjob/official/processors/impl/sql/SpringDatasourceSqlProcessor.java
+++ b/powerjob-official-processors/src/main/java/tech/powerjob/official/processors/impl/sql/SpringDatasourceSqlProcessor.java
@@ -3,13 +3,13 @@ package tech.powerjob.official.processors.impl.sql;
import tech.powerjob.worker.core.processor.TaskContext;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.Assert;
import org.apache.commons.lang3.StringUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
+import java.util.Objects;
/**
* 简单 Spring SQL 处理器,目前只能用 Spring Bean 的方式加载
@@ -75,8 +75,8 @@ public class SpringDatasourceSqlProcessor extends AbstractSqlProcessor {
* @param dataSource 数据源
*/
public void registerDataSource(String dataSourceName, DataSource dataSource) {
- Assert.notNull(dataSourceName, "DataSource name must not be null");
- Assert.notNull(dataSource, "DataSource must not be null");
+ Objects.requireNonNull(dataSourceName, "DataSource name must not be null");
+ Objects.requireNonNull(dataSource, "DataSource must not be null");
dataSourceMap.put(dataSourceName, dataSource);
log.info("register data source({})' successfully.", dataSourceName);
}
diff --git a/powerjob-remote/pom.xml b/powerjob-remote/pom.xml
new file mode 100644
index 00000000..5dd8343f
--- /dev/null
+++ b/powerjob-remote/pom.xml
@@ -0,0 +1,47 @@
+
+
+
+ powerjob
+ tech.powerjob
+ 4.0.0
+
+ 4.0.0
+ pom
+
+ powerjob-remote-framework
+ powerjob-remote-benchmark
+ powerjob-remote-impl-http
+ powerjob-remote-impl-akka
+
+
+ powerjob-remote
+
+
+ 8
+ 8
+ UTF-8
+
+ 5.9.0
+ 1.2.9
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.version}
+ test
+
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+ test
+
+
+
+
\ No newline at end of file
diff --git a/powerjob-remote/powerjob-remote-benchmark/pom.xml b/powerjob-remote/powerjob-remote-benchmark/pom.xml
new file mode 100644
index 00000000..827c31cb
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/pom.xml
@@ -0,0 +1,106 @@
+
+
+
+ powerjob-remote
+ tech.powerjob
+ 4.0.0
+
+ 4.0.0
+
+ powerjob-remote-benchmark
+
+
+ 8
+ 8
+ UTF-8
+
+ 3.10.1
+ 3.2.2
+
+ 1.2.9
+ 2.7.4
+ 4.3.0
+ 4.3.0
+
+ 3.9.0
+ 4.2.9
+
+
+
+
+
+
+ io.gatling.highcharts
+ gatling-charts-highcharts
+ ${gatling.version}
+ test
+
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${springboot.version}
+
+
+
+ tech.powerjob
+ powerjob-remote-impl-http
+ ${powerjob-remote-impl-http.version}
+
+
+
+ tech.powerjob
+ powerjob-remote-impl-akka
+ ${powerjob-remote-impl-akka.version}
+
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${springboot.version}
+
+ tech.powerjob.remote.benchmark.BenchmarkApplication
+
+
+
+
+ repackage
+
+
+
+
+
+
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ maven-jar-plugin
+ ${maven-jar-plugin.version}
+
+
+ io.gatling
+ gatling-maven-plugin
+ ${gatling-maven-plugin.version}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/BenchmarkApplication.java b/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/BenchmarkApplication.java
new file mode 100644
index 00000000..64dcb25e
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/BenchmarkApplication.java
@@ -0,0 +1,19 @@
+package tech.powerjob.remote.benchmark;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * 测试工程
+ * 用于 remote 协议压测
+ *
+ * @author tjq
+ * @since 2023/1/7
+ */
+@SpringBootApplication
+public class BenchmarkApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(BenchmarkApplication.class, args);
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/EngineService.java b/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/EngineService.java
new file mode 100644
index 00000000..41079878
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/EngineService.java
@@ -0,0 +1,68 @@
+package tech.powerjob.remote.benchmark;
+
+import com.google.common.collect.Lists;
+import lombok.Getter;
+import org.springframework.stereotype.Service;
+import tech.powerjob.common.enums.Protocol;
+import tech.powerjob.remote.framework.BenchmarkActor;
+import tech.powerjob.remote.framework.base.Address;
+import tech.powerjob.remote.framework.base.ServerType;
+import tech.powerjob.remote.framework.engine.EngineConfig;
+import tech.powerjob.remote.framework.engine.impl.PowerJobRemoteEngine;
+import tech.powerjob.remote.framework.transporter.Transporter;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * EngineService
+ *
+ * @author tjq
+ * @since 2023/1/7
+ */
+@Service
+public class EngineService {
+
+ public static final String HOST = "127.0.0.1";
+
+ public static final int SERVER_AKKA_PORT = 10001;
+ public static final int SERVER_HTTP_PORT = 10002;
+
+ public static final int CLIENT_AKKA_PORT = 20001;
+ public static final int CLIENT_HTTP_PORT = 20002;
+
+ @Getter
+ private Transporter akkaTransporter;
+ @Getter
+ private Transporter httpTransporter;
+
+ @PostConstruct
+ public void init() {
+ // http server
+ new PowerJobRemoteEngine().start(new EngineConfig()
+ .setServerType(ServerType.SERVER)
+ .setActorList(Lists.newArrayList(new BenchmarkActor()))
+ .setType(Protocol.HTTP.name())
+ .setBindAddress(new Address().setHost(HOST).setPort(SERVER_HTTP_PORT)));
+
+ // akka server
+ new PowerJobRemoteEngine().start(new EngineConfig()
+ .setServerType(ServerType.SERVER)
+ .setActorList(Lists.newArrayList(new BenchmarkActor()))
+ .setType(Protocol.AKKA.name())
+ .setBindAddress(new Address().setHost(HOST).setPort(SERVER_AKKA_PORT)));
+
+ // http client
+ httpTransporter = new PowerJobRemoteEngine().start(new EngineConfig()
+ .setServerType(ServerType.WORKER)
+ .setActorList(Lists.newArrayList(new BenchmarkActor()))
+ .setType(Protocol.HTTP.name())
+ .setBindAddress(new Address().setHost(HOST).setPort(CLIENT_HTTP_PORT))).getTransporter();
+
+ // akka client
+ akkaTransporter = new PowerJobRemoteEngine().start(new EngineConfig()
+ .setServerType(ServerType.WORKER)
+ .setActorList(Lists.newArrayList(new BenchmarkActor()))
+ .setType(Protocol.AKKA.name())
+ .setBindAddress(new Address().setHost(HOST).setPort(CLIENT_AKKA_PORT))).getTransporter();
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/PressureTestController.java b/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/PressureTestController.java
new file mode 100644
index 00000000..c2f9fcc4
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/src/main/java/tech/powerjob/remote/benchmark/PressureTestController.java
@@ -0,0 +1,82 @@
+package tech.powerjob.remote.benchmark;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import tech.powerjob.common.enums.Protocol;
+import tech.powerjob.remote.framework.BenchmarkActor;
+import tech.powerjob.remote.framework.base.Address;
+import tech.powerjob.remote.framework.base.HandlerLocation;
+import tech.powerjob.remote.framework.base.URL;
+
+import javax.annotation.Resource;
+
+import java.util.concurrent.CompletionStage;
+
+import static tech.powerjob.remote.benchmark.EngineService.*;
+
+/**
+ * 压测测试入口
+ *
+ * @author tjq
+ * @since 2023/1/7
+ */
+@Slf4j
+@RestController
+@RequestMapping("/pressure")
+public class PressureTestController {
+
+ private static final HandlerLocation HL = new HandlerLocation().setRootPath("benchmark").setMethodPath("standard");
+
+ @Resource
+ private EngineService engineService;
+
+ @GetMapping("/tell")
+ public void httpTell(String protocol, Integer blockMs, Integer responseSize, String content) {
+ Address address = new Address().setHost(HOST);
+ URL url = new URL().setLocation(HL).setAddress(address);
+ final BenchmarkActor.BenchmarkRequest request = new BenchmarkActor.BenchmarkRequest().setContent(content).setBlockingMills(blockMs).setResponseSize(responseSize);
+ try {
+ if (Protocol.HTTP.name().equalsIgnoreCase(protocol)) {
+ address.setPort(SERVER_HTTP_PORT);
+ engineService.getHttpTransporter().tell(url, request);
+ } else {
+ address.setPort(SERVER_AKKA_PORT);
+ engineService.getAkkaTransporter().tell(url, request);
+ }
+ } catch (Exception e) {
+ log.error("[HttpTell] process failed!", e);
+ ExceptionUtils.rethrow(e);
+ }
+ }
+
+
+ @GetMapping("/ask")
+ public void httpAsk(String protocol, Integer blockMs, Integer responseSize, String content, Boolean debug) {
+ Address address = new Address().setHost(HOST);
+ URL url = new URL().setLocation(HL).setAddress(address);
+ final BenchmarkActor.BenchmarkRequest request = new BenchmarkActor.BenchmarkRequest().setContent(content).setBlockingMills(blockMs).setResponseSize(responseSize);
+ try {
+ CompletionStage responseOpt = null;
+
+ if (Protocol.HTTP.name().equalsIgnoreCase(protocol)) {
+ address.setPort(SERVER_HTTP_PORT);
+ responseOpt = engineService.getHttpTransporter().ask(url, request, BenchmarkActor.BenchmarkResponse.class);
+ } else {
+ address.setPort(SERVER_AKKA_PORT);
+ responseOpt = engineService.getAkkaTransporter().ask(url, request, BenchmarkActor.BenchmarkResponse.class);
+ }
+ final BenchmarkActor.BenchmarkResponse response = responseOpt.toCompletableFuture().get();
+ if (BooleanUtils.isTrue(debug)) {
+ log.info("[httpAsk] response: {}", response);
+ }
+ } catch (Exception e) {
+ log.error("[httpAsk] process failed", e);
+ ExceptionUtils.rethrow(e);
+ }
+ }
+
+}
diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/java/Engine.java b/powerjob-remote/powerjob-remote-benchmark/src/test/java/Engine.java
new file mode 100644
index 00000000..fa70e9eb
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/src/test/java/Engine.java
@@ -0,0 +1,20 @@
+import io.gatling.app.Gatling;
+import io.gatling.core.config.GatlingPropertiesBuilder;
+
+/**
+ * 压测启动入口
+ *
+ * @author tjq
+ * @since 2023/1/8
+ */
+public class Engine {
+
+ public static void main(String[] args) {
+ GatlingPropertiesBuilder props = new GatlingPropertiesBuilder()
+ .resourcesDirectory(IDEPathHelper.mavenResourcesDirectory.toString())
+ .resultsDirectory(IDEPathHelper.resultsDirectory.toString())
+ .binariesDirectory(IDEPathHelper.mavenBinariesDirectory.toString());
+
+ Gatling.fromMap(props.build());
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/java/IDEPathHelper.java b/powerjob-remote/powerjob-remote-benchmark/src/test/java/IDEPathHelper.java
new file mode 100644
index 00000000..5315cad1
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/src/test/java/IDEPathHelper.java
@@ -0,0 +1,33 @@
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * @author gatling-maven-plugin-demo-java
+ */
+public class IDEPathHelper {
+
+ static final Path mavenSourcesDirectory;
+ static final Path mavenResourcesDirectory;
+ static final Path mavenBinariesDirectory;
+ static final Path resultsDirectory;
+ static final Path recorderConfigFile;
+
+ static {
+ try {
+ Path projectRootDir = Paths.get(requireNonNull(IDEPathHelper.class.getResource("gatling.conf"), "Couldn't locate gatling.conf").toURI()).getParent().getParent().getParent();
+ Path mavenTargetDirectory = projectRootDir.resolve("target");
+ Path mavenSrcTestDirectory = projectRootDir.resolve("src").resolve("test");
+
+ mavenSourcesDirectory = mavenSrcTestDirectory.resolve("java");
+ mavenResourcesDirectory = mavenSrcTestDirectory.resolve("resources");
+ mavenBinariesDirectory = mavenTargetDirectory.resolve("test-classes");
+ resultsDirectory = mavenTargetDirectory.resolve("gatling");
+ recorderConfigFile = mavenResourcesDirectory.resolve("recorder.conf");
+ } catch (URISyntaxException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/Constant.java b/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/Constant.java
new file mode 100644
index 00000000..71820edb
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/Constant.java
@@ -0,0 +1,14 @@
+package tech.powerjob.remote.benchmark;
+
+/**
+ * Constant
+ * 压测时需要修改的常量
+ *
+ * @author tjq
+ * @since 2023/1/8
+ */
+public class Constant {
+
+ public static final String SERVER_HOST = "127.0.0.1";
+
+}
diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/HttpSimulation.java b/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/HttpSimulation.java
new file mode 100644
index 00000000..00b1a8b4
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/src/test/java/tech/powerjob/remote/benchmark/HttpSimulation.java
@@ -0,0 +1,62 @@
+package tech.powerjob.remote.benchmark;
+
+import static io.gatling.javaapi.core.CoreDsl.*;
+import static io.gatling.javaapi.http.HttpDsl.*;
+
+import io.gatling.javaapi.core.*;
+import io.gatling.javaapi.http.*;
+/**
+ * 以 HTTP 为入口压测
+ *
+ * @author tjq
+ * @since 2023/1/8
+ */
+public class HttpSimulation extends Simulation {
+
+ String baseUrl = String.format("http://%s:8080", Constant.SERVER_HOST);
+ HttpProtocolBuilder httpProtocol = http // 4
+ .baseUrl(baseUrl) // 5
+ .acceptHeader("application/json") // 6
+ .doNotTrackHeader("1")
+ .acceptLanguageHeader("en-US,en;q=0.5")
+ .acceptEncodingHeader("gzip, deflate")
+ .userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0");
+
+ ScenarioBuilder warmup = scenario("WarmupSimulation")
+ .exec(http("PowerJob-Warmup-HTTP")
+ .get("/pressure/ask?protocol=HTTP&debug=false&responseSize=1024"))
+ .exec(http("PowerJob-Warmup-AKKA")
+ .get("/pressure/ask?protocol=AKKA&debug=false&responseSize=1024"))
+ ;
+
+ ScenarioBuilder httpAsk = scenario("HttpSimulation") // 7
+ .exec(http("PowerJob-Remote-Http") // 请求名称,用于压测报表展示
+ .get("/pressure/ask?protocol=HTTP&debug=false&responseSize=1024")) // 9
+ ;
+
+ ScenarioBuilder akkaAsk = scenario("AkkaSimulation") // 7
+ .exec(http("PowerJob-Remote-AKKA") // 请求名称,用于压测报表展示
+ .get("/pressure/ask?protocol=AKKA&debug=false&responseSize=1024")) // 9
+ ;
+
+
+ /*
+ atOnceUsers(10) 一次模拟的用户数量(10)
+ nothingFor(4 seconds) 在指定的时间段(4 seconds)内什么都不干
+ constantUsersPerSec(10) during(20 seconds) 以固定的速度模拟用户,指定每秒模拟的用户数(10),指定模拟测试时间长度(20 seconds)
+ rampUsersPerSec(10) to (20) during(20 seconds) 在指定的时间(20 seconds)内,使每秒模拟的用户从数量1(10)逐渐增加到数量2(20),速度匀速
+ heavisideUsers(100) over(10 seconds) 在指定的时间(10 seconds)内使用类似单位阶跃函数的方法逐渐增加模拟并发的用户,直到总数达到指定的数量(100).简单说就是每秒并发用户数递增
+ */
+
+ {
+ setUp( // 11
+ warmup.injectOpen(constantUsersPerSec(50).during(10))
+ .andThen(
+ httpAsk.injectOpen(incrementUsersPerSec(100).times(10).eachLevelLasting(10))
+ )
+ .andThen(
+ akkaAsk.injectOpen(incrementUsersPerSec(100).times(10).eachLevelLasting(10))
+ )
+ ).protocols(httpProtocol); // 13
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-benchmark/src/test/resources/gatling.conf b/powerjob-remote/powerjob-remote-benchmark/src/test/resources/gatling.conf
new file mode 100644
index 00000000..c6db7626
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-benchmark/src/test/resources/gatling.conf
@@ -0,0 +1,127 @@
+#########################
+# Gatling Configuration #
+#########################
+
+# This file contains all the settings configurable for Gatling with their default values
+
+gatling {
+ core {
+ #outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp)
+ #runDescription = "" # The description for this simulation run, displayed in each report
+ #encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation
+ #simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated)
+ #elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable
+ #rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable
+ #rawFileBodiesInMemoryMaxSize = 1000 # Below this limit, raw file bodies will be cached in memory
+ #pebbleFileBodiesCacheMaxCapacity = 200 # Cache size for request body Peeble templates, set to 0 to disable
+ #feederAdaptiveLoadModeThreshold = 100 # File size threshold (in MB). Below load eagerly in memory, above use batch mode with default buffer size
+ #shutdownTimeout = 10000 # Milliseconds to wait for the actor system to shutdown
+ extract {
+ regex {
+ #cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching
+ }
+ xpath {
+ #cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching
+ }
+ jsonPath {
+ #cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching
+ }
+ css {
+ #cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching
+ }
+ }
+ directory {
+ #simulations = user-files/simulations # Directory where simulation classes are located (for bundle packaging only)
+ #resources = user-files/resources # Directory where resources, such as feeder files and request bodies are located (for bundle packaging only)
+ #reportsOnly = "" # If set, name of report folder to look for in order to generate its report
+ #binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target.
+ #results = results # Name of the folder where all reports folder are located
+ }
+ }
+ socket {
+ #connectTimeout = 10000 # Timeout in millis for establishing a TCP socket
+ #tcpNoDelay = true
+ #soKeepAlive = false # if TCP keepalive configured at OS level should be used
+ #soReuseAddress = false
+ }
+ netty {
+ #useNativeTransport = true # if Netty native transport should be used instead of Java NIO
+ #allocator = "pooled" # switch to unpooled for unpooled ByteBufAllocator
+ #maxThreadLocalCharBufferSize = 200000 # Netty's default is 16k
+ }
+ ssl {
+ #useOpenSsl = true # if OpenSSL should be used instead of JSSE (only the latter can be debugged with -Djava.net.debug=ssl)
+ #useOpenSslFinalizers = false # if OpenSSL contexts should be freed with Finalizer or if using RefCounted is fine
+ #handshakeTimeout = 10000 # TLS handshake timeout in millis
+ #useInsecureTrustManager = true # Use an insecure TrustManager that trusts all server certificates
+ #enabledProtocols = [] # Array of enabled protocols for HTTPS, if empty use Netty's defaults
+ #enabledCipherSuites = [] # Array of enabled cipher suites for HTTPS, if empty enable all available ciphers
+ #sessionCacheSize = 0 # SSLSession cache size, set to 0 to use JDK's default
+ #sessionTimeout = 0 # SSLSession timeout in seconds, set to 0 to use JDK's default (24h)
+ #enableSni = true # When set to true, enable Server Name indication (SNI)
+ keyStore {
+ #type = "" # Type of SSLContext's KeyManagers store
+ #file = "" # Location of SSLContext's KeyManagers store
+ #password = "" # Password for SSLContext's KeyManagers store
+ #algorithm = "" # Algorithm used SSLContext's KeyManagers store
+ }
+ trustStore {
+ #type = "" # Type of SSLContext's TrustManagers store
+ #file = "" # Location of SSLContext's TrustManagers store
+ #password = "" # Password for SSLContext's TrustManagers store
+ #algorithm = "" # Algorithm used by SSLContext's TrustManagers store
+ }
+ }
+ charting {
+ #noReports = false # When set to true, don't generate HTML reports
+ #maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports
+ #useGroupDurationMetric = false # Switch group timings from cumulated response time to group duration.
+ indicators {
+ #lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary
+ #higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary
+ #percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and Graphite
+ #percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and Graphite
+ #percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and Graphite
+ #percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and Graphite
+ }
+ }
+ http {
+ #fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable
+ #fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable
+ #perUserCacheMaxCapacity = 200 # Per virtual user cache size, set to 0 to disable
+ #warmUpUrl = "https://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled)
+ #enableGA = true # Very light Google Analytics (Gatling and Java version), please support
+ #pooledConnectionIdleTimeout = 60000 # Timeout in millis for a connection to stay idle in the pool
+ #requestTimeout = 60000 # Timeout in millis for performing an HTTP request
+ #enableHostnameVerification = false # When set to true, enable hostname verification: SSLEngine.setHttpsEndpointIdentificationAlgorithm("HTTPS")
+ dns {
+ #queryTimeout = 5000 # Timeout in millis of each DNS query in millis
+ #maxQueriesPerResolve = 6 # Maximum allowed number of DNS queries for a given name resolution
+ }
+ }
+ jms {
+ #replyTimeoutScanPeriod = 1000 # scan period for timedout reply messages
+ }
+ data {
+ #writers = [console, file] # The list of DataWriters to which Gatling write simulation data (currently supported : console, file, graphite)
+ console {
+ #light = false # When set to true, displays a light version without detailed request stats
+ #writePeriod = 5 # Write interval, in seconds
+ }
+ file {
+ #bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes
+ }
+ leak {
+ #noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening
+ }
+ graphite {
+ #light = false # only send the all* stats
+ #host = "localhost" # The host where the Carbon server is located
+ #port = 2003 # The port to which the Carbon server listens to (2003 is default for plaintext, 2004 is default for pickle)
+ #protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp")
+ #rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite
+ #bufferSize = 8192 # Internal data buffer size, in bytes
+ #writePeriod = 1 # Write period, in seconds
+ }
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-framework/pom.xml b/powerjob-remote/powerjob-remote-framework/pom.xml
new file mode 100644
index 00000000..29e6ca81
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/pom.xml
@@ -0,0 +1,41 @@
+
+
+
+ powerjob-remote
+ tech.powerjob
+ 4.0.0
+
+ 4.0.0
+
+ 4.3.0
+ powerjob-remote-framework
+
+
+ 8
+ 8
+ UTF-8
+
+ 4.3.0
+ 0.10.2
+
+
+
+
+
+
+ tech.powerjob
+ powerjob-common
+ ${powerjob-common.version}
+
+
+
+ org.reflections
+ reflections
+ ${reflections.version}
+
+
+
+
+
\ No newline at end of file
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/BenchmarkActor.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/BenchmarkActor.java
new file mode 100644
index 00000000..325aa6e2
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/BenchmarkActor.java
@@ -0,0 +1,94 @@
+package tech.powerjob.remote.framework;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.RandomStringUtils;
+import tech.powerjob.common.PowerSerializable;
+import tech.powerjob.common.utils.CommonUtils;
+import tech.powerjob.remote.framework.actor.Actor;
+import tech.powerjob.remote.framework.actor.Handler;
+
+import java.util.Optional;
+
+/**
+ * 基准测试
+ *
+ * @author tjq
+ * @since 2023/1/1
+ */
+@Slf4j
+@Actor(path = "benchmark")
+public class BenchmarkActor {
+
+ @Handler(path = "standard")
+ public BenchmarkResponse standardRequest(BenchmarkRequest request) {
+ long startTs = System.currentTimeMillis();
+ log.info("[BenchmarkActor] [standardRequest] receive request: {}", request);
+ BenchmarkResponse response = new BenchmarkResponse()
+ .setSuccess(true)
+ .setContent(request.getContent())
+ .setProcessThread(Thread.currentThread().getName())
+ .setServerReceiveTs(System.currentTimeMillis());
+ if (request.getResponseSize() != null && request.getResponseSize() > 0) {
+ response.setExtra(RandomStringUtils.randomPrint(request.getResponseSize()));
+ }
+ executeSleep(request);
+ response.setServerCost(System.currentTimeMillis() - startTs);
+ return response;
+ }
+
+ @Handler(path = "emptyReturn")
+ public void emptyReturn(BenchmarkRequest request) {
+ log.info("[BenchmarkActor] [emptyReturn] receive request: {}", request);
+ executeSleep(request);
+ }
+
+ @Handler(path = "stringReturn")
+ public String stringReturn(BenchmarkRequest request) {
+ log.info("[BenchmarkActor] [stringReturn] receive request: {}", request);
+ executeSleep(request);
+ return RandomStringUtils.randomPrint(Optional.ofNullable(request.getResponseSize()).orElse(100));
+ }
+
+ private static void executeSleep(BenchmarkRequest request) {
+ if (request.getBlockingMills() != null && request.getBlockingMills() > 0) {
+ CommonUtils.easySleep(request.getBlockingMills());
+ }
+ }
+
+
+ @Data
+ @Accessors(chain = true)
+ public static class BenchmarkRequest implements PowerSerializable {
+ /**
+ * 请求内容
+ */
+ private String content;
+ /**
+ * 期望的响应大小,可空
+ */
+ private Integer responseSize;
+ /**
+ * 阻塞时间,模拟 IO 耗时
+ */
+ private Integer blockingMills;
+ }
+
+ @Data
+ @Accessors(chain = true)
+ public static class BenchmarkResponse implements PowerSerializable {
+ private boolean success;
+ /**
+ * 原路返回原来的 content
+ */
+ private String content;
+
+ private String processThread;
+ private long serverReceiveTs;
+
+ private long serverCost;
+
+ private String extra;
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/Actor.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/Actor.java
new file mode 100644
index 00000000..419b3353
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/Actor.java
@@ -0,0 +1,21 @@
+package tech.powerjob.remote.framework.actor;
+
+import java.lang.annotation.*;
+
+/**
+ * 行为处理器
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface Actor {
+
+ /**
+ * root path
+ * @return root path
+ */
+ String path();
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/ActorInfo.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/ActorInfo.java
new file mode 100644
index 00000000..d139dc73
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/ActorInfo.java
@@ -0,0 +1,27 @@
+package tech.powerjob.remote.framework.actor;
+
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * ActorInfo
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class ActorInfo {
+
+ private Object actor;
+
+ private Actor anno;
+
+ private List handlerInfos;
+
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/Handler.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/Handler.java
new file mode 100644
index 00000000..e5d1972d
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/Handler.java
@@ -0,0 +1,27 @@
+package tech.powerjob.remote.framework.actor;
+
+import java.lang.annotation.*;
+
+/**
+ * Handler
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface Handler {
+
+ /**
+ * handler path
+ * @return handler path
+ */
+ String path();
+
+ /**
+ * 处理类型
+ * @return 阻塞 or 非阻塞
+ */
+ ProcessType processType() default ProcessType.BLOCKING;
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/HandlerInfo.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/HandlerInfo.java
new file mode 100644
index 00000000..dd502d9e
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/HandlerInfo.java
@@ -0,0 +1,34 @@
+package tech.powerjob.remote.framework.actor;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+import tech.powerjob.remote.framework.base.HandlerLocation;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+/**
+ * HandlerInfo
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class HandlerInfo {
+
+ private HandlerLocation location;
+ /**
+ * handler 对应的方法
+ */
+ private Method method;
+
+ /**
+ * Handler 注解携带的信息
+ */
+ private Handler anno;
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/ProcessType.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/ProcessType.java
new file mode 100644
index 00000000..ef3d7623
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/actor/ProcessType.java
@@ -0,0 +1,20 @@
+package tech.powerjob.remote.framework.actor;
+
+/**
+ * 处理器类型
+ *
+ * @author tjq
+ * @since 2023/1/1
+ */
+public enum ProcessType {
+
+ /**
+ * 阻塞式
+ */
+ BLOCKING,
+ /**
+ * 非阻塞式
+ */
+ NO_BLOCKING
+
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/Address.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/Address.java
new file mode 100644
index 00000000..5541f111
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/Address.java
@@ -0,0 +1,37 @@
+package tech.powerjob.remote.framework.base;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * 地址
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class Address implements Serializable {
+ private String host;
+ private int port;
+
+ public String toFullAddress() {
+ return String.format("%s:%d", host, port);
+ }
+
+ public static Address fromIpv4(String ipv4) {
+ String[] split = ipv4.split(":");
+ return new Address()
+ .setHost(split[0])
+ .setPort(Integer.parseInt(split[1]));
+ }
+
+ @Override
+ public String toString() {
+ return toFullAddress();
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/HandlerLocation.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/HandlerLocation.java
new file mode 100644
index 00000000..6f9cc5ba
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/HandlerLocation.java
@@ -0,0 +1,33 @@
+package tech.powerjob.remote.framework.base;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * handler location
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class HandlerLocation implements Serializable {
+ /**
+ * 根路径
+ */
+ private String rootPath;
+ /**
+ * 方法路径
+ */
+ private String methodPath;
+
+ public String toPath() {
+ return String.format("/%s/%s", rootPath, methodPath);
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/RemotingException.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/RemotingException.java
new file mode 100644
index 00000000..fd3185db
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/RemotingException.java
@@ -0,0 +1,16 @@
+package tech.powerjob.remote.framework.base;
+
+import java.io.IOException;
+
+/**
+ * RemotingException
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+public class RemotingException extends RuntimeException {
+
+ public RemotingException(String message) {
+ super(message);
+ }
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/ServerType.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/ServerType.java
new file mode 100644
index 00000000..2b57212f
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/ServerType.java
@@ -0,0 +1,12 @@
+package tech.powerjob.remote.framework.base;
+
+/**
+ * 服务器类型类型
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+public enum ServerType {
+ SERVER,
+ WORKER
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/URL.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/URL.java
new file mode 100644
index 00000000..c1909b99
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/base/URL.java
@@ -0,0 +1,32 @@
+package tech.powerjob.remote.framework.base;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * URL
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Data
+@Accessors(chain = true)
+public class URL implements Serializable {
+
+ /**
+ * 调用的集群类型(用于兼容 AKKA 等除了IP还需要指定 system 访问的情况)
+ */
+ private ServerType serverType;
+
+ /**
+ * remote address
+ */
+ private Address address;
+
+ /**
+ * location
+ */
+ private HandlerLocation location;
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/cs/CSInitializer.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/cs/CSInitializer.java
new file mode 100644
index 00000000..a5e140d9
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/cs/CSInitializer.java
@@ -0,0 +1,43 @@
+package tech.powerjob.remote.framework.cs;
+
+import tech.powerjob.remote.framework.actor.ActorInfo;
+import tech.powerjob.remote.framework.transporter.Transporter;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * client & server initializer
+ *
+ * @author MuBao
+ * @since 2022/12/31
+ */
+public interface CSInitializer {
+
+ /**
+ * 类型名称,比如 akka, netty4,httpJson
+ * @return 名称
+ */
+ String type();
+
+ /**
+ * initialize the framework
+ * @param config config
+ */
+ void init(CSInitializerConfig config);
+
+ /**
+ * build a Transporter by based network framework
+ * @return Transporter
+ */
+ Transporter buildTransporter();
+
+ /**
+ * bind Actor, publish handler's service
+ * @param actorInfos actor infos
+ */
+ void bindHandlers(List actorInfos);
+
+ void close() throws IOException;
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/cs/CSInitializerConfig.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/cs/CSInitializerConfig.java
new file mode 100644
index 00000000..a64051fd
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/cs/CSInitializerConfig.java
@@ -0,0 +1,25 @@
+package tech.powerjob.remote.framework.cs;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import tech.powerjob.remote.framework.base.Address;
+import tech.powerjob.remote.framework.base.ServerType;
+
+import java.io.Serializable;
+
+/**
+ * CSInitializerConfig
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class CSInitializerConfig implements Serializable {
+
+ private Address bindAddress;
+
+ private ServerType serverType;
+}
diff --git a/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/engine/EngineConfig.java b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/engine/EngineConfig.java
new file mode 100644
index 00000000..a9b82961
--- /dev/null
+++ b/powerjob-remote/powerjob-remote-framework/src/main/java/tech/powerjob/remote/framework/engine/EngineConfig.java
@@ -0,0 +1,37 @@
+package tech.powerjob.remote.framework.engine;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+import tech.powerjob.remote.framework.base.Address;
+import tech.powerjob.remote.framework.base.ServerType;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * EngineConfig
+ *
+ * @author tjq
+ * @since 2022/12/31
+ */
+@Data
+@Accessors(chain = true)
+public class EngineConfig implements Serializable {
+
+ /**
+ * 服务类型
+ */
+ private ServerType serverType;
+ /**
+ * 需要启动的引擎类型
+ */
+ private String type;
+ /**
+ * 绑定的本地地址
+ */
+ private Address bindAddress;
+ /**
+ * actor实例,交由使用侧自己实例化以便自行注入各种 bean
+ */
+ private List
-
- io.vertx
- vertx-web
- ${vertx-web.version}
-
-
- io.vertx
- vertx-web-client
- ${vertx-web.version}
-
-
com.cronutils
cron-utils
@@ -267,6 +269,12 @@
io.springfox
springfox-swagger2
${swagger.version}
+
+
+ guava
+ com.google.guava
+
+
diff --git a/powerjob-server/powerjob-server-common/pom.xml b/powerjob-server/powerjob-server-common/pom.xml
index 227e65b1..c45da96b 100644
--- a/powerjob-server/powerjob-server-common/pom.xml
+++ b/powerjob-server/powerjob-server-common/pom.xml
@@ -5,7 +5,7 @@
powerjob-server
tech.powerjob
- 4.2.1
+ 4.3.0
../pom.xml
4.0.0
diff --git a/powerjob-server/powerjob-server-common/src/main/java/tech/powerjob/server/common/module/ServerInfo.java b/powerjob-server/powerjob-server-common/src/main/java/tech/powerjob/server/common/module/ServerInfo.java
index d2c004fa..c264b258 100644
--- a/powerjob-server/powerjob-server-common/src/main/java/tech/powerjob/server/common/module/ServerInfo.java
+++ b/powerjob-server/powerjob-server-common/src/main/java/tech/powerjob/server/common/module/ServerInfo.java
@@ -15,5 +15,7 @@ public class ServerInfo {
private String ip;
+ private long bornTime;
+
private String version = "UNKNOWN";
}
diff --git a/powerjob-server/powerjob-server-core/pom.xml b/powerjob-server/powerjob-server-core/pom.xml
index 2a3e13ea..8b3d02b3 100644
--- a/powerjob-server/powerjob-server-core/pom.xml
+++ b/powerjob-server/powerjob-server-core/pom.xml
@@ -5,7 +5,7 @@
powerjob-server
tech.powerjob
- 4.2.1
+ 4.3.0
../pom.xml
4.0.0
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/DispatchService.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/DispatchService.java
index 4a80cf87..b0821b62 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/DispatchService.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/DispatchService.java
@@ -3,14 +3,18 @@ package tech.powerjob.server.core;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.SystemInstanceResult;
-import tech.powerjob.common.enums.*;
+import tech.powerjob.common.enums.ExecuteType;
+import tech.powerjob.common.enums.InstanceStatus;
+import tech.powerjob.common.enums.ProcessorType;
+import tech.powerjob.common.enums.TimeExpressionType;
import tech.powerjob.common.request.ServerScheduleJobReq;
+import tech.powerjob.remote.framework.base.URL;
import tech.powerjob.server.common.Holder;
import tech.powerjob.server.common.module.WorkerInfo;
import tech.powerjob.server.core.instance.InstanceManager;
@@ -19,7 +23,8 @@ import tech.powerjob.server.core.lock.UseCacheLock;
import tech.powerjob.server.persistence.remote.model.InstanceInfoDO;
import tech.powerjob.server.persistence.remote.model.JobInfoDO;
import tech.powerjob.server.persistence.remote.repository.InstanceInfoRepository;
-import tech.powerjob.server.remote.transport.TransportService;
+import tech.powerjob.server.remote.transporter.TransportService;
+import tech.powerjob.server.remote.transporter.impl.ServerURLFactory;
import tech.powerjob.server.remote.worker.WorkerClusterQueryService;
import java.util.ArrayList;
@@ -165,7 +170,8 @@ public class DispatchService {
WorkerInfo taskTracker = suitableWorkers.get(0);
String taskTrackerAddress = taskTracker.getAddress();
- transportService.tell(Protocol.of(taskTracker.getProtocol()), taskTrackerAddress, req);
+ URL workerUrl = ServerURLFactory.dispatchJob2Worker(taskTrackerAddress);
+ transportService.tell(taskTracker.getProtocol(), workerUrl, req);
log.info("[Dispatcher-{}|{}] send schedule request to TaskTracker[protocol:{},address:{}] successfully: {}.", jobId, instanceId, taskTracker.getProtocol(), taskTrackerAddress, req);
// 修改状态
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/container/ContainerService.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/container/ContainerService.java
index 56dc22ee..35de0310 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/container/ContainerService.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/container/ContainerService.java
@@ -1,25 +1,5 @@
package tech.powerjob.server.core.container;
-import tech.powerjob.common.OmsConstant;
-import tech.powerjob.common.enums.Protocol;
-import tech.powerjob.common.model.DeployedContainerInfo;
-import tech.powerjob.common.model.GitRepoInfo;
-import tech.powerjob.common.request.ServerDeployContainerRequest;
-import tech.powerjob.common.request.ServerDestroyContainerRequest;
-import tech.powerjob.common.utils.CommonUtils;
-import tech.powerjob.common.serialize.JsonUtils;
-import tech.powerjob.common.utils.NetUtils;
-import tech.powerjob.common.utils.SegmentLock;
-import tech.powerjob.server.common.constants.ContainerSourceType;
-import tech.powerjob.server.common.constants.SwitchableStatus;
-import tech.powerjob.server.common.utils.OmsFileUtils;
-import tech.powerjob.server.extension.LockService;
-import tech.powerjob.server.persistence.remote.model.ContainerInfoDO;
-import tech.powerjob.server.persistence.remote.repository.ContainerInfoRepository;
-import tech.powerjob.server.persistence.mongodb.GridFsManager;
-import tech.powerjob.server.remote.transport.TransportService;
-import tech.powerjob.server.remote.worker.WorkerClusterQueryService;
-import tech.powerjob.server.common.module.WorkerInfo;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
@@ -28,6 +8,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.maven.shared.invoker.DefaultInvocationRequest;
@@ -43,8 +24,29 @@ import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
+import tech.powerjob.common.OmsConstant;
+import tech.powerjob.common.model.DeployedContainerInfo;
+import tech.powerjob.common.model.GitRepoInfo;
+import tech.powerjob.common.request.ServerDeployContainerRequest;
+import tech.powerjob.common.request.ServerDestroyContainerRequest;
+import tech.powerjob.common.serialize.JsonUtils;
+import tech.powerjob.common.utils.CommonUtils;
+import tech.powerjob.common.utils.NetUtils;
+import tech.powerjob.common.utils.SegmentLock;
+import tech.powerjob.remote.framework.base.URL;
+import tech.powerjob.server.common.constants.ContainerSourceType;
+import tech.powerjob.server.common.constants.SwitchableStatus;
+import tech.powerjob.server.common.module.WorkerInfo;
+import tech.powerjob.server.common.utils.OmsFileUtils;
+import tech.powerjob.server.extension.LockService;
+import tech.powerjob.server.persistence.mongodb.GridFsManager;
+import tech.powerjob.server.persistence.remote.model.ContainerInfoDO;
+import tech.powerjob.server.persistence.remote.repository.ContainerInfoRepository;
+import tech.powerjob.server.remote.server.redirector.DesignateServer;
+import tech.powerjob.server.remote.transporter.impl.ServerURLFactory;
+import tech.powerjob.server.remote.transporter.TransportService;
+import tech.powerjob.server.remote.worker.WorkerClusterQueryService;
import javax.annotation.Resource;
import javax.websocket.RemoteEndpoint;
@@ -128,7 +130,8 @@ public class ContainerService {
ServerDestroyContainerRequest destroyRequest = new ServerDestroyContainerRequest(container.getId());
workerClusterQueryService.getAllAliveWorkers(container.getAppId()).forEach(workerInfo -> {
- transportService.tell(Protocol.AKKA, workerInfo.getAddress(), destroyRequest);
+ final URL url = ServerURLFactory.destroyContainer2Worker(workerInfo.getAddress());
+ transportService.tell(workerInfo.getProtocol(), url, destroyRequest);
});
log.info("[ContainerService] delete container: {}.", container);
@@ -245,13 +248,11 @@ public class ContainerService {
container.setGmtModified(now);
container.setLastDeployTime(now);
containerInfoRepository.saveAndFlush(container);
+ remote.sendText(String.format("SYSTEM: update current container version=%s successfully!", container.getVersion()));
// 开始部署(需要分批进行)
- Set workerAddressList = workerClusterQueryService.getAllAliveWorkers(container.getAppId())
- .stream()
- .map(WorkerInfo::getAddress)
- .collect(Collectors.toSet());
- if (workerAddressList.isEmpty()) {
+ final List allAliveWorkers = workerClusterQueryService.getAllAliveWorkers(container.getAppId());
+ if (allAliveWorkers.isEmpty()) {
remote.sendText("SYSTEM: there is no worker available now, deploy failed!");
return;
}
@@ -262,10 +263,12 @@ public class ContainerService {
long sleepTime = calculateSleepTime(jarFile.length());
AtomicInteger count = new AtomicInteger();
- workerAddressList.forEach(akkaAddress -> {
- transportService.tell(Protocol.AKKA, akkaAddress, req);
+ allAliveWorkers.forEach(workerInfo -> {
- remote.sendText("SYSTEM: send deploy request to " + akkaAddress);
+ final URL url = ServerURLFactory.deployContainer2Worker(workerInfo.getAddress());
+ transportService.tell(workerInfo.getProtocol(), url, req);
+
+ remote.sendText("SYSTEM: send deploy request to " + url.getAddress());
if (count.incrementAndGet() % DEPLOY_BATCH_NUM == 0) {
CommonUtils.executeIgnoreException(() -> Thread.sleep(sleepTime));
@@ -285,6 +288,7 @@ public class ContainerService {
* @param containerId 容器ID
* @return 拼接好的可阅读字符串
*/
+ @DesignateServer
public String fetchDeployedInfo(Long appId, Long containerId) {
List infoList = workerClusterQueryService.getDeployedContainerInfos(appId, containerId);
@@ -417,7 +421,10 @@ public class ContainerService {
FileUtils.copyFile(jarWithDependency, localFile);
return localFile;
- }finally {
+ } catch (Throwable t) {
+ log.error("[ContainerService] prepareJarFile failed for container: {}", container, t);
+ remote.sendText("SYSTEM: [ERROR] prepare jar file failed: " + ExceptionUtils.getStackTrace(t));
+ } finally {
// 删除工作区数据
FileUtils.forceDelete(workerDir);
}
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/AbWorkerRequestHandler.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/AbWorkerRequestHandler.java
index b0e8047c..90c0e59e 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/AbWorkerRequestHandler.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/AbWorkerRequestHandler.java
@@ -10,6 +10,8 @@ import tech.powerjob.common.request.*;
import tech.powerjob.common.response.AskResponse;
import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.common.utils.NetUtils;
+import tech.powerjob.remote.framework.actor.Handler;
+import tech.powerjob.remote.framework.actor.ProcessType;
import tech.powerjob.server.common.constants.SwitchableStatus;
import tech.powerjob.server.common.module.WorkerInfo;
import tech.powerjob.server.common.utils.SpringUtils;
@@ -28,6 +30,8 @@ import java.util.Optional;
import java.util.concurrent.RejectedExecutionException;
import java.util.stream.Collectors;
+import static tech.powerjob.common.RemoteConstant.*;
+
/**
* wrapper monitor for IWorkerRequestHandler
*
@@ -49,12 +53,13 @@ public abstract class AbWorkerRequestHandler implements IWorkerRequestHandler {
protected abstract void processWorkerHeartbeat0(WorkerHeartbeat heartbeat, WorkerHeartbeatEvent event);
- protected abstract Optional processTaskTrackerReportInstanceStatus0(TaskTrackerReportInstanceStatusReq req, TtReportInstanceStatusEvent event) throws Exception;
+ protected abstract AskResponse processTaskTrackerReportInstanceStatus0(TaskTrackerReportInstanceStatusReq req, TtReportInstanceStatusEvent event) throws Exception;
protected abstract void processWorkerLogReport0(WorkerLogReportReq req, WorkerLogReportEvent event);
@Override
+ @Handler(path = S4W_HANDLER_WORKER_HEARTBEAT, processType = ProcessType.NO_BLOCKING)
public void processWorkerHeartbeat(WorkerHeartbeat heartbeat) {
long startMs = System.currentTimeMillis();
WorkerHeartbeatEvent event = new WorkerHeartbeatEvent()
@@ -71,7 +76,8 @@ public abstract class AbWorkerRequestHandler implements IWorkerRequestHandler {
}
@Override
- public Optional processTaskTrackerReportInstanceStatus(TaskTrackerReportInstanceStatusReq req) {
+ @Handler(path = S4W_HANDLER_REPORT_INSTANCE_STATUS, processType = ProcessType.BLOCKING)
+ public AskResponse processTaskTrackerReportInstanceStatus(TaskTrackerReportInstanceStatusReq req) {
long startMs = System.currentTimeMillis();
TtReportInstanceStatusEvent event = new TtReportInstanceStatusEvent()
.setAppId(req.getAppId())
@@ -86,7 +92,7 @@ public abstract class AbWorkerRequestHandler implements IWorkerRequestHandler {
} catch (Exception e) {
event.setServerProcessStatus(TtReportInstanceStatusEvent.Status.FAILED);
log.error("[WorkerRequestHandler] processTaskTrackerReportInstanceStatus failed for request: {}", req, e);
- return Optional.of(AskResponse.failed(ExceptionUtils.getMessage(e)));
+ return AskResponse.failed(ExceptionUtils.getMessage(e));
} finally {
event.setServerProcessCost(System.currentTimeMillis() - startMs);
monitorService.monitor(event);
@@ -94,6 +100,7 @@ public abstract class AbWorkerRequestHandler implements IWorkerRequestHandler {
}
@Override
+ @Handler(path = S4W_HANDLER_REPORT_LOG, processType = ProcessType.NO_BLOCKING)
public void processWorkerLogReport(WorkerLogReportReq req) {
WorkerLogReportEvent event = new WorkerLogReportEvent()
@@ -113,6 +120,7 @@ public abstract class AbWorkerRequestHandler implements IWorkerRequestHandler {
}
@Override
+ @Handler(path = S4W_HANDLER_QUERY_JOB_CLUSTER, processType = ProcessType.BLOCKING)
public AskResponse processWorkerQueryExecutorCluster(WorkerQueryExecutorClusterReq req) {
AskResponse askResponse;
@@ -137,6 +145,7 @@ public abstract class AbWorkerRequestHandler implements IWorkerRequestHandler {
}
@Override
+ @Handler(path = S4W_HANDLER_WORKER_NEED_DEPLOY_CONTAINER, processType = ProcessType.BLOCKING)
public AskResponse processWorkerNeedDeployContainer(WorkerNeedDeployContainerRequest req) {
String port = environment.getProperty("local.server.port");
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/IWorkerRequestHandler.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/IWorkerRequestHandler.java
index 6fe30e70..7b11ded6 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/IWorkerRequestHandler.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/IWorkerRequestHandler.java
@@ -3,8 +3,6 @@ package tech.powerjob.server.core.handler;
import tech.powerjob.common.request.*;
import tech.powerjob.common.response.AskResponse;
-import java.util.Optional;
-
/**
* 定义 server 与 worker 之间需要处理的协议
*
@@ -24,7 +22,7 @@ public interface IWorkerRequestHandler {
* @param req 上报请求
* @return 响应信息
*/
- Optional processTaskTrackerReportInstanceStatus(TaskTrackerReportInstanceStatusReq req);
+ AskResponse processTaskTrackerReportInstanceStatus(TaskTrackerReportInstanceStatusReq req);
/**
* 处理 worker 查询执行器集群
@@ -34,7 +32,7 @@ public interface IWorkerRequestHandler {
AskResponse processWorkerQueryExecutorCluster(WorkerQueryExecutorClusterReq req);
/**
- * 处理 worker 日志推送请求
+ * 处理 worker 日志推送请求(内部使用线程池异步处理,非阻塞)
* @param req 请求
*/
void processWorkerLogReport(WorkerLogReportReq req);
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/WorkerRequestHandlerHolder.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/WorkerRequestHandlerHolder.java
deleted file mode 100644
index f9c267cc..00000000
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/WorkerRequestHandlerHolder.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package tech.powerjob.server.core.handler;
-
-import org.springframework.stereotype.Component;
-
-
-/**
- * WorkerRequestHandlerHolder
- *
- * @author tjq
- * @since 2022/9/11
- */
-@Component
-public class WorkerRequestHandlerHolder {
-
- private static IWorkerRequestHandler workerRequestHandler;
-
- public WorkerRequestHandlerHolder(IWorkerRequestHandler injectedWorkerRequestHandler) {
- workerRequestHandler = injectedWorkerRequestHandler;
- }
-
- public static IWorkerRequestHandler fetchWorkerRequestHandler() {
- if (workerRequestHandler == null){
- throw new IllegalStateException("WorkerRequestHandlerHolder not initialized!");
- }
- return workerRequestHandler;
- }
-}
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/WorkerRequestHandlerImpl.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/WorkerRequestHandlerImpl.java
index ed4e9206..129571e0 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/WorkerRequestHandlerImpl.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/WorkerRequestHandlerImpl.java
@@ -4,11 +4,13 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
+import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.enums.InstanceStatus;
import tech.powerjob.common.request.TaskTrackerReportInstanceStatusReq;
import tech.powerjob.common.request.WorkerHeartbeat;
import tech.powerjob.common.request.WorkerLogReportReq;
import tech.powerjob.common.response.AskResponse;
+import tech.powerjob.remote.framework.actor.Actor;
import tech.powerjob.server.core.instance.InstanceLogService;
import tech.powerjob.server.core.instance.InstanceManager;
import tech.powerjob.server.core.workflow.WorkflowInstanceManager;
@@ -20,8 +22,6 @@ import tech.powerjob.server.persistence.remote.repository.ContainerInfoRepositor
import tech.powerjob.server.remote.worker.WorkerClusterManagerService;
import tech.powerjob.server.remote.worker.WorkerClusterQueryService;
-import java.util.Optional;
-
/**
* receive and process worker's request
*
@@ -30,6 +30,7 @@ import java.util.Optional;
*/
@Slf4j
@Component
+@Actor(path = RemoteConstant.S4W_PATH)
public class WorkerRequestHandlerImpl extends AbWorkerRequestHandler {
private final InstanceManager instanceManager;
@@ -52,7 +53,7 @@ public class WorkerRequestHandlerImpl extends AbWorkerRequestHandler {
}
@Override
- protected Optional processTaskTrackerReportInstanceStatus0(TaskTrackerReportInstanceStatusReq req, TtReportInstanceStatusEvent event) throws Exception {
+ protected AskResponse processTaskTrackerReportInstanceStatus0(TaskTrackerReportInstanceStatusReq req, TtReportInstanceStatusEvent event) throws Exception {
// 2021/02/05 如果是工作流中的实例先尝试更新上下文信息,再更新实例状态,这里一定不会有异常
if (req.getWfInstanceId() != null && !CollectionUtils.isEmpty(req.getAppendedWfContext())) {
// 更新工作流上下文信息
@@ -63,9 +64,10 @@ public class WorkerRequestHandlerImpl extends AbWorkerRequestHandler {
// 结束状态(成功/失败)需要回复消息
if (InstanceStatus.FINISHED_STATUS.contains(req.getInstanceStatus())) {
- return Optional.of(AskResponse.succeed(null));
+ return AskResponse.succeed(null);
}
- return Optional.empty();
+
+ return null;
}
@Override
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/Initializer.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/Initializer.java
deleted file mode 100644
index d34d7469..00000000
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/Initializer.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package tech.powerjob.server.core.handler.impl;
-
-import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
-import org.springframework.stereotype.Component;
-import tech.powerjob.common.RemoteConstant;
-import tech.powerjob.server.remote.transport.starter.AkkaStarter;
-import tech.powerjob.server.remote.transport.starter.VertXStarter;
-
-import javax.annotation.PostConstruct;
-
-/**
- * 初始化器
- *
- * @author tjq
- * @since 2022/9/11
- */
-@Component
-@ConditionalOnExpression("'${execution.env}'!='test'")
-public class Initializer {
-
- @PostConstruct
- public void initHandler() {
- // init akka
- AkkaStarter.actorSystem.actorOf(WorkerRequestAkkaHandler.defaultProps(), RemoteConstant.SERVER_ACTOR_NAME);
- // init vert.x
- VertXStarter.vertx.deployVerticle(new WorkerRequestHttpHandler());
- }
-}
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/WorkerRequestAkkaHandler.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/WorkerRequestAkkaHandler.java
deleted file mode 100644
index 26f18be0..00000000
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/WorkerRequestAkkaHandler.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package tech.powerjob.server.core.handler.impl;
-
-import akka.actor.AbstractActor;
-import akka.actor.Props;
-import akka.routing.DefaultResizer;
-import akka.routing.RoundRobinPool;
-import tech.powerjob.common.request.*;
-import tech.powerjob.common.response.AskResponse;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Optional;
-
-import static tech.powerjob.server.core.handler.WorkerRequestHandlerHolder.fetchWorkerRequestHandler;
-
-/**
- * 处理 Worker 请求
- *
- * @author tjq
- * @since 2020/3/30
- */
-@Slf4j
-public class WorkerRequestAkkaHandler extends AbstractActor {
-
-
- public static Props defaultProps(){
- return Props.create(WorkerRequestAkkaHandler.class)
- .withDispatcher("akka.w-r-c-d")
- .withRouter(
- new RoundRobinPool(Runtime.getRuntime().availableProcessors() * 4)
- .withResizer(new DefaultResizer(
- Runtime.getRuntime().availableProcessors() * 4,
- Runtime.getRuntime().availableProcessors() * 10,
- 1,
- 0.2d,
- 0.3d,
- 0.1d,
- 10
- ))
- );
- }
-
- @Override
- public Receive createReceive() {
- return receiveBuilder()
- .match(WorkerHeartbeat.class, hb -> fetchWorkerRequestHandler().processWorkerHeartbeat(hb))
- .match(TaskTrackerReportInstanceStatusReq.class, this::onReceiveTaskTrackerReportInstanceStatusReq)
- .match(WorkerLogReportReq.class, req -> fetchWorkerRequestHandler().processWorkerLogReport(req))
- .match(WorkerNeedDeployContainerRequest.class, this::onReceiveWorkerNeedDeployContainerRequest)
- .match(WorkerQueryExecutorClusterReq.class, this::onReceiveWorkerQueryExecutorClusterReq)
- .matchAny(obj -> log.warn("[WorkerRequestAkkaHandler] receive unknown request: {}.", obj))
- .build();
- }
-
- @Override
- public void preStart() throws Exception {
- super.preStart();
- log.debug("[WorkerRequestAkkaHandler]init WorkerRequestActor");
- }
-
-
- @Override
- public void postStop() throws Exception {
- super.postStop();
- log.debug("[WorkerRequestAkkaHandler]stop WorkerRequestActor");
- }
-
- /**
- * 处理 instance 状态
- * @param req 任务实例的状态上报请求
- */
- private void onReceiveTaskTrackerReportInstanceStatusReq(TaskTrackerReportInstanceStatusReq req) {
-
- try {
- Optional askResponseOpt = fetchWorkerRequestHandler().processTaskTrackerReportInstanceStatus(req);
- if (askResponseOpt.isPresent()) {
- getSender().tell(AskResponse.succeed(null), getSelf());
- }
- }catch (Exception e) {
- log.error("[WorkerRequestAkkaHandler] update instance status failed for request: {}.", req, e);
- }
- }
-
- /**
- * 处理 Worker容器部署请求
- * @param req 容器部署请求
- */
- private void onReceiveWorkerNeedDeployContainerRequest(WorkerNeedDeployContainerRequest req) {
- getSender().tell(fetchWorkerRequestHandler().processWorkerNeedDeployContainer(req), getSelf());
- }
-
- /**
- * 处理 worker 请求获取当前任务所有处理器节点的请求
- * @param req jobId + appId
- */
- private void onReceiveWorkerQueryExecutorClusterReq(WorkerQueryExecutorClusterReq req) {
-
- getSender().tell(fetchWorkerRequestHandler().processWorkerQueryExecutorCluster(req), getSelf());
- }
-
-}
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/WorkerRequestHttpHandler.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/WorkerRequestHttpHandler.java
deleted file mode 100644
index 3749158f..00000000
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/handler/impl/WorkerRequestHttpHandler.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package tech.powerjob.server.core.handler.impl;
-
-import tech.powerjob.common.OmsConstant;
-import tech.powerjob.common.ProtocolConstant;
-import tech.powerjob.common.request.TaskTrackerReportInstanceStatusReq;
-import tech.powerjob.common.request.WorkerHeartbeat;
-import tech.powerjob.common.request.WorkerLogReportReq;
-import tech.powerjob.common.response.AskResponse;
-import tech.powerjob.common.response.ResultDTO;
-import tech.powerjob.server.common.PowerJobServerConfigKey;
-import tech.powerjob.server.common.utils.PropertyUtils;
-import io.vertx.core.AbstractVerticle;
-import io.vertx.core.http.HttpServer;
-import io.vertx.core.http.HttpServerOptions;
-import io.vertx.core.json.JsonObject;
-import io.vertx.ext.web.Router;
-import io.vertx.ext.web.RoutingContext;
-import io.vertx.ext.web.handler.BodyHandler;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-
-import java.util.Properties;
-
-import static tech.powerjob.server.core.handler.WorkerRequestHandlerHolder.fetchWorkerRequestHandler;
-
-/**
- * WorkerRequestHandler
- *
- * @author tjq
- * @since 2021/2/8
- */
-@Slf4j
-public class WorkerRequestHttpHandler extends AbstractVerticle {
-
- @Override
- public void start() throws Exception {
-
- Properties properties = PropertyUtils.getProperties();
- int port = Integer.parseInt(properties.getProperty(PowerJobServerConfigKey.HTTP_PORT, String.valueOf(OmsConstant.SERVER_DEFAULT_HTTP_PORT)));
-
- HttpServerOptions options = new HttpServerOptions();
- HttpServer server = vertx.createHttpServer(options);
-
- Router router = Router.router(vertx);
- router.route().handler(BodyHandler.create());
- router.post(ProtocolConstant.SERVER_PATH_HEARTBEAT)
- .handler(ctx -> {
- WorkerHeartbeat heartbeat = ctx.getBodyAsJson().mapTo(WorkerHeartbeat.class);
- fetchWorkerRequestHandler().processWorkerHeartbeat(heartbeat);
- success(ctx);
- });
- router.post(ProtocolConstant.SERVER_PATH_STATUS_REPORT)
- .blockingHandler(ctx -> {
- TaskTrackerReportInstanceStatusReq req = ctx.getBodyAsJson().mapTo(TaskTrackerReportInstanceStatusReq.class);
- try {
- fetchWorkerRequestHandler().processTaskTrackerReportInstanceStatus(req);
- out(ctx, AskResponse.succeed(null));
- } catch (Exception e) {
- log.error("[WorkerRequestHttpHandler] update instance status failed for request: {}.", req, e);
- out(ctx, AskResponse.failed(ExceptionUtils.getMessage(e)));
- }
- });
- router.post(ProtocolConstant.SERVER_PATH_LOG_REPORT)
- .blockingHandler(ctx -> {
- WorkerLogReportReq req = ctx.getBodyAsJson().mapTo(WorkerLogReportReq.class);
- fetchWorkerRequestHandler().processWorkerLogReport(req);
- success(ctx);
- });
- server.requestHandler(router).listen(port);
- }
-
- private static void out(RoutingContext ctx, Object msg) {
- ctx.response()
- .putHeader(OmsConstant.HTTP_HEADER_CONTENT_TYPE, OmsConstant.JSON_MEDIA_TYPE)
- .end(JsonObject.mapFrom(msg).encode());
- }
-
- private static void success(RoutingContext ctx) {
- out(ctx, ResultDTO.success(null));
- }
-}
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/instance/InstanceManager.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/instance/InstanceManager.java
index 40f066e1..ee810483 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/instance/InstanceManager.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/instance/InstanceManager.java
@@ -2,15 +2,15 @@ package tech.powerjob.server.core.instance;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
-import org.apache.commons.lang3.StringUtils;
import tech.powerjob.common.enums.InstanceStatus;
-import tech.powerjob.common.enums.Protocol;
import tech.powerjob.common.enums.TimeExpressionType;
import tech.powerjob.common.model.LifeCycle;
import tech.powerjob.common.request.ServerStopInstanceReq;
import tech.powerjob.common.request.TaskTrackerReportInstanceStatusReq;
+import tech.powerjob.remote.framework.base.URL;
import tech.powerjob.server.common.module.WorkerInfo;
import tech.powerjob.server.common.timewheel.holder.HashedWheelTimerHolder;
import tech.powerjob.server.common.utils.SpringUtils;
@@ -22,10 +22,10 @@ import tech.powerjob.server.persistence.remote.model.InstanceInfoDO;
import tech.powerjob.server.persistence.remote.model.JobInfoDO;
import tech.powerjob.server.persistence.remote.model.UserInfoDO;
import tech.powerjob.server.persistence.remote.repository.InstanceInfoRepository;
-import tech.powerjob.server.remote.transport.TransportService;
+import tech.powerjob.server.remote.transporter.impl.ServerURLFactory;
+import tech.powerjob.server.remote.transporter.TransportService;
import tech.powerjob.server.remote.worker.WorkerClusterQueryService;
-import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Optional;
@@ -176,7 +176,8 @@ public class InstanceManager {
if (workerInfoOpt.isPresent()) {
ServerStopInstanceReq stopInstanceReq = new ServerStopInstanceReq(instanceId);
WorkerInfo workerInfo = workerInfoOpt.get();
- transportService.tell(Protocol.of(workerInfo.getProtocol()), workerInfo.getAddress(), stopInstanceReq);
+ final URL url = ServerURLFactory.stopInstance2Worker(workerInfo.getAddress());
+ transportService.tell(workerInfo.getProtocol(), url, stopInstanceReq);
}
}
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/instance/InstanceService.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/instance/InstanceService.java
index 2d465b96..53071a6d 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/instance/InstanceService.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/instance/InstanceService.java
@@ -5,15 +5,16 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import tech.powerjob.common.PowerQuery;
+import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.SystemInstanceResult;
import tech.powerjob.common.enums.InstanceStatus;
-import tech.powerjob.common.enums.Protocol;
import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.model.InstanceDetail;
import tech.powerjob.common.request.ServerQueryInstanceStatusReq;
import tech.powerjob.common.request.ServerStopInstanceReq;
import tech.powerjob.common.response.AskResponse;
import tech.powerjob.common.response.InstanceInfoDTO;
+import tech.powerjob.remote.framework.base.URL;
import tech.powerjob.server.common.constants.InstanceType;
import tech.powerjob.server.common.module.WorkerInfo;
import tech.powerjob.server.common.timewheel.TimerFuture;
@@ -26,12 +27,14 @@ import tech.powerjob.server.persistence.remote.model.JobInfoDO;
import tech.powerjob.server.persistence.remote.repository.InstanceInfoRepository;
import tech.powerjob.server.persistence.remote.repository.JobInfoRepository;
import tech.powerjob.server.remote.server.redirector.DesignateServer;
-import tech.powerjob.server.remote.transport.TransportService;
+import tech.powerjob.server.remote.transporter.impl.ServerURLFactory;
+import tech.powerjob.server.remote.transporter.TransportService;
import tech.powerjob.server.remote.worker.WorkerClusterQueryService;
import java.util.Date;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static tech.powerjob.common.enums.InstanceStatus.RUNNING;
@@ -136,7 +139,7 @@ public class InstanceService {
if (workerInfoOpt.isPresent()) {
ServerStopInstanceReq req = new ServerStopInstanceReq(instanceId);
WorkerInfo workerInfo = workerInfoOpt.get();
- transportService.tell(Protocol.of(workerInfo.getProtocol()), workerInfo.getAddress(), req);
+ transportService.tell(workerInfo.getProtocol(), ServerURLFactory.stopInstance2Worker(workerInfo.getAddress()), req);
log.info("[Instance-{}] update instanceInfo and send 'stopInstance' request succeed.", instanceId);
} else {
log.warn("[Instance-{}] update instanceInfo successfully but can't find TaskTracker to stop instance", instanceId);
@@ -280,7 +283,10 @@ public class InstanceService {
WorkerInfo workerInfo = workerInfoOpt.get();
ServerQueryInstanceStatusReq req = new ServerQueryInstanceStatusReq(instanceId);
try {
- AskResponse askResponse = transportService.ask(Protocol.of(workerInfo.getProtocol()), workerInfo.getAddress(), req);
+ final URL url = ServerURLFactory.queryInstance2Worker(workerInfo.getAddress());
+ AskResponse askResponse = transportService.ask(workerInfo.getProtocol(), url, req, AskResponse.class)
+ .toCompletableFuture()
+ .get(RemoteConstant.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (askResponse.isSuccess()) {
InstanceDetail instanceDetail = askResponse.getData(InstanceDetail.class);
instanceDetail.setRunningTimes(instanceInfoDO.getRunningTimes());
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/InstanceStatusCheckService.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/InstanceStatusCheckService.java
index 879cd749..4652904f 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/InstanceStatusCheckService.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/InstanceStatusCheckService.java
@@ -22,9 +22,8 @@ import tech.powerjob.server.persistence.remote.model.WorkflowInfoDO;
import tech.powerjob.server.persistence.remote.model.WorkflowInstanceInfoDO;
import tech.powerjob.server.persistence.remote.model.brief.BriefInstanceInfo;
import tech.powerjob.server.persistence.remote.repository.*;
-import tech.powerjob.server.remote.transport.starter.AkkaStarter;
+import tech.powerjob.server.remote.transporter.TransportService;
-import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@@ -49,6 +48,8 @@ public class InstanceStatusCheckService {
public static final long CHECK_INTERVAL = 10000;
+ private final TransportService transportService;
+
private final DispatchService dispatchService;
private final InstanceManager instanceManager;
@@ -61,7 +62,6 @@ public class InstanceStatusCheckService {
private final InstanceInfoRepository instanceInfoRepository;
-
private final WorkflowInfoRepository workflowInfoRepository;
private final WorkflowInstanceInfoRepository workflowInstanceInfoRepository;
@@ -69,7 +69,7 @@ public class InstanceStatusCheckService {
public void checkWorkflowInstance() {
Stopwatch stopwatch = Stopwatch.createStarted();
// 查询 DB 获取该 Server 需要负责的 AppGroup
- List allAppIds = appInfoRepository.listAppIdByCurrentServer(AkkaStarter.getActorSystemAddress());
+ List allAppIds = appInfoRepository.listAppIdByCurrentServer(transportService.defaultProtocol().getAddress());
if (CollectionUtils.isEmpty(allAppIds)) {
log.info("[InstanceStatusChecker] current server has no app's job to check");
return;
@@ -89,7 +89,7 @@ public class InstanceStatusCheckService {
public void checkWaitingDispatchInstance() {
Stopwatch stopwatch = Stopwatch.createStarted();
// 查询 DB 获取该 Server 需要负责的 AppGroup
- List allAppIds = appInfoRepository.listAppIdByCurrentServer(AkkaStarter.getActorSystemAddress());
+ List allAppIds = appInfoRepository.listAppIdByCurrentServer(transportService.defaultProtocol().getAddress());
if (CollectionUtils.isEmpty(allAppIds)) {
log.info("[InstanceStatusChecker] current server has no app's job to check");
return;
@@ -110,7 +110,7 @@ public class InstanceStatusCheckService {
public void checkWaitingWorkerReceiveInstance() {
Stopwatch stopwatch = Stopwatch.createStarted();
// 查询 DB 获取该 Server 需要负责的 AppGroup
- List allAppIds = appInfoRepository.listAppIdByCurrentServer(AkkaStarter.getActorSystemAddress());
+ List allAppIds = appInfoRepository.listAppIdByCurrentServer(transportService.defaultProtocol().getAddress());
if (CollectionUtils.isEmpty(allAppIds)) {
log.info("[InstanceStatusChecker] current server has no app's job to check");
return;
@@ -131,7 +131,7 @@ public class InstanceStatusCheckService {
public void checkRunningInstance() {
Stopwatch stopwatch = Stopwatch.createStarted();
// 查询 DB 获取该 Server 需要负责的 AppGroup
- List allAppIds = appInfoRepository.listAppIdByCurrentServer(AkkaStarter.getActorSystemAddress());
+ List allAppIds = appInfoRepository.listAppIdByCurrentServer(transportService.defaultProtocol().getAddress());
if (CollectionUtils.isEmpty(allAppIds)) {
log.info("[InstanceStatusChecker] current server has no app's job to check");
return;
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/PowerScheduleService.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/PowerScheduleService.java
index 33bf97f3..5f65fa07 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/PowerScheduleService.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/PowerScheduleService.java
@@ -23,10 +23,9 @@ import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
import tech.powerjob.server.persistence.remote.repository.InstanceInfoRepository;
import tech.powerjob.server.persistence.remote.repository.JobInfoRepository;
import tech.powerjob.server.persistence.remote.repository.WorkflowInfoRepository;
-import tech.powerjob.server.remote.transport.starter.AkkaStarter;
+import tech.powerjob.server.remote.transporter.TransportService;
import tech.powerjob.server.remote.worker.WorkerClusterManagerService;
-import javax.annotation.Resource;
import java.util.*;
/**
@@ -47,6 +46,7 @@ public class PowerScheduleService {
*/
private static final int MAX_APP_NUM = 10;
+ private final TransportService transportService;
private final DispatchService dispatchService;
private final InstanceService instanceService;
@@ -72,7 +72,7 @@ public class PowerScheduleService {
long start = System.currentTimeMillis();
// 调度 CRON 表达式 JOB
try {
- final List allAppIds = appInfoRepository.listAppIdByCurrentServer(AkkaStarter.getActorSystemAddress());
+ final List allAppIds = appInfoRepository.listAppIdByCurrentServer(transportService.defaultProtocol().getAddress());
if (CollectionUtils.isEmpty(allAppIds)) {
log.info("[CronJobSchedule] current server has no app's job to schedule.");
return;
@@ -92,7 +92,7 @@ public class PowerScheduleService {
long start = System.currentTimeMillis();
// 调度 CRON 表达式 WORKFLOW
try {
- final List allAppIds = appInfoRepository.listAppIdByCurrentServer(AkkaStarter.getActorSystemAddress());
+ final List allAppIds = appInfoRepository.listAppIdByCurrentServer(transportService.defaultProtocol().getAddress());
if (CollectionUtils.isEmpty(allAppIds)) {
log.info("[CronWorkflowSchedule] current server has no app's workflow to schedule.");
return;
@@ -113,7 +113,7 @@ public class PowerScheduleService {
long start = System.currentTimeMillis();
// 调度 FIX_RATE/FIX_DELAY 表达式 JOB
try {
- final List allAppIds = appInfoRepository.listAppIdByCurrentServer(AkkaStarter.getActorSystemAddress());
+ final List allAppIds = appInfoRepository.listAppIdByCurrentServer(transportService.defaultProtocol().getAddress());
if (CollectionUtils.isEmpty(allAppIds)) {
log.info("[FrequentJobSchedule] current server has no app's job to schedule.");
return;
@@ -132,7 +132,7 @@ public class PowerScheduleService {
public void cleanData() {
try {
- final List allAppIds = appInfoRepository.listAppIdByCurrentServer(AkkaStarter.getActorSystemAddress());
+ final List allAppIds = appInfoRepository.listAppIdByCurrentServer(transportService.defaultProtocol().getAddress());
if (allAppIds.isEmpty()) {
return;
}
diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/service/CacheService.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/service/CacheService.java
index 491ea328..c4ae22a4 100644
--- a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/service/CacheService.java
+++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/service/CacheService.java
@@ -44,18 +44,22 @@ public class CacheService {
jobId2JobNameCache = CacheBuilder.newBuilder()
.expireAfterWrite(Duration.ofMinutes(1))
.maximumSize(512)
+ .softValues()
.build();
workflowId2WorkflowNameCache = CacheBuilder.newBuilder()
.expireAfterWrite(Duration.ofMinutes(1))
.maximumSize(512)
+ .softValues()
.build();
instanceId2AppId = CacheBuilder.newBuilder()
.maximumSize(1024)
+ .softValues()
.build();
jobId2AppId = CacheBuilder.newBuilder()
.maximumSize(1024)
+ .softValues()
.build();
}
diff --git a/powerjob-server/powerjob-server-extension/pom.xml b/powerjob-server/powerjob-server-extension/pom.xml
index 29ab5693..4ed8e548 100644
--- a/powerjob-server/powerjob-server-extension/pom.xml
+++ b/powerjob-server/powerjob-server-extension/pom.xml
@@ -5,7 +5,7 @@
powerjob-server
tech.powerjob
- 4.2.1
+ 4.3.0
../pom.xml
4.0.0
diff --git a/powerjob-server/powerjob-server-extension/src/main/java/tech/powerjob/server/extension/defaultimpl/alarm/impl/DingTalkAlarmService.java b/powerjob-server/powerjob-server-extension/src/main/java/tech/powerjob/server/extension/defaultimpl/alarm/impl/DingTalkAlarmService.java
index b42d9c05..57eb4d35 100644
--- a/powerjob-server/powerjob-server-extension/src/main/java/tech/powerjob/server/extension/defaultimpl/alarm/impl/DingTalkAlarmService.java
+++ b/powerjob-server/powerjob-server-extension/src/main/java/tech/powerjob/server/extension/defaultimpl/alarm/impl/DingTalkAlarmService.java
@@ -1,25 +1,24 @@
package tech.powerjob.server.extension.defaultimpl.alarm.impl;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Service;
import tech.powerjob.common.OmsConstant;
import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.utils.NetUtils;
import tech.powerjob.server.common.PowerJobServerConfigKey;
import tech.powerjob.server.common.SJ;
-import tech.powerjob.server.persistence.remote.model.UserInfoDO;
-import tech.powerjob.server.extension.defaultimpl.alarm.module.Alarm;
import tech.powerjob.server.extension.Alarmable;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.core.env.Environment;
-import org.springframework.stereotype.Service;
+import tech.powerjob.server.extension.defaultimpl.alarm.module.Alarm;
+import tech.powerjob.server.persistence.remote.model.UserInfoDO;
import javax.annotation.PostConstruct;
-import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
@@ -108,7 +107,7 @@ public class DingTalkAlarmService implements Alarmable {
}
this.agentId = Long.valueOf(agentId);
dingTalkUtils = new DingTalkUtils(appKey, appSecret);
- mobile2UserIdCache = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).build();
+ mobile2UserIdCache = CacheBuilder.newBuilder().maximumSize(CACHE_SIZE).softValues().build();
log.info("[DingTalkAlarmService] init DingTalkAlarmService successfully!");
}
diff --git a/powerjob-server/powerjob-server-migrate/pom.xml b/powerjob-server/powerjob-server-migrate/pom.xml
index 9b8b32b6..282cee69 100644
--- a/powerjob-server/powerjob-server-migrate/pom.xml
+++ b/powerjob-server/powerjob-server-migrate/pom.xml
@@ -5,7 +5,7 @@
powerjob-server
tech.powerjob
- 4.2.1
+ 4.3.0
../pom.xml
4.0.0
diff --git a/powerjob-server/powerjob-server-monitor/pom.xml b/powerjob-server/powerjob-server-monitor/pom.xml
index c54bb0df..ccf24dc4 100644
--- a/powerjob-server/powerjob-server-monitor/pom.xml
+++ b/powerjob-server/powerjob-server-monitor/pom.xml
@@ -5,7 +5,7 @@
powerjob-server
tech.powerjob
- 4.2.1
+ 4.3.0
../pom.xml
4.0.0
diff --git a/powerjob-server/powerjob-server-persistence/pom.xml b/powerjob-server/powerjob-server-persistence/pom.xml
index a5e6b9f4..bf54efb6 100644
--- a/powerjob-server/powerjob-server-persistence/pom.xml
+++ b/powerjob-server/powerjob-server-persistence/pom.xml
@@ -5,7 +5,7 @@
powerjob-server
tech.powerjob
- 4.2.1
+ 4.3.0
../pom.xml
4.0.0
diff --git a/powerjob-server/powerjob-server-remote/pom.xml b/powerjob-server/powerjob-server-remote/pom.xml
index 878289d0..62338062 100644
--- a/powerjob-server/powerjob-server-remote/pom.xml
+++ b/powerjob-server/powerjob-server-remote/pom.xml
@@ -5,7 +5,7 @@
powerjob-server
tech.powerjob
- 4.2.1
+ 4.3.0
../pom.xml
4.0.0
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/FriendActor.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/FriendActor.java
new file mode 100644
index 00000000..8d7d56e3
--- /dev/null
+++ b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/FriendActor.java
@@ -0,0 +1,57 @@
+package tech.powerjob.server.remote.server;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.springframework.stereotype.Component;
+import tech.powerjob.common.response.AskResponse;
+import tech.powerjob.common.serialize.JsonUtils;
+import tech.powerjob.remote.framework.actor.Actor;
+import tech.powerjob.remote.framework.actor.Handler;
+import tech.powerjob.remote.framework.actor.ProcessType;
+import tech.powerjob.server.remote.server.election.Ping;
+import tech.powerjob.server.remote.server.redirector.RemoteProcessReq;
+import tech.powerjob.server.remote.server.redirector.RemoteRequestProcessor;
+import tech.powerjob.server.remote.transporter.TransportService;
+
+import static tech.powerjob.common.RemoteConstant.*;
+
+/**
+ * 处理朋友们的信息(处理服务器与服务器之间的通讯)
+ *
+ * @author tjq
+ * @since 2020/4/9
+ */
+@Slf4j
+@Component
+@Actor(path = S4S_PATH)
+public class FriendActor {
+
+ private final TransportService transportService;
+
+ public FriendActor(TransportService transportService) {
+ this.transportService = transportService;
+ }
+
+ /**
+ * 处理存活检测的请求
+ */
+ @Handler(path = S4S_HANDLER_PING, processType = ProcessType.NO_BLOCKING)
+ public AskResponse onReceivePing(Ping ping) {
+ return AskResponse.succeed(transportService.allProtocols());
+ }
+
+ @Handler(path = S4S_HANDLER_PROCESS, processType = ProcessType.BLOCKING)
+ public AskResponse onReceiveRemoteProcessReq(RemoteProcessReq req) {
+
+ AskResponse response = new AskResponse();
+ response.setSuccess(true);
+ try {
+ response.setData(JsonUtils.toBytes(RemoteRequestProcessor.processRemoteRequest(req)));
+ } catch (Throwable t) {
+ log.error("[FriendActor] process remote request[{}] failed!", req, t);
+ response.setSuccess(false);
+ response.setMessage(ExceptionUtils.getMessage(t));
+ }
+ return response;
+ }
+}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/FriendRequestHandler.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/FriendRequestHandler.java
deleted file mode 100644
index edda488e..00000000
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/FriendRequestHandler.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package tech.powerjob.server.remote.server;
-
-import akka.actor.AbstractActor;
-import akka.actor.Props;
-import akka.routing.DefaultResizer;
-import akka.routing.RoundRobinPool;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import tech.powerjob.common.response.AskResponse;
-import tech.powerjob.common.serialize.JsonUtils;
-import tech.powerjob.server.remote.server.election.Ping;
-import tech.powerjob.server.remote.server.redirector.RemoteProcessReq;
-import tech.powerjob.server.remote.server.redirector.RemoteRequestProcessor;
-import tech.powerjob.server.remote.transport.TransportService;
-
-/**
- * 处理朋友们的信息(处理服务器与服务器之间的通讯)
- *
- * @author tjq
- * @since 2020/4/9
- */
-@Slf4j
-public class FriendRequestHandler extends AbstractActor {
-
-
- public static Props defaultProps() {
- return Props.create(FriendRequestHandler.class)
- .withDispatcher("akka.friend-request-actor-dispatcher")
- .withRouter(
- new RoundRobinPool(Runtime.getRuntime().availableProcessors() * 4)
- .withResizer(new DefaultResizer(
- Runtime.getRuntime().availableProcessors() * 4,
- Runtime.getRuntime().availableProcessors() * 10,
- 1,
- 0.2d,
- 0.3d,
- 0.1d,
- 10
- ))
- );
- }
-
- @Override
- public Receive createReceive() {
- return receiveBuilder()
- .match(Ping.class, this::onReceivePing)
- .match(RemoteProcessReq.class, this::onReceiveRemoteProcessReq)
- .matchAny(obj -> log.warn("[FriendActor] receive unknown request: {}.", obj))
- .build();
- }
-
-
- @Override
- public void preStart() throws Exception {
- super.preStart();
- log.debug("[FriendRequestHandler]init FriendRequestActor");
- }
-
-
- @Override
- public void postStop() throws Exception {
- super.postStop();
- log.debug("[FriendRequestHandler]stop FriendRequestActor");
- }
-
- /**
- * 处理存活检测的请求
- */
- private void onReceivePing(Ping ping) {
- getSender().tell(AskResponse.succeed(TransportService.getAllAddress()), getSelf());
- }
-
- private void onReceiveRemoteProcessReq(RemoteProcessReq req) {
-
- AskResponse response = new AskResponse();
- response.setSuccess(true);
- try {
- response.setData(JsonUtils.toBytes(RemoteRequestProcessor.processRemoteRequest(req)));
- } catch (Throwable t) {
- log.error("[FriendActor] process remote request[{}] failed!", req, t);
- response.setSuccess(false);
- response.setMessage(ExceptionUtils.getMessage(t));
- }
- getSender().tell(response, getSelf());
- }
-}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/election/ServerElectionService.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/election/ServerElectionService.java
index 1db65201..5b0eb819 100644
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/election/ServerElectionService.java
+++ b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/election/ServerElectionService.java
@@ -1,29 +1,27 @@
package tech.powerjob.server.remote.server.election;
-import akka.actor.ActorSelection;
-import akka.pattern.Patterns;
import com.alibaba.fastjson.JSONObject;
-import tech.powerjob.common.exception.PowerJobException;
-import tech.powerjob.common.enums.Protocol;
-import tech.powerjob.common.response.AskResponse;
-import tech.powerjob.common.serialize.JsonUtils;
-import tech.powerjob.server.extension.LockService;
-import tech.powerjob.server.persistence.remote.model.AppInfoDO;
-import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
-import tech.powerjob.server.remote.transport.TransportService;
-import tech.powerjob.server.remote.transport.starter.AkkaStarter;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
+import tech.powerjob.common.enums.Protocol;
+import tech.powerjob.common.exception.PowerJobException;
+import tech.powerjob.common.request.ServerDiscoveryRequest;
+import tech.powerjob.common.response.AskResponse;
+import tech.powerjob.common.serialize.JsonUtils;
+import tech.powerjob.remote.framework.base.URL;
+import tech.powerjob.server.extension.LockService;
+import tech.powerjob.server.persistence.remote.model.AppInfoDO;
+import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
+import tech.powerjob.server.remote.transporter.ProtocolInfo;
+import tech.powerjob.server.remote.transporter.impl.ServerURLFactory;
+import tech.powerjob.server.remote.transporter.TransportService;
-import javax.annotation.Resource;
-import java.time.Duration;
import java.util.Date;
import java.util.Optional;
import java.util.Set;
-import java.util.concurrent.CompletionStage;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -56,18 +54,23 @@ public class ServerElectionService {
this.accurateSelectServerPercentage = accurateSelectServerPercentage;
}
- public String elect(Long appId, String protocol, String currentServer) {
+ public String elect(ServerDiscoveryRequest request) {
if (!accurate()) {
+ final String currentServer = request.getCurrentServer();
// 如果是本机,就不需要查数据库那么复杂的操作了,直接返回成功
- if (getProtocolServerAddress(protocol).equals(currentServer)) {
+ Optional localProtocolInfoOpt = Optional.ofNullable(transportService.allProtocols().get(request.getProtocol()));
+ if (localProtocolInfoOpt.isPresent() && localProtocolInfoOpt.get().getAddress().equals(currentServer)) {
+ log.debug("[ServerElectionService] this server[{}] is worker's current server, skip check", currentServer);
return currentServer;
}
}
- return getServer0(appId, protocol);
+ return getServer0(request);
}
- private String getServer0(Long appId, String protocol) {
+ private String getServer0(ServerDiscoveryRequest discoveryRequest) {
+ final Long appId = discoveryRequest.getAppId();
+ final String protocol = discoveryRequest.getProtocol();
Set downServerCache = Sets.newHashSet();
for (int i = 0; i < RETRY_TIMES; i++) {
@@ -103,17 +106,20 @@ public class ServerElectionService {
return address;
}
- // 篡位,本机作为Server
- // 注意,写入 AppInfoDO#currentServer 的永远是 ActorSystem 的地址,仅在返回的时候特殊处理
- appInfo.setCurrentServer(transportService.getTransporter(Protocol.AKKA).getAddress());
- appInfo.setGmtModified(new Date());
+ // 篡位,如果本机存在协议,则作为Server调度该 worker
+ final ProtocolInfo targetProtocolInfo = transportService.allProtocols().get(protocol);
+ if (targetProtocolInfo != null) {
+ // 注意,写入 AppInfoDO#currentServer 的永远是 default 的地址,仅在返回的时候特殊处理为协议地址
+ appInfo.setCurrentServer(transportService.defaultProtocol().getAddress());
+ appInfo.setGmtModified(new Date());
- appInfoRepository.saveAndFlush(appInfo);
- log.info("[ServerElection] this server({}) become the new server for app(appId={}).", appInfo.getCurrentServer(), appId);
- return getProtocolServerAddress(protocol);
+ appInfoRepository.saveAndFlush(appInfo);
+ log.info("[ServerElection] this server({}) become the new server for app(appId={}).", appInfo.getCurrentServer(), appId);
+ return targetProtocolInfo.getAddress();
+ }
}catch (Exception e) {
log.error("[ServerElection] write new server to db failed for app {}.", appName, e);
- }finally {
+ } finally {
lockService.unlock(lockName);
}
}
@@ -139,16 +145,25 @@ public class ServerElectionService {
Ping ping = new Ping();
ping.setCurrentTime(System.currentTimeMillis());
- ActorSelection serverActor = AkkaStarter.getFriendActor(serverAddress);
+ URL targetUrl = ServerURLFactory.ping2Friend(serverAddress);
try {
- CompletionStage askCS = Patterns.ask(serverActor, ping, Duration.ofMillis(PING_TIMEOUT_MS));
- AskResponse response = (AskResponse) askCS.toCompletableFuture().get(PING_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- downServerCache.remove(serverAddress);
+ AskResponse response = transportService.ask(Protocol.HTTP.name(), targetUrl, ping, AskResponse.class)
+ .toCompletableFuture()
+ .get(PING_TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (response.isSuccess()) {
- return JsonUtils.parseObject(response.getData(), JSONObject.class).getString(protocol);
+ // 检测通过的是远程 server 的暴露地址,需要返回 worker 需要的协议地址
+ final JSONObject protocolInfo = JsonUtils.parseObject(response.getData(), JSONObject.class).getJSONObject(protocol);
+ if (protocolInfo != null) {
+ downServerCache.remove(serverAddress);
+ final String protocolAddress = protocolInfo.toJavaObject(ProtocolInfo.class).getAddress();
+ log.info("[ServerElection] server[{}] is active, it will be the master, final protocol address={}", serverAddress, protocolAddress);
+ return protocolAddress;
+ } else {
+ log.warn("[ServerElection] server[{}] is active but don't have target protocol", serverAddress);
+ }
}
}catch (Exception e) {
- log.warn("[ServerElection] server({}) was down.", serverAddress);
+ log.warn("[ServerElection] server[{}] was down.", serverAddress, e);
}
downServerCache.add(serverAddress);
return null;
@@ -157,9 +172,4 @@ public class ServerElectionService {
private boolean accurate() {
return ThreadLocalRandom.current().nextInt(100) < accurateSelectServerPercentage;
}
-
- private String getProtocolServerAddress(String protocol) {
- Protocol pt = Protocol.of(protocol);
- return TransportService.getAllAddress().get(pt);
- }
}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/redirector/DesignateServerAspect.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/redirector/DesignateServerAspect.java
index 9b5280b5..ad906487 100644
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/redirector/DesignateServerAspect.java
+++ b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/redirector/DesignateServerAspect.java
@@ -1,17 +1,9 @@
package tech.powerjob.server.remote.server.redirector;
-import akka.pattern.Patterns;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import lombok.RequiredArgsConstructor;
-import tech.powerjob.common.exception.PowerJobException;
-import tech.powerjob.common.RemoteConstant;
-import tech.powerjob.common.response.AskResponse;
-import org.springframework.core.annotation.Order;
-import tech.powerjob.server.persistence.remote.model.AppInfoDO;
-import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
-import tech.powerjob.server.remote.transport.starter.AkkaStarter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
@@ -19,16 +11,25 @@ import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
+import tech.powerjob.common.RemoteConstant;
+import tech.powerjob.common.enums.Protocol;
+import tech.powerjob.common.exception.PowerJobException;
+import tech.powerjob.common.response.AskResponse;
+import tech.powerjob.remote.framework.base.URL;
+import tech.powerjob.server.persistence.remote.model.AppInfoDO;
+import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
+import tech.powerjob.server.remote.transporter.impl.ServerURLFactory;
+import tech.powerjob.server.remote.transporter.TransportService;
-import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
-import java.time.Duration;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.CompletionStage;
+import java.util.concurrent.TimeUnit;
/**
* 指定服务器运行切面
@@ -43,6 +44,7 @@ import java.util.concurrent.CompletionStage;
@RequiredArgsConstructor
public class DesignateServerAspect {
+ private final TransportService transportService;
private final AppInfoRepository appInfoRepository;
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@@ -84,7 +86,7 @@ public class DesignateServerAspect {
}
// 目标IP与本地符合则本地执行
- if (Objects.equals(targetServer, AkkaStarter.getActorSystemAddress())) {
+ if (Objects.equals(targetServer, transportService.defaultProtocol().getAddress())) {
return point.proceed();
}
@@ -96,8 +98,10 @@ public class DesignateServerAspect {
.setParameterTypes(parameterTypes)
.setArgs(args);
- CompletionStage askCS = Patterns.ask(AkkaStarter.getFriendActor(targetServer), remoteProcessReq, Duration.ofMillis(RemoteConstant.DEFAULT_TIMEOUT_MS));
- AskResponse askResponse = (AskResponse) askCS.toCompletableFuture().get();
+ final URL friendUrl = ServerURLFactory.process2Friend(targetServer);
+
+ CompletionStage askCS = transportService.ask(Protocol.HTTP.name(), friendUrl, remoteProcessReq, AskResponse.class);
+ AskResponse askResponse = askCS.toCompletableFuture().get(RemoteConstant.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (!askResponse.isSuccess()) {
throw new PowerJobException("remote process failed: " + askResponse.getMessage());
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/self/ServerInfoServiceImpl.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/self/ServerInfoServiceImpl.java
index eb94b58b..8a205e49 100644
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/self/ServerInfoServiceImpl.java
+++ b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/server/self/ServerInfoServiceImpl.java
@@ -1,22 +1,20 @@
package tech.powerjob.server.remote.server.self;
+import com.google.common.base.Stopwatch;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.time.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.info.BuildProperties;
-import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.common.utils.NetUtils;
-import tech.powerjob.server.common.constants.PJThreadPool;
import tech.powerjob.server.common.module.ServerInfo;
import tech.powerjob.server.extension.LockService;
import tech.powerjob.server.persistence.remote.model.ServerInfoDO;
import tech.powerjob.server.persistence.remote.repository.ServerInfoRepository;
-import com.google.common.base.Stopwatch;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.time.DateUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
@@ -50,6 +48,7 @@ public class ServerInfoServiceImpl implements ServerInfoService {
String ip = NetUtils.getLocalHost();
serverInfo.setIp(ip);
+ serverInfo.setBornTime(System.currentTimeMillis());
this.serverInfoRepository = serverInfoRepository;
Stopwatch sw = Stopwatch.createStarted();
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/TransportService.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/TransportService.java
deleted file mode 100644
index 3ee154d5..00000000
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/TransportService.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package tech.powerjob.server.remote.transport;
-
-import tech.powerjob.common.PowerSerializable;
-import tech.powerjob.common.enums.Protocol;
-import tech.powerjob.common.response.AskResponse;
-import com.google.common.collect.Maps;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * TransportService
- *
- * @author tjq
- * @since 2021/2/7
- */
-@Slf4j
-@Service
-public class TransportService {
-
- private static final Map protocol2Address = Maps.newHashMap();
-
- @Getter
- private final Map protocol2Transporter = Maps.newConcurrentMap();
-
- @Autowired
- public TransportService(List transporters) {
- transporters.forEach(t -> {
- log.info("[TransportService] Transporter[protocol:{},address:{}] registration successful!", t.getProtocol(), t.getAddress());
- protocol2Transporter.put(t.getProtocol(), t);
- protocol2Address.put(t.getProtocol(), t.getAddress());
- });
- }
-
- public void tell(Protocol protocol, String address, PowerSerializable object) {
- getTransporter(protocol).tell(address, object);
- }
-
- public AskResponse ask(Protocol protocol, String address, PowerSerializable object) throws Exception {
-
- return getTransporter(protocol).ask(address, object);
- }
-
- public Transporter getTransporter(Protocol protocol) {
- Transporter transporter = protocol2Transporter.get(protocol);
- if (transporter == null) {
- log.error("[TransportService] can't find transporter by protocol[{}], this is a bug!", protocol);
- throw new UnknownProtocolException("can't find transporter by protocol: " + protocol);
- }
- return transporter;
- }
-
- public static class UnknownProtocolException extends RuntimeException {
- public UnknownProtocolException(String message) {
- super(message);
- }
- }
-
- public static Map getAllAddress() {
- return protocol2Address;
- }
-}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/Transporter.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/Transporter.java
deleted file mode 100644
index 6d77dd69..00000000
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/Transporter.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package tech.powerjob.server.remote.transport;
-
-import tech.powerjob.common.PowerSerializable;
-import tech.powerjob.common.enums.Protocol;
-import tech.powerjob.common.response.AskResponse;
-
-/**
- * Transporter
- *
- * @author tjq
- * @since 2021/2/7
- */
-public interface Transporter {
-
- Protocol getProtocol();
-
- String getAddress();
-
- void tell(String address, PowerSerializable object);
-
- AskResponse ask(String address, PowerSerializable object) throws Exception;
-}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/impl/AkkaTransporter.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/impl/AkkaTransporter.java
deleted file mode 100644
index 3a7ae9a1..00000000
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/impl/AkkaTransporter.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package tech.powerjob.server.remote.transport.impl;
-
-import akka.actor.ActorSelection;
-import akka.pattern.Patterns;
-import tech.powerjob.common.PowerSerializable;
-import tech.powerjob.common.enums.Protocol;
-import tech.powerjob.common.RemoteConstant;
-import tech.powerjob.common.response.AskResponse;
-import tech.powerjob.server.remote.transport.Transporter;
-import tech.powerjob.server.remote.transport.starter.AkkaStarter;
-import org.springframework.stereotype.Service;
-
-import java.time.Duration;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.TimeUnit;
-
-/**
- * akka transporter
- *
- * @author tjq
- * @since 2021/2/7
- */
-@Service
-public class AkkaTransporter implements Transporter {
-
- @Override
- public Protocol getProtocol() {
- return Protocol.AKKA;
- }
-
- @Override
- public String getAddress() {
- return AkkaStarter.getActorSystemAddress();
- }
-
- @Override
- public void tell(String address, PowerSerializable object) {
- ActorSelection taskTrackerActor = AkkaStarter.getWorkerActor(address);
- taskTrackerActor.tell(object, null);
- }
-
- @Override
- public AskResponse ask(String address, PowerSerializable object) throws Exception {
- ActorSelection taskTrackerActor = AkkaStarter.getWorkerActor(address);
- CompletionStage askCS = Patterns.ask(taskTrackerActor, object, Duration.ofMillis(RemoteConstant.DEFAULT_TIMEOUT_MS));
- return (AskResponse) askCS.toCompletableFuture().get(RemoteConstant.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- }
-}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/impl/HttpTransporter.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/impl/HttpTransporter.java
deleted file mode 100644
index 365b60a5..00000000
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/impl/HttpTransporter.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package tech.powerjob.server.remote.transport.impl;
-
-import tech.powerjob.common.PowerSerializable;
-import tech.powerjob.common.enums.Protocol;
-import tech.powerjob.common.RemoteConstant;
-import tech.powerjob.common.response.AskResponse;
-import tech.powerjob.common.utils.NetUtils;
-import tech.powerjob.server.remote.transport.Transporter;
-import tech.powerjob.server.remote.transport.starter.VertXStarter;
-import io.vertx.core.Future;
-import io.vertx.core.Vertx;
-import io.vertx.core.buffer.Buffer;
-import io.vertx.ext.web.client.HttpResponse;
-import io.vertx.ext.web.client.WebClient;
-import io.vertx.ext.web.client.WebClientOptions;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.tuple.Pair;
-import org.springframework.stereotype.Service;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-/**
- * http transporter powered by vert.x
- *
- * @author tjq
- * @since 2021/2/8
- */
-@Slf4j
-@Service
-public class HttpTransporter implements Transporter {
-
- private final WebClient webClient;
-
- public HttpTransporter() {
- WebClientOptions options = new WebClientOptions()
- .setKeepAlive(false)
- .setConnectTimeout((int) RemoteConstant.DEFAULT_TIMEOUT_MS);
- webClient = WebClient.create(Vertx.vertx(), options);
- }
-
- @Override
- public Protocol getProtocol() {
- return Protocol.HTTP;
- }
-
- @Override
- public String getAddress() {
- return VertXStarter.getAddress();
- }
-
- @Override
- public void tell(String address, PowerSerializable object) {
- postRequest(address, object);
- }
-
- @Override
- public AskResponse ask(String address, PowerSerializable object) throws Exception {
- CompletableFuture> future = postRequest(address, object).toCompletionStage().toCompletableFuture();
- HttpResponse httpResponse = future.get(RemoteConstant.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- return httpResponse.bodyAsJson(AskResponse.class);
- }
-
- private Future> postRequest(String address, PowerSerializable object) {
- Pair ipAndPort = NetUtils.splitAddress2IpAndPort(address);
- String ip = ipAndPort.getLeft();
- int port = ipAndPort.getRight();
- return webClient.post(port, ip, object.path())
- .sendJson(object)
- .onSuccess(res -> log.info("[HttpTransporter] send request to {}{} successfully: {}, response: {}", address, object.path(), object, res))
- .onFailure(t -> log.warn("[HttpTransporter] send request to {}{} failed: {}", address, object.path(), object, t));
- }
-}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/starter/AkkaStarter.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/starter/AkkaStarter.java
deleted file mode 100644
index de54e273..00000000
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/starter/AkkaStarter.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package tech.powerjob.server.remote.transport.starter;
-
-import akka.actor.ActorSelection;
-import akka.actor.ActorSystem;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Maps;
-import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import tech.powerjob.common.OmsConstant;
-import tech.powerjob.common.RemoteConstant;
-import tech.powerjob.common.utils.NetUtils;
-import tech.powerjob.server.common.PowerJobServerConfigKey;
-import tech.powerjob.server.common.utils.PropertyUtils;
-import tech.powerjob.server.remote.server.FriendRequestHandler;
-
-import java.util.Map;
-import java.util.Properties;
-
-/**
- * 服务端 ActorSystem 启动器
- *
- * @author tjq
- * @since 2020/4/2
- */
-@Slf4j
-public class AkkaStarter {
-
- public static ActorSystem actorSystem;
- @Getter
- private static String actorSystemAddress;
-
- private static final String AKKA_PATH = "akka://%s@%s/user/%s";
-
- public static void init() {
-
- Stopwatch stopwatch = Stopwatch.createStarted();
- log.info("[PowerJob] PowerJob's akka system start to bootstrap...");
-
- // 忽略了一个问题,机器是没办法访问外网的,除非架设自己的NTP服务器
- // TimeUtils.check();
-
- // 解析配置文件
- Config akkaFinalConfig = parseConfig();
- actorSystem = ActorSystem.create(RemoteConstant.SERVER_ACTOR_SYSTEM_NAME, akkaFinalConfig);
- actorSystem.actorOf(FriendRequestHandler.defaultProps(), RemoteConstant.SERVER_FRIEND_ACTOR_NAME);
- log.info("[PowerJob] PowerJob's akka system started successfully, using time {}.", stopwatch);
- }
-
- private static Config parseConfig() {
- Properties properties = PropertyUtils.getProperties();
- int port = Integer.parseInt(properties.getProperty(PowerJobServerConfigKey.AKKA_PORT, String.valueOf(OmsConstant.SERVER_DEFAULT_AKKA_PORT)));
- String portFromJvm = System.getProperty(PowerJobServerConfigKey.AKKA_PORT);
- if (StringUtils.isNotEmpty(portFromJvm)) {
- log.info("[PowerJob] use port from jvm params: {}", portFromJvm);
- port = Integer.parseInt(portFromJvm);
- }
-
- // 启动 ActorSystem
- Map overrideConfig = Maps.newHashMap();
- String localIp = NetUtils.getLocalHost();
- overrideConfig.put("akka.remote.artery.canonical.hostname", localIp);
- overrideConfig.put("akka.remote.artery.canonical.port", port);
- actorSystemAddress = localIp + ":" + port;
- log.info("[PowerJob] akka-remote server address: {}", actorSystemAddress);
-
- Config akkaBasicConfig = ConfigFactory.load(RemoteConstant.SERVER_AKKA_CONFIG_NAME);
- return ConfigFactory.parseMap(overrideConfig).withFallback(akkaBasicConfig);
- }
-
- /**
- * 获取 ServerActor 的 ActorSelection
- *
- * @param address IP:port
- * @return ActorSelection
- */
- public static ActorSelection getFriendActor(String address) {
- String path = String.format(AKKA_PATH, RemoteConstant.SERVER_ACTOR_SYSTEM_NAME, address, RemoteConstant.SERVER_FRIEND_ACTOR_NAME);
- return actorSystem.actorSelection(path);
- }
-
- public static ActorSelection getWorkerActor(String address) {
- String path = String.format(AKKA_PATH, RemoteConstant.WORKER_ACTOR_SYSTEM_NAME, address, RemoteConstant.WORKER_ACTOR_NAME);
- return actorSystem.actorSelection(path);
- }
-}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/starter/VertXStarter.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/starter/VertXStarter.java
deleted file mode 100644
index 5f419c26..00000000
--- a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transport/starter/VertXStarter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package tech.powerjob.server.remote.transport.starter;
-
-import tech.powerjob.common.OmsConstant;
-import tech.powerjob.common.utils.NetUtils;
-import tech.powerjob.server.common.PowerJobServerConfigKey;
-import tech.powerjob.server.common.utils.PropertyUtils;
-import com.google.common.base.Stopwatch;
-import io.vertx.core.Vertx;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.Properties;
-
-/**
- * vert.x starter
- *
- * @author tjq
- * @since 2021/2/8
- */
-@Slf4j
-public class VertXStarter {
-
- public static Vertx vertx;
- @Getter
- private static String address;
-
- public static void init() {
- Stopwatch stopwatch = Stopwatch.createStarted();
- log.info("[PowerJob] PowerJob's vert.x system start to bootstrap...");
-
- Properties properties = PropertyUtils.getProperties();
- int port = Integer.parseInt(properties.getProperty(PowerJobServerConfigKey.HTTP_PORT, String.valueOf(OmsConstant.SERVER_DEFAULT_HTTP_PORT)));
- String portFromJVM = System.getProperty(PowerJobServerConfigKey.HTTP_PORT);
- if (StringUtils.isNotEmpty(portFromJVM)) {
- port = Integer.parseInt(portFromJVM);
- }
- String localIP = NetUtils.getLocalHost();
-
- address = localIP + ":" + port;
- log.info("[PowerJob] vert.x server address: {}", address);
-
- vertx = Vertx.vertx();
-
- log.info("[PowerJob] PowerJob's vert.x system started successfully, using time {}.", stopwatch);
- }
-}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/ProtocolInfo.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/ProtocolInfo.java
new file mode 100644
index 00000000..0802e811
--- /dev/null
+++ b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/ProtocolInfo.java
@@ -0,0 +1,30 @@
+package tech.powerjob.server.remote.transporter;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import tech.powerjob.remote.framework.transporter.Transporter;
+
+/**
+ * ProtocolInfo
+ *
+ * @author tjq
+ * @since 2023/1/21
+ */
+@Getter
+@Setter
+@ToString
+public class ProtocolInfo {
+
+ private String protocol;
+
+ private String address;
+
+ private transient Transporter transporter;
+
+ public ProtocolInfo(String protocol, String address, Transporter transporter) {
+ this.protocol = protocol;
+ this.address = address;
+ this.transporter = transporter;
+ }
+}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/TransportService.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/TransportService.java
new file mode 100644
index 00000000..97e390e3
--- /dev/null
+++ b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/TransportService.java
@@ -0,0 +1,36 @@
+package tech.powerjob.server.remote.transporter;
+
+import tech.powerjob.common.PowerSerializable;
+import tech.powerjob.remote.framework.base.RemotingException;
+import tech.powerjob.remote.framework.base.URL;
+
+import java.util.Map;
+import java.util.concurrent.CompletionStage;
+
+/**
+ * server 数据传输服务
+ *
+ * @author tjq
+ * @since 2023/1/21
+ */
+public interface TransportService {
+
+ /**
+ * 自用地址,用于维护 server -> appId 和 server 间通讯
+ * 4.3.0 前为 ActorSystem Address(ip:10086)
+ * 4.3.0 后 PowerJob 将主协议切换为自由协议,默认使用 HTTP address (ip:10010)
+ * @return 自用地址
+ */
+ ProtocolInfo defaultProtocol();
+
+ /**
+ * 当前支持的全部协议
+ * @return allProtocols
+ */
+ Map allProtocols();
+
+ void tell(String protocol, URL url, PowerSerializable request);
+
+ CompletionStage ask(String protocol, URL url, PowerSerializable request, Class clz) throws RemotingException;
+
+}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/impl/PowerTransportService.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/impl/PowerTransportService.java
new file mode 100644
index 00000000..d5d2f624
--- /dev/null
+++ b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/impl/PowerTransportService.java
@@ -0,0 +1,207 @@
+package tech.powerjob.server.remote.transporter.impl;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Service;
+import tech.powerjob.common.OmsConstant;
+import tech.powerjob.common.PowerSerializable;
+import tech.powerjob.common.enums.Protocol;
+import tech.powerjob.common.utils.NetUtils;
+import tech.powerjob.remote.framework.actor.Actor;
+import tech.powerjob.remote.framework.base.Address;
+import tech.powerjob.remote.framework.base.RemotingException;
+import tech.powerjob.remote.framework.base.ServerType;
+import tech.powerjob.remote.framework.base.URL;
+import tech.powerjob.remote.framework.engine.EngineConfig;
+import tech.powerjob.remote.framework.engine.EngineOutput;
+import tech.powerjob.remote.framework.engine.RemoteEngine;
+import tech.powerjob.remote.framework.engine.impl.PowerJobRemoteEngine;
+import tech.powerjob.server.remote.transporter.ProtocolInfo;
+import tech.powerjob.server.remote.transporter.TransportService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletionStage;
+
+/**
+ * server 数据传输服务
+ *
+ * @author tjq
+ * @since 2023/1/21
+ */
+@Slf4j
+@Service
+public class PowerTransportService implements TransportService, InitializingBean, DisposableBean, ApplicationContextAware {
+
+ /**
+ * server 需要激活的通讯协议,建议激活全部支持的协议
+ */
+ @Value("${oms.transporter.active.protocols}")
+ private String activeProtocols;
+
+ /**
+ * 主要通讯协议,用于 server 与 server 之间的通讯,用户必须保证该协议可用(端口开放)!
+ */
+ @Value("${oms.transporter.main.protocol}")
+ private String mainProtocol;
+
+ private static final String PROTOCOL_PORT_CONFIG = "oms.%s.port";
+
+ private final Environment environment;
+
+ private ProtocolInfo defaultProtocol;
+ private final Map protocolName2Info = Maps.newHashMap();
+
+ private final List engines = Lists.newArrayList();
+
+ private ApplicationContext applicationContext;
+
+ public PowerTransportService(Environment environment) {
+ this.environment = environment;
+ }
+
+ @Override
+ public ProtocolInfo defaultProtocol() {
+ return defaultProtocol;
+ }
+
+ @Override
+ public Map allProtocols() {
+ return protocolName2Info;
+ }
+
+ private ProtocolInfo fetchProtocolInfo(String protocol) {
+ // 兼容老版 worker 未上报 protocol 的情况
+ protocol = compatibleProtocol(protocol);
+ final ProtocolInfo protocolInfo = protocolName2Info.get(protocol);
+ if (protocolInfo == null) {
+ throw new IllegalArgumentException("can't find Transporter by protocol :" + protocol);
+ }
+ return protocolInfo;
+ }
+
+ @Override
+ public void tell(String protocol, URL url, PowerSerializable request) {
+ fetchProtocolInfo(protocol).getTransporter().tell(url, request);
+ }
+
+ @Override
+ public CompletionStage ask(String protocol, URL url, PowerSerializable request, Class clz) throws RemotingException {
+ return fetchProtocolInfo(protocol).getTransporter().ask(url, request, clz);
+ }
+
+ private void initRemoteFrameWork(String protocol, int port) {
+
+ // 从构造器注入改为从 applicationContext 获取来避免循环依赖
+ final Map beansWithAnnotation = applicationContext.getBeansWithAnnotation(Actor.class);
+ log.info("[PowerTransportService] find Actor num={},names={}", beansWithAnnotation.size(), beansWithAnnotation.keySet());
+
+ Address address = new Address()
+ .setHost(NetUtils.getLocalHost())
+ .setPort(port);
+ EngineConfig engineConfig = new EngineConfig()
+ .setServerType(ServerType.SERVER)
+ .setType(protocol.toUpperCase())
+ .setBindAddress(address)
+ .setActorList(Lists.newArrayList(beansWithAnnotation.values()));
+ log.info("[PowerTransportService] start to initialize RemoteEngine[type={},address={}]", protocol, address);
+ RemoteEngine re = new PowerJobRemoteEngine();
+ final EngineOutput engineOutput = re.start(engineConfig);
+ log.info("[PowerTransportService] start RemoteEngine[type={},address={}] successfully", protocol, address);
+
+ this.engines.add(re);
+ this.protocolName2Info.put(protocol, new ProtocolInfo(protocol, address.toFullAddress(), engineOutput.getTransporter()));
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+
+ log.info("[PowerTransportService] start to initialize whole PowerTransportService!");
+ log.info("[PowerTransportService] activeProtocols: {}", activeProtocols);
+
+ if (StringUtils.isEmpty(activeProtocols)) {
+ throw new IllegalArgumentException("activeProtocols can't be empty!");
+ }
+
+ for (String protocol : activeProtocols.split(OmsConstant.COMMA)) {
+ try {
+ final int port = parseProtocolPort(protocol);
+ initRemoteFrameWork(protocol, port);
+ } catch (Throwable t) {
+ log.error("[PowerTransportService] initialize protocol[{}] failed. If you don't need to use this protocol, you can turn it off by 'oms.transporter.active.protocols'", protocol);
+ ExceptionUtils.rethrow(t);
+ }
+ }
+
+ choseDefault();
+
+ log.info("[PowerTransportService] initialize successfully!");
+ log.info("[PowerTransportService] ALL_PROTOCOLS: {}", protocolName2Info);
+ }
+
+ /**
+ * 获取协议端口,考虑兼容性 & 用户仔细扩展的场景,选择动态从 env 获取 port
+ * @return port
+ */
+ private int parseProtocolPort(String protocol) {
+ final String key1 = String.format(PROTOCOL_PORT_CONFIG, protocol.toLowerCase());
+ final String key2 = String.format(PROTOCOL_PORT_CONFIG, protocol.toUpperCase());
+ String portStr = environment.getProperty(key1);
+ if (StringUtils.isEmpty(portStr)) {
+ portStr = environment.getProperty(key2);
+ }
+ log.info("[PowerTransportService] fetch port for protocol[{}], key={}, value={}", protocol, key1, portStr);
+
+ if (StringUtils.isEmpty(portStr)) {
+ throw new IllegalArgumentException(String.format("can't find protocol config by key: %s, please check your spring config!", key1));
+ }
+
+ return Integer.parseInt(portStr);
+ }
+
+ private String compatibleProtocol(String p) {
+ if (p == null) {
+ return Protocol.AKKA.name();
+ }
+ return p;
+ }
+
+ /**
+ * HTTP 优先,否则默认取第一个协议
+ */
+ private void choseDefault() {
+
+
+ this.defaultProtocol = this.protocolName2Info.get(mainProtocol);
+ log.info("[PowerTransportService] chose [{}] as the default protocol, make sure this protocol can work!", mainProtocol);
+
+ if (this.defaultProtocol == null) {
+ throw new IllegalArgumentException("can't find default protocol, please check your config!");
+ }
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ engines.forEach(e -> {
+ try {
+ e.close();
+ } catch (Exception ignore) {
+ }
+ });
+ }
+}
diff --git a/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/impl/ServerURLFactory.java b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/impl/ServerURLFactory.java
new file mode 100644
index 00000000..0edc3c65
--- /dev/null
+++ b/powerjob-server/powerjob-server-remote/src/main/java/tech/powerjob/server/remote/transporter/impl/ServerURLFactory.java
@@ -0,0 +1,52 @@
+package tech.powerjob.server.remote.transporter.impl;
+
+import tech.powerjob.remote.framework.base.Address;
+import tech.powerjob.remote.framework.base.HandlerLocation;
+import tech.powerjob.remote.framework.base.ServerType;
+import tech.powerjob.remote.framework.base.URL;
+
+import static tech.powerjob.common.RemoteConstant.*;
+
+/**
+ * 统一生成地址
+ *
+ * @author tjq
+ * @since 2023/1/21
+ */
+public class ServerURLFactory {
+
+ public static URL dispatchJob2Worker(String address) {
+ return simileBuild(address, ServerType.WORKER, WORKER_PATH, WTT_HANDLER_RUN_JOB);
+ }
+
+ public static URL stopInstance2Worker(String address) {
+ return simileBuild(address, ServerType.WORKER, WORKER_PATH, WTT_HANDLER_STOP_INSTANCE);
+ }
+
+ public static URL queryInstance2Worker(String address) {
+ return simileBuild(address, ServerType.WORKER, WORKER_PATH, WTT_HANDLER_QUERY_INSTANCE_STATUS);
+ }
+
+ public static URL deployContainer2Worker(String address) {
+ return simileBuild(address, ServerType.WORKER, WORKER_PATH, WORKER_HANDLER_DEPLOY_CONTAINER);
+ }
+
+ public static URL destroyContainer2Worker(String address) {
+ return simileBuild(address, ServerType.WORKER, WORKER_PATH, WORKER_HANDLER_DESTROY_CONTAINER);
+ }
+
+ public static URL ping2Friend(String address) {
+ return simileBuild(address, ServerType.SERVER, S4S_PATH, S4S_HANDLER_PING);
+ }
+
+ public static URL process2Friend(String address) {
+ return simileBuild(address, ServerType.SERVER, S4S_PATH, S4S_HANDLER_PROCESS);
+ }
+
+ public static URL simileBuild(String address, ServerType type, String rootPath, String handlerPath) {
+ return new URL()
+ .setServerType(type)
+ .setAddress(Address.fromIpv4(address))
+ .setLocation(new HandlerLocation().setRootPath(rootPath).setMethodPath(handlerPath));
+ }
+}
diff --git a/powerjob-server/powerjob-server-starter/pom.xml b/powerjob-server/powerjob-server-starter/pom.xml
index 8f3f73df..bb3a3b2c 100644
--- a/powerjob-server/powerjob-server-starter/pom.xml
+++ b/powerjob-server/powerjob-server-starter/pom.xml
@@ -5,7 +5,7 @@
powerjob-server
tech.powerjob
- 4.2.1
+ 4.3.0
../pom.xml
4.0.0
diff --git a/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/PowerJobServerApplication.java b/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/PowerJobServerApplication.java
index 22a660af..75af8667 100644
--- a/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/PowerJobServerApplication.java
+++ b/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/PowerJobServerApplication.java
@@ -1,8 +1,6 @@
package tech.powerjob.server;
import tech.powerjob.server.common.utils.PropertyUtils;
-import tech.powerjob.server.remote.transport.starter.AkkaStarter;
-import tech.powerjob.server.remote.transport.starter.VertXStarter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -30,9 +28,6 @@ public class PowerJobServerApplication {
pre();
- AkkaStarter.init();
- VertXStarter.init();
-
// Start SpringBoot application.
try {
SpringApplication.run(PowerJobServerApplication.class, args);
diff --git a/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/ContainerController.java b/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/ContainerController.java
index 8f13e0ef..02acd5d0 100644
--- a/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/ContainerController.java
+++ b/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/ContainerController.java
@@ -1,20 +1,5 @@
package tech.powerjob.server.web.controller;
-import tech.powerjob.common.OmsConstant;
-import tech.powerjob.common.response.ResultDTO;
-import tech.powerjob.server.remote.transport.starter.AkkaStarter;
-import tech.powerjob.server.common.constants.ContainerSourceType;
-import tech.powerjob.server.common.constants.SwitchableStatus;
-import tech.powerjob.server.core.container.ContainerTemplateGenerator;
-import tech.powerjob.server.common.utils.OmsFileUtils;
-import tech.powerjob.server.persistence.remote.model.AppInfoDO;
-import tech.powerjob.server.persistence.remote.model.ContainerInfoDO;
-import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
-import tech.powerjob.server.persistence.remote.repository.ContainerInfoRepository;
-import tech.powerjob.server.core.container.ContainerService;
-import tech.powerjob.server.web.request.GenerateContainerTemplateRequest;
-import tech.powerjob.server.web.request.SaveContainerInfoRequest;
-import tech.powerjob.server.web.response.ContainerInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
@@ -22,8 +7,21 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
+import tech.powerjob.common.OmsConstant;
+import tech.powerjob.common.response.ResultDTO;
+import tech.powerjob.server.common.constants.ContainerSourceType;
+import tech.powerjob.server.common.constants.SwitchableStatus;
+import tech.powerjob.server.common.utils.OmsFileUtils;
+import tech.powerjob.server.core.container.ContainerService;
+import tech.powerjob.server.core.container.ContainerTemplateGenerator;
+import tech.powerjob.server.persistence.remote.model.AppInfoDO;
+import tech.powerjob.server.persistence.remote.model.ContainerInfoDO;
+import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
+import tech.powerjob.server.persistence.remote.repository.ContainerInfoRepository;
+import tech.powerjob.server.web.request.GenerateContainerTemplateRequest;
+import tech.powerjob.server.web.request.SaveContainerInfoRequest;
+import tech.powerjob.server.web.response.ContainerInfoVO;
-import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
@@ -62,6 +60,8 @@ public class ContainerController {
File file = containerService.fetchContainerJarFile(version);
if (file.exists()) {
OmsFileUtils.file2HttpResponse(file, response);
+ } else {
+ log.error("[Container] can't find container by version[{}], please deploy first!", version);
}
}
@@ -114,17 +114,6 @@ public class ContainerController {
return ResultDTO.failed("No workers have even registered!");
}
- // 转发 HTTP 请求
- if (!AkkaStarter.getActorSystemAddress().equals(targetServer)) {
- String targetIp = targetServer.split(":")[0];
- String url = String.format("http://%s:%d/container/listDeployedWorker?appId=%d&containerId=%d", targetIp, port, appId, containerId);
- try {
- response.sendRedirect(url);
- return ResultDTO.success(null);
- }catch (Exception e) {
- return ResultDTO.failed(e);
- }
- }
return ResultDTO.success(containerService.fetchDeployedInfo(appId, containerId));
}
diff --git a/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/ServerController.java b/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/ServerController.java
index ada346e3..c9c71dcf 100644
--- a/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/ServerController.java
+++ b/powerjob-server/powerjob-server-starter/src/main/java/tech/powerjob/server/web/controller/ServerController.java
@@ -7,13 +7,16 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import tech.powerjob.common.request.ServerDiscoveryRequest;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.common.utils.NetUtils;
+import tech.powerjob.server.common.aware.ServerInfoAware;
+import tech.powerjob.server.common.module.ServerInfo;
import tech.powerjob.server.persistence.remote.model.AppInfoDO;
import tech.powerjob.server.persistence.remote.repository.AppInfoRepository;
import tech.powerjob.server.remote.server.election.ServerElectionService;
-import tech.powerjob.server.remote.transport.TransportService;
+import tech.powerjob.server.remote.transporter.TransportService;
import tech.powerjob.server.remote.worker.WorkerClusterQueryService;
import java.util.Optional;
@@ -29,8 +32,9 @@ import java.util.TimeZone;
@RestController
@RequestMapping("/server")
@RequiredArgsConstructor
-public class ServerController {
+public class ServerController implements ServerInfoAware {
+ private ServerInfo serverInfo;
private final TransportService transportService;
private final ServerElectionService serverElectionService;
@@ -47,23 +51,33 @@ public class ServerController {
}
@GetMapping("/acquire")
- public ResultDTO acquireServer(Long appId, String protocol, String currentServer) {
- return ResultDTO.success(serverElectionService.elect(appId, protocol, currentServer));
+ public ResultDTO acquireServer(ServerDiscoveryRequest request) {
+ return ResultDTO.success(serverElectionService.elect(request));
}
@GetMapping("/hello")
public ResultDTO ping(@RequestParam(required = false) boolean debug) {
JSONObject res = new JSONObject();
res.put("localHost", NetUtils.getLocalHost());
- res.put("communicationSystemInfo", transportService.getProtocol2Transporter());
+ res.put("serverInfo", serverInfo);
res.put("serverTime", CommonUtils.formatTime(System.currentTimeMillis()));
+ res.put("serverTimeTs", System.currentTimeMillis());
res.put("serverTimeZone", TimeZone.getDefault().getDisplayName());
res.put("appIds", workerClusterQueryService.getAppId2ClusterStatus().keySet());
if (debug) {
res.put("appId2ClusterInfo", JSON.parseObject(JSON.toJSONString(workerClusterQueryService.getAppId2ClusterStatus())));
-
}
+
+ try {
+ res.put("defaultAddress", JSONObject.toJSON(transportService.defaultProtocol()));
+ } catch (Exception ignore) {
+ }
+
return ResultDTO.success(res);
}
+ @Override
+ public void setServerInfo(ServerInfo serverInfo) {
+ this.serverInfo = serverInfo;
+ }
}
diff --git a/powerjob-server/powerjob-server-starter/src/main/resources/application.properties b/powerjob-server/powerjob-server-starter/src/main/resources/application.properties
index 9f65c568..f8cce8b8 100644
--- a/powerjob-server/powerjob-server-starter/src/main/resources/application.properties
+++ b/powerjob-server/powerjob-server-starter/src/main/resources/application.properties
@@ -16,8 +16,9 @@ spring.servlet.multipart.max-request-size=209715200
# temporary skip circular references check
spring.main.allow-circular-references=true
-###### PowerJob self-owned configuration (The following properties should exist in application.properties only). ######
-# Akka ActorSystem port.
+###### PowerJob transporter configuration ######
+oms.transporter.active.protocols=AKKA,HTTP
+oms.transporter.main.protocol=HTTP
oms.akka.port=10086
oms.http.port=10010
# Prefix for all tables. Default empty string. Config if you have needs, i.e. pj_
diff --git a/powerjob-server/powerjob-server-starter/src/main/resources/banner.txt b/powerjob-server/powerjob-server-starter/src/main/resources/banner.txt
index 6ca0bdbc..e52ab26f 100644
--- a/powerjob-server/powerjob-server-starter/src/main/resources/banner.txt
+++ b/powerjob-server/powerjob-server-starter/src/main/resources/banner.txt
@@ -11,5 +11,5 @@ ${AnsiColor.BRIGHT_RED}
* Maintainer: tengjiqi@gmail.com & Team PowerJob
* OfficialWebsite: http://www.powerjob.tech/
* SourceCode: https://github.com/PowerJob/PowerJob
-* PoweredBy: SpringBoot${spring-boot.formatted-version} & Akka (v2.6.12) & Vert.x (v4.0.2)
+* PoweredBy: SpringBoot${spring-boot.formatted-version}
${AnsiColor.DEFAULT}
\ No newline at end of file
diff --git a/powerjob-server/powerjob-server-starter/src/main/resources/logback-dev.xml b/powerjob-server/powerjob-server-starter/src/main/resources/logback-dev.xml
index 1c58dc7c..9951c3bc 100644
--- a/powerjob-server/powerjob-server-starter/src/main/resources/logback-dev.xml
+++ b/powerjob-server/powerjob-server-starter/src/main/resources/logback-dev.xml
@@ -12,6 +12,8 @@
+
+
diff --git a/powerjob-server/powerjob-server-starter/src/main/resources/oms-server.akka.conf b/powerjob-server/powerjob-server-starter/src/main/resources/oms-server.akka.conf
deleted file mode 100644
index 95afe889..00000000
--- a/powerjob-server/powerjob-server-starter/src/main/resources/oms-server.akka.conf
+++ /dev/null
@@ -1,68 +0,0 @@
-akka {
-
- loggers = ["akka.event.slf4j.Slf4jLogger"]
- loglevel = "WARNING"
-
- actor {
- # cluster is better(recommend by official document), but I prefer remote
- provider = remote
- allow-java-serialization = off
-
- serializers {
- power-serializer = "tech.powerjob.common.serialize.PowerAkkaSerializer"
- }
-
- serialization-bindings {
- "tech.powerjob.common.PowerSerializable" = power-serializer
- }
- }
- remote {
- artery {
- transport = tcp # See Selecting a transport below
- # over write by code
- canonical.hostname = "127.0.0.1"
- canonical.port = 0
- }
- }
-
- # worker-request-core-dispatcher
- w-r-c-d {
- # 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 = 128
- }
- # 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
- }
-
- friend-request-actor-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 = 128
- }
- # 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 = 5
- }
-}
\ No newline at end of file
diff --git a/powerjob-worker-agent/Dockerfile b/powerjob-worker-agent/Dockerfile
index f33b43e1..c7b3160e 100644
--- a/powerjob-worker-agent/Dockerfile
+++ b/powerjob-worker-agent/Dockerfile
@@ -13,7 +13,10 @@ RUN apt-get update && \
&& apt-get clean \
&& apt-get autoclean \
&& rm -rf /var/lib/apt/lists/*
-
+# 安装 wait-for-it 脚本
+RUN curl -o wait-for-it.sh https://gitee.com/KFCFans/wait-for-it/raw/master/wait-for-it.sh
+RUN chmod +x wait-for-it.sh
+# 拷贝主文件
COPY powerjob-agent.jar /powerjob-agent.jar
# 暴露端口(AKKA-Client)
EXPOSE 27777
diff --git a/powerjob-worker-agent/pom.xml b/powerjob-worker-agent/pom.xml
index 7449eabc..6eb753a5 100644
--- a/powerjob-worker-agent/pom.xml
+++ b/powerjob-worker-agent/pom.xml
@@ -5,19 +5,20 @@
powerjob
tech.powerjob
- 3.0.0
+ 4.0.0
4.0.0
powerjob-worker-agent
- 4.2.1
+ 4.3.0
jar
- 4.2.1
+ 4.3.0
1.2.9
4.3.2
+ 5.3.23
2.3.4.RELEASE
@@ -98,6 +99,13 @@
postgresql
${postgresql.version}
+
+
+
+ org.springframework
+ spring-context
+ ${spring.version}
+
diff --git a/powerjob-worker-agent/src/main/java/tech/powerjob/agent/MainApplication.java b/powerjob-worker-agent/src/main/java/tech/powerjob/agent/MainApplication.java
index b89767f1..4b84bfac 100644
--- a/powerjob-worker-agent/src/main/java/tech/powerjob/agent/MainApplication.java
+++ b/powerjob-worker-agent/src/main/java/tech/powerjob/agent/MainApplication.java
@@ -57,8 +57,7 @@ public class MainApplication implements Runnable {
cfg.setMaxResultLength(length);
cfg.setTag(tag);
- PowerJobWorker worker = new PowerJobWorker();
- worker.setConfig(cfg);
+ PowerJobWorker worker = new PowerJobWorker(cfg);
worker.init();
}catch (Exception e) {
diff --git a/powerjob-worker-samples/pom.xml b/powerjob-worker-samples/pom.xml
index 091c275e..00c1d5df 100644
--- a/powerjob-worker-samples/pom.xml
+++ b/powerjob-worker-samples/pom.xml
@@ -5,16 +5,16 @@
powerjob
tech.powerjob
- 3.0.0
+ 4.0.0
4.0.0
powerjob-worker-samples
- 4.2.1
+ 4.3.0
2.7.4
- 4.2.1
+ 4.3.0
1.2.83
1.2.1
@@ -59,6 +59,13 @@
${powerjob.official.processors.version}
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.3.1
+
+
diff --git a/powerjob-worker-samples/src/main/java/tech/powerjob/samples/PowerJobWorkerConfig.java b/powerjob-worker-samples/src/main/java/tech/powerjob/samples/PowerJobWorkerConfig.java
deleted file mode 100644
index 7ec8672b..00000000
--- a/powerjob-worker-samples/src/main/java/tech/powerjob/samples/PowerJobWorkerConfig.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package tech.powerjob.samples;
-
-import org.springframework.context.annotation.Configuration;
-
-/**
- * powerjob-worker 配置
- * 代码配置示例,SpringBoot 项目支持使用 starter,只需要在 application.properties 中完成配置即可
- *
- * @author tjq
- * @since 2020/4/17
- */
-@Configuration
-public class PowerJobWorkerConfig {
-
- /*
-
- @Bean(name = "worker2")
- public OhMyWorker initOMS() throws Exception {
-
- // 服务器HTTP地址(端口号为 server.port,而不是 ActorSystem port)
- List serverAddress = Lists.newArrayList("127.0.0.1:7700", "127.0.0.1:7701");
-
- // 1. 创建配置文件
- OhMyConfig config = new OhMyConfig();
- config.setPort(28888);
- config.setAppName("powerjob-multi-worker-2");
- config.setServerAddress(serverAddress);
- // 如果没有大型 Map/MapReduce 的需求,建议使用内存来加速计算
- config.setStoreStrategy(StoreStrategy.DISK);
-
- // 2. 创建 Worker 对象,设置配置文件
- OhMyWorker ohMyWorker = new OhMyWorker();
- ohMyWorker.setConfig(config);
- return ohMyWorker;
- }
-
-
- */
-
-
-}
diff --git a/powerjob-worker-samples/src/main/java/tech/powerjob/samples/PowerJobWorkerInitializer.java b/powerjob-worker-samples/src/main/java/tech/powerjob/samples/PowerJobWorkerInitializer.java
new file mode 100644
index 00000000..e6150ee2
--- /dev/null
+++ b/powerjob-worker-samples/src/main/java/tech/powerjob/samples/PowerJobWorkerInitializer.java
@@ -0,0 +1,44 @@
+package tech.powerjob.samples;
+
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * powerjob-worker 配置
+ * 代码配置示例,SpringBoot 项目支持使用 starter,只需要在 application.properties 中完成配置即可
+ *
+ * @author tjq
+ * @since 2020/4/17
+ */
+@Configuration
+public class PowerJobWorkerInitializer {
+
+ /*
+ 手动配置版代码
+ 常规 SpringBoot 用户直接使用 starter 配置即可,具体配置见 application.properties
+
+ @Bean
+ public PowerJobSpringWorker initPowerJobSpringWorkerByCode() {
+
+ // 初始化 PowerJob 配置文件
+ PowerJobWorkerConfig config = new PowerJobWorkerConfig();
+ // 传输协议,新用户建议直接上 HTTP
+ config.setProtocol(Protocol.HTTP);
+ // 传输层端口号
+ config.setPort(28888);
+ // worker 的归组,建议使用项目名称
+ config.setAppName("powerjob-multi-worker-2");
+ // server 的服务发现地址,支持多IP 或 HTTP 域名
+ config.setServerAddress(Lists.newArrayList("127.0.0.1:7700", "127.0.0.1:7701"));
+ // 如果没有大型 Map/MapReduce 的需求,建议使用内存来加速计算
+ config.setStoreStrategy(StoreStrategy.DISK);
+ // 执行器的自定义标签,可用于指定部分执行器运行。举例:多单元机房将 TAG 设置为单元名称,即可在控制台指定单元运行
+ config.setTag("CENTER");
+
+ // 以上为核心配置,其他配置可直接参考注释 or 官方文档
+
+ // 注意 Spring 用户请使用 PowerJobSpringWorker 而不是 PowerJobWorker,后者无法使用 Spring 管理的 Bean 作为执行器
+ return new PowerJobSpringWorker(config);
+ }
+
+ */
+}
diff --git a/powerjob-worker-samples/src/main/java/tech/powerjob/samples/processors/SimpleProcessor.java b/powerjob-worker-samples/src/main/java/tech/powerjob/samples/processors/SimpleProcessor.java
index 97876073..96a8f382 100644
--- a/powerjob-worker-samples/src/main/java/tech/powerjob/samples/processors/SimpleProcessor.java
+++ b/powerjob-worker-samples/src/main/java/tech/powerjob/samples/processors/SimpleProcessor.java
@@ -5,6 +5,8 @@ import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
import tech.powerjob.worker.log.OmsLogger;
+import java.util.Optional;
+
/**
* @author Echo009
* @since 2022/4/27
@@ -17,11 +19,11 @@ public class SimpleProcessor implements BasicProcessor {
OmsLogger logger = context.getOmsLogger();
- String jobParams = context.getJobParams();
+ String jobParams = Optional.ofNullable(context.getJobParams()).orElse("S");
logger.info("Current context:{}", context.getWorkflowContext());
logger.info("Current job params:{}", jobParams);
- return jobParams.contains("F") ? new ProcessResult(false) : new ProcessResult(true);
+ return jobParams.contains("F") ? new ProcessResult(false) : new ProcessResult(true, "yeah!");
}
}
\ No newline at end of file
diff --git a/powerjob-worker-samples/src/main/resources/application.properties b/powerjob-worker-samples/src/main/resources/application.properties
index 838e6ce3..f2f6e1b0 100644
--- a/powerjob-worker-samples/src/main/resources/application.properties
+++ b/powerjob-worker-samples/src/main/resources/application.properties
@@ -3,12 +3,14 @@ spring.jpa.open-in-view=false
########### PowerJob-worker properties. ###########
# Whether to enable PowerJob Worker, default is true
powerjob.worker.enabled=true
-# Akka port, default is 27777
-powerjob.worker.akka-port=27777
+# Transport port, default is 27777
+powerjob.worker.port=27777
# Application name, used for grouping applications. Recommend to set the same value as project name.
powerjob.worker.app-name=powerjob-worker-samples
# Address of PowerJob-server node(s). Ip:port or domain. Multiple addresses should be separated with comma.
powerjob.worker.server-address=127.0.0.1:7700,127.0.0.1:7701
+# transport protocol between server and worker
+powerjob.worker.protocol=akka
# Store strategy of H2 database. disk or memory. Default value is disk.
powerjob.worker.store-strategy=disk
# Max length of result. Results that are longer than the value will be truncated.
diff --git a/powerjob-worker-spring-boot-starter/pom.xml b/powerjob-worker-spring-boot-starter/pom.xml
index cc79470f..be0645ce 100644
--- a/powerjob-worker-spring-boot-starter/pom.xml
+++ b/powerjob-worker-spring-boot-starter/pom.xml
@@ -5,16 +5,16 @@
powerjob
tech.powerjob
- 3.0.0
+ 4.0.0
4.0.0
powerjob-worker-spring-boot-starter
- 4.2.1
+ 4.3.0
jar
- 4.2.1
+ 4.3.0
2.7.4
diff --git a/powerjob-worker-spring-boot-starter/src/main/java/tech/powerjob/worker/autoconfigure/PowerJobAutoConfiguration.java b/powerjob-worker-spring-boot-starter/src/main/java/tech/powerjob/worker/autoconfigure/PowerJobAutoConfiguration.java
index a5e079c2..77da03f3 100644
--- a/powerjob-worker-spring-boot-starter/src/main/java/tech/powerjob/worker/autoconfigure/PowerJobAutoConfiguration.java
+++ b/powerjob-worker-spring-boot-starter/src/main/java/tech/powerjob/worker/autoconfigure/PowerJobAutoConfiguration.java
@@ -7,6 +7,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.common.utils.NetUtils;
+import tech.powerjob.worker.PowerJobSpringWorker;
import tech.powerjob.worker.PowerJobWorker;
import tech.powerjob.worker.common.PowerJobWorkerConfig;
@@ -45,11 +46,15 @@ public class PowerJobAutoConfiguration {
/*
* Configuration of worker port. Random port is enabled when port is set with non-positive number.
*/
- int port = worker.getAkkaPort();
- if (port <= 0) {
- port = NetUtils.getRandomPort();
+ if (worker.getPort() != null) {
+ config.setPort(worker.getPort());
+ } else {
+ int port = worker.getAkkaPort();
+ if (port <= 0) {
+ port = NetUtils.getRandomPort();
+ }
+ config.setPort(port);
}
- config.setPort(port);
/*
* appName, name of the application. Applications should be registered in advance to prevent
* error. This property should be the same with what you entered for appName when getting
@@ -57,6 +62,7 @@ public class PowerJobAutoConfiguration {
*/
config.setAppName(worker.getAppName());
config.setServerAddress(serverAddress);
+ config.setProtocol(worker.getProtocol());
/*
* For non-Map/MapReduce tasks, {@code memory} is recommended for speeding up calculation.
* Map/MapReduce tasks may produce batches of subtasks, which could lead to OutOfMemory
@@ -81,11 +87,9 @@ public class PowerJobAutoConfiguration {
config.setHealthReportInterval(worker.getHealthReportInterval());
/*
- * Create OhMyWorker object and set properties.
+ * Create PowerJobSpringWorker object and set properties.
*/
- PowerJobWorker ohMyWorker = new PowerJobWorker();
- ohMyWorker.setConfig(config);
- return ohMyWorker;
+ return new PowerJobSpringWorker(config);
}
}
diff --git a/powerjob-worker-spring-boot-starter/src/main/java/tech/powerjob/worker/autoconfigure/PowerJobProperties.java b/powerjob-worker-spring-boot-starter/src/main/java/tech/powerjob/worker/autoconfigure/PowerJobProperties.java
index 4074c5ff..5ac4181e 100644
--- a/powerjob-worker-spring-boot-starter/src/main/java/tech/powerjob/worker/autoconfigure/PowerJobProperties.java
+++ b/powerjob-worker-spring-boot-starter/src/main/java/tech/powerjob/worker/autoconfigure/PowerJobProperties.java
@@ -1,6 +1,7 @@
package tech.powerjob.worker.autoconfigure;
import tech.powerjob.common.RemoteConstant;
+import tech.powerjob.common.enums.Protocol;
import tech.powerjob.worker.common.constants.StoreStrategy;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.WorkflowContext;
@@ -111,8 +112,14 @@ public class PowerJobProperties {
/**
* Akka port of Powerjob-worker, optional value. Default value of this property is 27777.
* If multiple PowerJob-worker nodes were deployed, different, unique ports should be assigned.
+ * Deprecated, please use 'port'
*/
+ @Deprecated
private int akkaPort = RemoteConstant.DEFAULT_WORKER_PORT;
+ /**
+ * port
+ */
+ private Integer port;
/**
* Address(es) of Powerjob-server node(s). Ip:port or domain.
* Example of single Powerjob-server node:
@@ -125,6 +132,10 @@ public class PowerJobProperties {
*
*/
private String serverAddress;
+ /**
+ * Protocol for communication between WORKER and server
+ */
+ private Protocol protocol = Protocol.AKKA;
/**
* Local store strategy for H2 database. {@code disk} or {@code memory}.
*/
diff --git a/powerjob-worker/pom.xml b/powerjob-worker/pom.xml
index be2e8535..068e1ceb 100644
--- a/powerjob-worker/pom.xml
+++ b/powerjob-worker/pom.xml
@@ -5,38 +5,55 @@
powerjob
tech.powerjob
- 3.0.0
+ 4.0.0
4.0.0
powerjob-worker
- 4.2.1
+ 4.3.0
jar
5.3.23
- 4.2.1
2.1.214
4.0.3
5.9.1
1.2.9
+
+ 4.3.0
+ 4.3.0
+ 4.3.0
+ 4.3.0
-
-
- org.springframework
- spring-context
- ${spring.version}
-
-
-
+
tech.powerjob
powerjob-common
- ${powerjob.common.version}
+ ${powerjob-common.version}
+
+
+
+
+ tech.powerjob
+ powerjob-remote-framework
+ ${powerjob-remote-framework.version}
+
+
+
+
+
+ tech.powerjob
+ powerjob-remote-impl-akka
+ ${powerjob-remote-impl-akka.version}
+
+
+ tech.powerjob
+ powerjob-remote-impl-http
+ ${powerjob-remote-impl-http.version}
@@ -52,6 +69,14 @@
${hikaricp.version}
+
+
+ org.springframework
+ spring-context
+ ${spring.version}
+ provided
+
+
org.junit.jupiter
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/PowerJobSpringWorker.java b/powerjob-worker/src/main/java/tech/powerjob/worker/PowerJobSpringWorker.java
new file mode 100644
index 00000000..c089fb43
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/PowerJobSpringWorker.java
@@ -0,0 +1,49 @@
+package tech.powerjob.worker;
+
+import com.google.common.collect.Lists;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import tech.powerjob.worker.common.PowerJobWorkerConfig;
+import tech.powerjob.worker.extension.processor.ProcessorFactory;
+import tech.powerjob.worker.processor.impl.BuiltInSpringProcessorFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Spring 项目中的 Worker 启动器
+ * 能够获取到由 Spring IOC 容器管理的 processor
+ *
+ * @author tjq
+ * @since 2023/1/20
+ */
+public class PowerJobSpringWorker extends PowerJobWorker implements ApplicationContextAware, InitializingBean, DisposableBean {
+
+
+ public PowerJobSpringWorker(PowerJobWorkerConfig config) {
+ super(config);
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ init();
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ BuiltInSpringProcessorFactory springProcessorFactory = new BuiltInSpringProcessorFactory(applicationContext);
+
+ // append BuiltInSpringProcessorFactory
+ PowerJobWorkerConfig workerConfig = workerRuntime.getWorkerConfig();
+ List processorFactories = Lists.newArrayList(
+ Optional.ofNullable(workerConfig.getProcessorFactoryList())
+ .orElse(Collections.emptyList()));
+ processorFactories.add(springProcessorFactory);
+ workerConfig.setProcessorFactoryList(processorFactories);
+ }
+
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/PowerJobWorker.java b/powerjob-worker/src/main/java/tech/powerjob/worker/PowerJobWorker.java
index ef88197f..61ea7271 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/PowerJobWorker.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/PowerJobWorker.java
@@ -1,30 +1,22 @@
package tech.powerjob.worker;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.DeadLetter;
-import akka.actor.Props;
-import akka.routing.RoundRobinPool;
import com.google.common.base.Stopwatch;
-import com.google.common.collect.Maps;
-import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
+import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.common.utils.HttpUtils;
import tech.powerjob.common.utils.NetUtils;
+import tech.powerjob.remote.framework.base.Address;
+import tech.powerjob.remote.framework.base.ServerType;
+import tech.powerjob.remote.framework.engine.EngineConfig;
+import tech.powerjob.remote.framework.engine.EngineOutput;
+import tech.powerjob.remote.framework.engine.RemoteEngine;
+import tech.powerjob.remote.framework.engine.impl.PowerJobRemoteEngine;
import tech.powerjob.worker.actors.ProcessorTrackerActor;
import tech.powerjob.worker.actors.TaskTrackerActor;
-import tech.powerjob.worker.actors.TroubleshootingActor;
import tech.powerjob.worker.actors.WorkerActor;
import tech.powerjob.worker.background.OmsLogHandler;
import tech.powerjob.worker.background.ServerDiscoveryService;
@@ -32,12 +24,18 @@ import tech.powerjob.worker.background.WorkerHealthReporter;
import tech.powerjob.worker.common.PowerBannerPrinter;
import tech.powerjob.worker.common.PowerJobWorkerConfig;
import tech.powerjob.worker.common.WorkerRuntime;
-import tech.powerjob.worker.common.utils.SpringUtils;
import tech.powerjob.worker.core.executor.ExecutorManager;
+import tech.powerjob.worker.extension.processor.ProcessorFactory;
import tech.powerjob.worker.persistence.TaskPersistenceService;
+import tech.powerjob.worker.processor.PowerJobProcessorLoader;
+import tech.powerjob.worker.processor.ProcessorLoader;
+import tech.powerjob.worker.processor.impl.BuiltInDefaultProcessorFactory;
+import tech.powerjob.worker.processor.impl.JarContainerProcessorFactory;
-import java.util.Map;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
+import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -48,20 +46,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @since 2020/3/16
*/
@Slf4j
-public class PowerJobWorker implements ApplicationContextAware, InitializingBean, DisposableBean {
+public class PowerJobWorker {
+ private final RemoteEngine remoteEngine;
+ protected final WorkerRuntime workerRuntime;
+ private final AtomicBoolean initialized = new AtomicBoolean(false);
- private final WorkerRuntime workerRuntime = new WorkerRuntime();
-
- private final AtomicBoolean initialized = new AtomicBoolean();
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- SpringUtils.inject(applicationContext);
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- init();
+ public PowerJobWorker(PowerJobWorkerConfig config) {
+ this.workerRuntime = new WorkerRuntime();
+ this.remoteEngine = new PowerJobRemoteEngine();
+ workerRuntime.setWorkerConfig(config);
}
public void init() throws Exception {
@@ -75,11 +68,7 @@ public class PowerJobWorker implements ApplicationContextAware, InitializingBean
log.info("[PowerJobWorker] start to initialize PowerJobWorker...");
PowerJobWorkerConfig config = workerRuntime.getWorkerConfig();
-
- // 打印 worker 配置
- log.info("[PowerJobWorker] worker config: {}", JsonUtils.toJSONString(config));
-
- CommonUtils.requireNonNull(config, "can't find OhMyConfig, please set OhMyConfig first");
+ CommonUtils.requireNonNull(config, "can't find PowerJobWorkerConfig, please set PowerJobWorkerConfig first");
try {
PowerBannerPrinter.print();
@@ -98,17 +87,24 @@ public class PowerJobWorker implements ApplicationContextAware, InitializingBean
final ExecutorManager executorManager = new ExecutorManager(workerRuntime.getWorkerConfig());
workerRuntime.setExecutorManager(executorManager);
- // 初始化 ActorSystem(macOS上 new ServerSocket 检测端口占用的方法并不生效,可能是AKKA是Scala写的缘故?没办法...只能靠异常重试了)
- Map overrideConfig = Maps.newHashMap();
- overrideConfig.put("akka.remote.artery.canonical.hostname", NetUtils.getLocalHost());
- overrideConfig.put("akka.remote.artery.canonical.port", config.getPort());
+ // 初始化 ProcessorLoader
+ ProcessorLoader processorLoader = buildProcessorLoader(workerRuntime);
+ workerRuntime.setProcessorLoader(processorLoader);
- Config akkaBasicConfig = ConfigFactory.load(RemoteConstant.WORKER_AKKA_CONFIG_NAME);
- Config akkaFinalConfig = ConfigFactory.parseMap(overrideConfig).withFallback(akkaBasicConfig);
+ // 初始化 actor
+ TaskTrackerActor taskTrackerActor = new TaskTrackerActor(workerRuntime);
+ ProcessorTrackerActor processorTrackerActor = new ProcessorTrackerActor(workerRuntime);
+ WorkerActor workerActor = new WorkerActor(workerRuntime, taskTrackerActor);
- int cores = Runtime.getRuntime().availableProcessors();
- ActorSystem actorSystem = ActorSystem.create(RemoteConstant.WORKER_ACTOR_SYSTEM_NAME, akkaFinalConfig);
- workerRuntime.setActorSystem(actorSystem);
+ // 初始化通讯引擎
+ EngineConfig engineConfig = new EngineConfig()
+ .setType(config.getProtocol().name())
+ .setServerType(ServerType.WORKER)
+ .setBindAddress(new Address().setHost(NetUtils.getLocalHost()).setPort(config.getPort()))
+ .setActorList(Lists.newArrayList(taskTrackerActor, processorTrackerActor, workerActor));
+
+ EngineOutput engineOutput = remoteEngine.start(engineConfig);
+ workerRuntime.setTransporter(engineOutput.getTransporter());
// 连接 server
ServerDiscoveryService serverDiscoveryService = new ServerDiscoveryService(workerRuntime.getAppId(), workerRuntime.getWorkerConfig());
@@ -116,25 +112,10 @@ public class PowerJobWorker implements ApplicationContextAware, InitializingBean
serverDiscoveryService.start(workerRuntime.getExecutorManager().getCoreExecutor());
workerRuntime.setServerDiscoveryService(serverDiscoveryService);
- ActorRef taskTrackerActorRef = actorSystem.actorOf(TaskTrackerActor.props(workerRuntime)
- .withDispatcher("akka.task-tracker-dispatcher")
- .withRouter(new RoundRobinPool(cores * 2)), RemoteConstant.TASK_TRACKER_ACTOR_NAME);
- actorSystem.actorOf(ProcessorTrackerActor.props(workerRuntime)
- .withDispatcher("akka.processor-tracker-dispatcher")
- .withRouter(new RoundRobinPool(cores)), RemoteConstant.PROCESSOR_TRACKER_ACTOR_NAME);
- actorSystem.actorOf(WorkerActor.props(taskTrackerActorRef)
- .withDispatcher("akka.worker-common-dispatcher")
- .withRouter(new RoundRobinPool(cores)), RemoteConstant.WORKER_ACTOR_NAME);
-
- // 处理系统中产生的异常情况
- ActorRef troubleshootingActor = actorSystem.actorOf(Props.create(TroubleshootingActor.class), RemoteConstant.TROUBLESHOOTING_ACTOR_NAME);
- actorSystem.eventStream().subscribe(troubleshootingActor, DeadLetter.class);
-
- log.info("[PowerJobWorker] akka-remote listening address: {}", workerAddress);
- log.info("[PowerJobWorker] akka ActorSystem({}) initialized successfully.", actorSystem);
+ log.info("[PowerJobWorker] PowerJobRemoteEngine initialized successfully.");
// 初始化日志系统
- OmsLogHandler omsLogHandler = new OmsLogHandler(workerAddress, actorSystem, serverDiscoveryService);
+ OmsLogHandler omsLogHandler = new OmsLogHandler(workerAddress, workerRuntime.getTransporter(), serverDiscoveryService);
workerRuntime.setOmsLogHandler(omsLogHandler);
// 初始化存储
@@ -155,10 +136,6 @@ public class PowerJobWorker implements ApplicationContextAware, InitializingBean
}
}
- public void setConfig(PowerJobWorkerConfig config) {
- workerRuntime.setWorkerConfig(config);
- }
-
@SuppressWarnings("rawtypes")
private void assertAppName() {
@@ -191,9 +168,19 @@ public class PowerJobWorker implements ApplicationContextAware, InitializingBean
throw new PowerJobException("no server available!");
}
- @Override
+ private ProcessorLoader buildProcessorLoader(WorkerRuntime runtime) {
+ List customPF = Optional.ofNullable(runtime.getWorkerConfig().getProcessorFactoryList()).orElse(Collections.emptyList());
+ List finalPF = Lists.newArrayList(customPF);
+
+ // 后置添加2个系统 ProcessorLoader
+ finalPF.add(new BuiltInDefaultProcessorFactory());
+ finalPF.add(new JarContainerProcessorFactory(runtime));
+
+ return new PowerJobProcessorLoader(finalPF);
+ }
+
public void destroy() throws Exception {
workerRuntime.getExecutorManager().shutdown();
- workerRuntime.getActorSystem().terminate();
+ remoteEngine.close();
}
}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/actors/ProcessorTrackerActor.java b/powerjob-worker/src/main/java/tech/powerjob/worker/actors/ProcessorTrackerActor.java
index 3c0bffbc..846cfa37 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/actors/ProcessorTrackerActor.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/actors/ProcessorTrackerActor.java
@@ -1,16 +1,17 @@
package tech.powerjob.worker.actors;
-import akka.actor.AbstractActor;
-import akka.actor.Props;
+import lombok.extern.slf4j.Slf4j;
+import tech.powerjob.common.RemoteConstant;
+import tech.powerjob.common.utils.CollectionUtils;
+import tech.powerjob.remote.framework.actor.Actor;
+import tech.powerjob.remote.framework.actor.Handler;
+import tech.powerjob.remote.framework.actor.ProcessType;
import tech.powerjob.worker.common.WorkerRuntime;
-import tech.powerjob.worker.core.tracker.processor.ProcessorTracker;
import tech.powerjob.worker.core.tracker.manager.ProcessorTrackerManager;
+import tech.powerjob.worker.core.tracker.processor.ProcessorTracker;
import tech.powerjob.worker.persistence.TaskDO;
import tech.powerjob.worker.pojo.request.TaskTrackerStartTaskReq;
import tech.powerjob.worker.pojo.request.TaskTrackerStopInstanceReq;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.CollectionUtils;
import java.util.List;
@@ -21,29 +22,21 @@ import java.util.List;
* @since 2020/3/17
*/
@Slf4j
-@AllArgsConstructor
-public class ProcessorTrackerActor extends AbstractActor {
+@Actor(path = RemoteConstant.WPT_PATH)
+public class ProcessorTrackerActor {
private final WorkerRuntime workerRuntime;
- public static Props props(WorkerRuntime workerRuntime) {
- return Props.create(ProcessorTrackerActor.class, () -> new ProcessorTrackerActor(workerRuntime));
- }
-
- @Override
- public Receive createReceive() {
- return receiveBuilder()
- .match(TaskTrackerStartTaskReq.class, this::onReceiveTaskTrackerStartTaskReq)
- .match(TaskTrackerStopInstanceReq.class, this::onReceiveTaskTrackerStopInstanceReq)
- .matchAny(obj -> log.warn("[ProcessorTrackerActor] receive unknown request: {}.", obj))
- .build();
+ public ProcessorTrackerActor(WorkerRuntime workerRuntime) {
+ this.workerRuntime = workerRuntime;
}
/**
* 处理来自TaskTracker的task执行请求
* @param req 请求
*/
- private void onReceiveTaskTrackerStartTaskReq(TaskTrackerStartTaskReq req) {
+ @Handler(path = RemoteConstant.WPT_HANDLER_START_TASK, processType = ProcessType.NO_BLOCKING)
+ public void onReceiveTaskTrackerStartTaskReq(TaskTrackerStartTaskReq req) {
Long instanceId = req.getInstanceInfo().getInstanceId();
@@ -68,7 +61,8 @@ public class ProcessorTrackerActor extends AbstractActor {
* 处理来自TaskTracker停止任务的请求
* @param req 请求
*/
- private void onReceiveTaskTrackerStopInstanceReq(TaskTrackerStopInstanceReq req) {
+ @Handler(path = RemoteConstant.WPT_HANDLER_STOP_INSTANCE)
+ public void onReceiveTaskTrackerStopInstanceReq(TaskTrackerStopInstanceReq req) {
Long instanceId = req.getInstanceId();
List removedPts = ProcessorTrackerManager.removeProcessorTracker(instanceId);
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/actors/TaskTrackerActor.java b/powerjob-worker/src/main/java/tech/powerjob/worker/actors/TaskTrackerActor.java
index c95a585b..917f3abb 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/actors/TaskTrackerActor.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/actors/TaskTrackerActor.java
@@ -1,9 +1,6 @@
package tech.powerjob.worker.actors;
-import akka.actor.AbstractActor;
-import akka.actor.Props;
import com.google.common.collect.Lists;
-import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import tech.powerjob.common.enums.ExecuteType;
import tech.powerjob.common.enums.TimeExpressionType;
@@ -12,6 +9,8 @@ import tech.powerjob.common.request.ServerQueryInstanceStatusReq;
import tech.powerjob.common.request.ServerScheduleJobReq;
import tech.powerjob.common.request.ServerStopInstanceReq;
import tech.powerjob.common.response.AskResponse;
+import tech.powerjob.remote.framework.actor.Actor;
+import tech.powerjob.remote.framework.actor.Handler;
import tech.powerjob.worker.common.WorkerRuntime;
import tech.powerjob.worker.common.constants.TaskStatus;
import tech.powerjob.worker.core.tracker.manager.HeavyTaskTrackerManager;
@@ -26,6 +25,8 @@ import tech.powerjob.worker.pojo.request.ProcessorTrackerStatusReportReq;
import java.util.List;
+import static tech.powerjob.common.RemoteConstant.*;
+
/**
* worker 的 master 节点,处理来自 server 的 jobInstance 请求和来自 worker 的task 请求
*
@@ -33,47 +34,29 @@ import java.util.List;
* @since 2020/3/17
*/
@Slf4j
-@AllArgsConstructor
-public class TaskTrackerActor extends AbstractActor {
+@Actor(path = WTT_PATH)
+public class TaskTrackerActor {
private final WorkerRuntime workerRuntime;
- public static Props props(WorkerRuntime workerRuntime) {
- return Props.create(TaskTrackerActor.class, () -> new TaskTrackerActor(workerRuntime));
+ public TaskTrackerActor(WorkerRuntime workerRuntime) {
+ this.workerRuntime = workerRuntime;
}
- @Override
- public Receive createReceive() {
- return receiveBuilder()
- .match(ProcessorReportTaskStatusReq.class, this::onReceiveProcessorReportTaskStatusReq)
- .match(ServerScheduleJobReq.class, this::onReceiveServerScheduleJobReq)
- .match(ProcessorMapTaskRequest.class, this::onReceiveProcessorMapTaskRequest)
- .match(ProcessorTrackerStatusReportReq.class, this::onReceiveProcessorTrackerStatusReportReq)
- .match(ServerStopInstanceReq.class, this::onReceiveServerStopInstanceReq)
- .match(ServerQueryInstanceStatusReq.class, this::onReceiveServerQueryInstanceStatusReq)
- .matchAny(obj -> log.warn("[ServerRequestActor] receive unknown request: {}.", obj))
- .build();
- }
-
-
/**
* 子任务状态上报 处理器
*/
- private void onReceiveProcessorReportTaskStatusReq(ProcessorReportTaskStatusReq req) {
+ @Handler(path = WTT_HANDLER_REPORT_TASK_STATUS)
+ public AskResponse onReceiveProcessorReportTaskStatusReq(ProcessorReportTaskStatusReq req) {
int taskStatus = req.getStatus();
// 只有重量级任务才会有两级任务状态上报的机制
HeavyTaskTracker taskTracker = HeavyTaskTrackerManager.getTaskTracker(req.getInstanceId());
- // 结束状态需要回复接受成功
- if (TaskStatus.FINISHED_STATUS.contains(taskStatus)) {
- AskResponse askResponse = AskResponse.succeed(null);
- getSender().tell(askResponse, getSelf());
- }
// 手动停止 TaskTracker 的情况下会出现这种情况
if (taskTracker == null) {
log.warn("[TaskTrackerActor] receive ProcessorReportTaskStatusReq({}) but system can't find TaskTracker.", req);
- return;
+ return null;
}
if (ProcessorReportTaskStatusReq.BROADCAST.equals(req.getCmd())) {
@@ -84,17 +67,25 @@ public class TaskTrackerActor extends AbstractActor {
// 更新工作流上下文
taskTracker.updateAppendedWfContext(req.getAppendedWfContext());
+
+ // 结束状态需要回复接受成功
+ if (TaskStatus.FINISHED_STATUS.contains(taskStatus)) {
+ return AskResponse.succeed(null);
+ }
+
+ return null;
}
/**
* 子任务 map 处理器
*/
- private void onReceiveProcessorMapTaskRequest(ProcessorMapTaskRequest req) {
+ @Handler(path = WTT_HANDLER_MAP_TASK)
+ public AskResponse onReceiveProcessorMapTaskRequest(ProcessorMapTaskRequest req) {
HeavyTaskTracker taskTracker = HeavyTaskTrackerManager.getTaskTracker(req.getInstanceId());
if (taskTracker == null) {
log.warn("[TaskTrackerActor] receive ProcessorMapTaskRequest({}) but system can't find TaskTracker.", req);
- return;
+ return null;
}
boolean success = false;
@@ -121,13 +112,14 @@ public class TaskTrackerActor extends AbstractActor {
AskResponse response = new AskResponse();
response.setSuccess(success);
- getSender().tell(response, getSelf());
+ return response;
}
/**
* 服务器任务调度处理器
*/
- private void onReceiveServerScheduleJobReq(ServerScheduleJobReq req) {
+ @Handler(path = WTT_HANDLER_RUN_JOB)
+ public void onReceiveServerScheduleJobReq(ServerScheduleJobReq req) {
log.debug("[TaskTrackerActor] server schedule job by request: {}.", req);
Long instanceId = req.getInstanceId();
// 区分轻量级任务模型以及重量级任务模型
@@ -168,7 +160,8 @@ public class TaskTrackerActor extends AbstractActor {
/**
* ProcessorTracker 心跳处理器
*/
- private void onReceiveProcessorTrackerStatusReportReq(ProcessorTrackerStatusReportReq req) {
+ @Handler(path = WTT_HANDLER_REPORT_PROCESSOR_TRACKER_STATUS)
+ public void onReceiveProcessorTrackerStatusReportReq(ProcessorTrackerStatusReportReq req) {
HeavyTaskTracker taskTracker = HeavyTaskTrackerManager.getTaskTracker(req.getInstanceId());
if (taskTracker == null) {
@@ -181,8 +174,8 @@ public class TaskTrackerActor extends AbstractActor {
/**
* 停止任务实例
*/
- private void onReceiveServerStopInstanceReq(ServerStopInstanceReq req) {
-
+ @Handler(path = WTT_HANDLER_STOP_INSTANCE)
+ public void onReceiveServerStopInstanceReq(ServerStopInstanceReq req) {
log.info("[TaskTrackerActor] receive ServerStopInstanceReq({}).", req);
HeavyTaskTracker heavyTaskTracker = HeavyTaskTrackerManager.getTaskTracker(req.getInstanceId());
@@ -201,7 +194,8 @@ public class TaskTrackerActor extends AbstractActor {
/**
* 查询任务实例运行状态
*/
- private void onReceiveServerQueryInstanceStatusReq(ServerQueryInstanceStatusReq req) {
+ @Handler(path = WTT_HANDLER_QUERY_INSTANCE_STATUS)
+ public AskResponse onReceiveServerQueryInstanceStatusReq(ServerQueryInstanceStatusReq req) {
AskResponse askResponse;
TaskTracker taskTracker = HeavyTaskTrackerManager.getTaskTracker(req.getInstanceId());
if (taskTracker == null && (taskTracker = LightTaskTrackerManager.getTaskTracker(req.getInstanceId())) == null) {
@@ -211,7 +205,7 @@ public class TaskTrackerActor extends AbstractActor {
InstanceDetail instanceDetail = taskTracker.fetchRunningStatus();
askResponse = AskResponse.succeed(instanceDetail);
}
- getSender().tell(askResponse, getSelf());
+ return askResponse;
}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/actors/WorkerActor.java b/powerjob-worker/src/main/java/tech/powerjob/worker/actors/WorkerActor.java
index 8edf7cf7..052b2a4a 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/actors/WorkerActor.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/actors/WorkerActor.java
@@ -1,12 +1,14 @@
package tech.powerjob.worker.actors;
-import akka.actor.AbstractActor;
-import akka.actor.ActorRef;
-import akka.actor.Props;
-import tech.powerjob.worker.container.OmsContainerFactory;
-import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import tech.powerjob.common.request.*;
+import tech.powerjob.common.response.AskResponse;
+import tech.powerjob.remote.framework.actor.Actor;
+import tech.powerjob.remote.framework.actor.Handler;
+import tech.powerjob.worker.common.WorkerRuntime;
+import tech.powerjob.worker.container.OmsContainerFactory;
+
+import static tech.powerjob.common.RemoteConstant.*;
/**
* Worker节点Actor,接受服务器请求
@@ -15,36 +17,38 @@ import tech.powerjob.common.request.*;
* @since 2020/3/24
*/
@Slf4j
-@AllArgsConstructor
-public class WorkerActor extends AbstractActor {
+@Actor(path = WORKER_PATH)
+public class WorkerActor {
- private final ActorRef taskTrackerActorRef;
+ private final WorkerRuntime workerRuntime;
+ private final TaskTrackerActor taskTrackerActor;
- public static Props props(ActorRef taskTrackerActorRef) {
- return Props.create(WorkerActor.class, () -> new WorkerActor(taskTrackerActorRef));
+
+ public WorkerActor(WorkerRuntime workerRuntime, TaskTrackerActor taskTrackerActor) {
+ this.workerRuntime = workerRuntime;
+ this.taskTrackerActor = taskTrackerActor;
}
- @Override
- public Receive createReceive() {
- return receiveBuilder()
- .match(ServerDeployContainerRequest.class, this::onReceiveServerDeployContainerRequest)
- .match(ServerDestroyContainerRequest.class, this::onReceiveServerDestroyContainerRequest)
- .match(ServerScheduleJobReq.class, this::forward2TaskTracker)
- .match(ServerStopInstanceReq.class, this::forward2TaskTracker)
- .match(ServerQueryInstanceStatusReq.class, this::forward2TaskTracker)
- .matchAny(obj -> log.warn("[WorkerActor] receive unknown request: {}.", obj))
- .build();
- }
-
- private void onReceiveServerDeployContainerRequest(ServerDeployContainerRequest request) {
+ @Handler(path = WORKER_HANDLER_DEPLOY_CONTAINER)
+ public void onReceiveServerDeployContainerRequest(ServerDeployContainerRequest request) {
OmsContainerFactory.deployContainer(request);
}
- private void onReceiveServerDestroyContainerRequest(ServerDestroyContainerRequest request) {
+ @Handler(path = WORKER_HANDLER_DESTROY_CONTAINER)
+ public void onReceiveServerDestroyContainerRequest(ServerDestroyContainerRequest request) {
OmsContainerFactory.destroyContainer(request.getContainerId());
}
- private void forward2TaskTracker(Object obj) {
- taskTrackerActorRef.forward(obj, getContext());
+ @Handler(path = WTT_HANDLER_RUN_JOB)
+ public void onReceiveServerScheduleJobReq(ServerScheduleJobReq req) {
+ taskTrackerActor.onReceiveServerScheduleJobReq(req);
+ }
+ @Handler(path = WTT_HANDLER_STOP_INSTANCE)
+ public void onReceiveServerStopInstanceReq(ServerStopInstanceReq req) {
+ taskTrackerActor.onReceiveServerStopInstanceReq(req);
+ }
+ @Handler(path = WTT_HANDLER_QUERY_INSTANCE_STATUS)
+ public AskResponse onReceiveServerQueryInstanceStatusReq(ServerQueryInstanceStatusReq req) {
+ return taskTrackerActor.onReceiveServerQueryInstanceStatusReq(req);
}
}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/background/OmsLogHandler.java b/powerjob-worker/src/main/java/tech/powerjob/worker/background/OmsLogHandler.java
index 54010994..5ea219cc 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/background/OmsLogHandler.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/background/OmsLogHandler.java
@@ -1,15 +1,14 @@
package tech.powerjob.worker.background;
-import akka.actor.ActorSelection;
-import akka.actor.ActorSystem;
import tech.powerjob.common.enums.LogLevel;
import tech.powerjob.common.model.InstanceLogContent;
import tech.powerjob.common.request.WorkerLogReportReq;
-import tech.powerjob.worker.common.utils.AkkaUtils;
+import tech.powerjob.remote.framework.transporter.Transporter;
import com.google.common.collect.Lists;
import com.google.common.collect.Queues;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import java.util.List;
import java.util.concurrent.BlockingQueue;
@@ -27,7 +26,7 @@ import java.util.concurrent.locks.ReentrantLock;
public class OmsLogHandler {
private final String workerAddress;
- private final ActorSystem actorSystem;
+ private final Transporter transporter;
private final ServerDiscoveryService serverDiscoveryService;
// 处理线程,需要通过线程池启动
@@ -42,9 +41,9 @@ public class OmsLogHandler {
// 本地囤积阈值
private static final int REPORT_SIZE = 1024;
- public OmsLogHandler(String workerAddress, ActorSystem actorSystem, ServerDiscoveryService serverDiscoveryService) {
+ public OmsLogHandler(String workerAddress, Transporter transporter, ServerDiscoveryService serverDiscoveryService) {
this.workerAddress = workerAddress;
- this.actorSystem = actorSystem;
+ this.transporter = transporter;
this.serverDiscoveryService = serverDiscoveryService;
}
@@ -81,9 +80,9 @@ public class OmsLogHandler {
try {
- String serverPath = AkkaUtils.getServerActorPath(serverDiscoveryService.getCurrentServerAddress());
+ final String currentServerAddress = serverDiscoveryService.getCurrentServerAddress();
// 当前无可用 Server
- if (StringUtils.isEmpty(serverPath)) {
+ if (StringUtils.isEmpty(currentServerAddress)) {
if (!logQueue.isEmpty()) {
logQueue.clear();
log.warn("[OmsLogHandler] because there is no available server to report logs which leads to queue accumulation, oms discarded all logs.");
@@ -91,7 +90,6 @@ public class OmsLogHandler {
return;
}
- ActorSelection serverActor = actorSystem.actorSelection(serverPath);
List logs = Lists.newLinkedList();
while (!logQueue.isEmpty()) {
@@ -102,7 +100,7 @@ public class OmsLogHandler {
if (logs.size() >= BATCH_SIZE) {
WorkerLogReportReq req = new WorkerLogReportReq(workerAddress, Lists.newLinkedList(logs));
// 不可靠请求,WEB日志不追求极致
- serverActor.tell(req, null);
+ TransportUtils.reportLogs(req, currentServerAddress, transporter);
logs.clear();
}
@@ -113,7 +111,7 @@ public class OmsLogHandler {
if (!logs.isEmpty()) {
WorkerLogReportReq req = new WorkerLogReportReq(workerAddress, logs);
- serverActor.tell(req, null);
+ TransportUtils.reportLogs(req, currentServerAddress, transporter);
}
}finally {
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/background/ServerDiscoveryService.java b/powerjob-worker/src/main/java/tech/powerjob/worker/background/ServerDiscoveryService.java
index 7e25a62f..e7e1752c 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/background/ServerDiscoveryService.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/background/ServerDiscoveryService.java
@@ -1,17 +1,20 @@
package tech.powerjob.worker.background;
+import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
-import org.springframework.util.CollectionUtils;
+import tech.powerjob.common.OmsConstant;
import tech.powerjob.common.exception.PowerJobException;
+import tech.powerjob.common.request.ServerDiscoveryRequest;
import tech.powerjob.common.response.ResultDTO;
import tech.powerjob.common.serialize.JsonUtils;
+import tech.powerjob.common.utils.CollectionUtils;
import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.common.utils.HttpUtils;
import tech.powerjob.worker.common.PowerJobWorkerConfig;
-import tech.powerjob.worker.core.tracker.task.heavy.HeavyTaskTracker;
import tech.powerjob.worker.core.tracker.manager.HeavyTaskTrackerManager;
+import tech.powerjob.worker.core.tracker.task.heavy.HeavyTaskTracker;
import java.util.List;
import java.util.Map;
@@ -37,7 +40,7 @@ public class ServerDiscoveryService {
/**
* 服务发现地址
*/
- private static final String DISCOVERY_URL = "http://%s/server/acquire?appId=%d¤tServer=%s&protocol=AKKA";
+ private static final String DISCOVERY_URL = "http://%s/server/acquire?%s";
/**
* 失败次数
*/
@@ -55,7 +58,7 @@ public class ServerDiscoveryService {
public void start(ScheduledExecutorService timingPool) {
this.currentServerAddress = discovery();
- if (org.springframework.util.StringUtils.isEmpty(this.currentServerAddress) && !config.isEnableTestMode()) {
+ if (StringUtils.isEmpty(this.currentServerAddress) && !config.isEnableTestMode()) {
throw new PowerJobException("can't find any available server, this worker has been quarantined.");
}
// 这里必须保证成功
@@ -131,7 +134,7 @@ public class ServerDiscoveryService {
@SuppressWarnings("rawtypes")
private String acquire(String httpServerAddress) {
String result = null;
- String url = String.format(DISCOVERY_URL, httpServerAddress, appId, currentServerAddress);
+ String url = buildServerDiscoveryUrl(httpServerAddress);
try {
result = CommonUtils.executeWithRetry0(() -> HttpUtils.get(url));
}catch (Exception ignore) {
@@ -147,4 +150,15 @@ public class ServerDiscoveryService {
}
return null;
}
+
+ private String buildServerDiscoveryUrl(String address) {
+
+ ServerDiscoveryRequest serverDiscoveryRequest = new ServerDiscoveryRequest()
+ .setAppId(appId)
+ .setCurrentServer(currentServerAddress)
+ .setProtocol(config.getProtocol().name().toUpperCase());
+
+ String query = Joiner.on(OmsConstant.AND).withKeyValueSeparator(OmsConstant.EQUAL).join(serverDiscoveryRequest.toMap());
+ return String.format(DISCOVERY_URL, address, query);
+ }
}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/background/WorkerHealthReporter.java b/powerjob-worker/src/main/java/tech/powerjob/worker/background/WorkerHealthReporter.java
index 50d50f20..645d74ed 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/background/WorkerHealthReporter.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/background/WorkerHealthReporter.java
@@ -1,17 +1,15 @@
package tech.powerjob.worker.background;
-import akka.actor.ActorSelection;
import lombok.RequiredArgsConstructor;
-import tech.powerjob.common.enums.Protocol;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
import tech.powerjob.common.model.SystemMetrics;
import tech.powerjob.common.request.WorkerHeartbeat;
import tech.powerjob.worker.common.PowerJobWorkerVersion;
import tech.powerjob.worker.common.WorkerRuntime;
-import tech.powerjob.worker.common.utils.AkkaUtils;
import tech.powerjob.worker.common.utils.SystemInfoUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.container.OmsContainerFactory;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.StringUtils;
import tech.powerjob.worker.core.tracker.manager.HeavyTaskTrackerManager;
import tech.powerjob.worker.core.tracker.manager.LightTaskTrackerManager;
@@ -54,8 +52,8 @@ public class WorkerHealthReporter implements Runnable {
heartbeat.setAppId(workerRuntime.getAppId());
heartbeat.setHeartbeatTime(System.currentTimeMillis());
heartbeat.setVersion(PowerJobWorkerVersion.getVersion());
- heartbeat.setProtocol(Protocol.AKKA.name());
- heartbeat.setClient("Atlantis");
+ heartbeat.setProtocol(workerRuntime.getWorkerConfig().getProtocol().name());
+ heartbeat.setClient("KingPenguin");
heartbeat.setTag(workerRuntime.getWorkerConfig().getTag());
// 上报 Tracker 数量
@@ -68,8 +66,7 @@ public class WorkerHealthReporter implements Runnable {
// 获取当前加载的容器列表
heartbeat.setContainerInfos(OmsContainerFactory.getDeployedContainerInfos());
// 发送请求
- String serverPath = AkkaUtils.getServerActorPath(currentServer);
- if (StringUtils.isEmpty(serverPath)) {
+ if (StringUtils.isEmpty(currentServer)) {
return;
}
// log
@@ -82,7 +79,7 @@ public class WorkerHealthReporter implements Runnable {
workerRuntime.getWorkerConfig().getMaxHeavyweightTaskNum(),
heartbeat.getHeavyTaskTrackerNum()
);
- ActorSelection actorSelection = workerRuntime.getActorSystem().actorSelection(serverPath);
- actorSelection.tell(heartbeat, null);
+
+ TransportUtils.reportWorkerHeartbeat(heartbeat, currentServer, workerRuntime.getTransporter());
}
}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/common/PowerJobWorkerConfig.java b/powerjob-worker/src/main/java/tech/powerjob/worker/common/PowerJobWorkerConfig.java
index 961aacec..c9238d1c 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/common/PowerJobWorkerConfig.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/common/PowerJobWorkerConfig.java
@@ -4,10 +4,12 @@ import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import tech.powerjob.common.RemoteConstant;
+import tech.powerjob.common.enums.Protocol;
import tech.powerjob.worker.common.constants.StoreStrategy;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.WorkflowContext;
import tech.powerjob.worker.extension.SystemMetricsCollector;
+import tech.powerjob.worker.extension.processor.ProcessorFactory;
import java.util.List;
@@ -35,6 +37,10 @@ public class PowerJobWorkerConfig {
* Do not mistake for ActorSystem port. Do not add any prefix, i.e. http://.
*/
private List serverAddress = Lists.newArrayList();
+ /**
+ * Protocol for communication between WORKER and server
+ */
+ private Protocol protocol = Protocol.AKKA;
/**
* Max length of response result. Result that is longer than the value will be truncated.
* {@link ProcessResult} max length for #msg
@@ -60,9 +66,14 @@ public class PowerJobWorkerConfig {
* {@link WorkflowContext} max length for #appendedContextData
*/
private int maxAppendedWfContextLength = 8192;
-
-
+ /**
+ * user-customized system metrics collector
+ */
private SystemMetricsCollector systemMetricsCollector;
+ /**
+ * Processor factory for custom logic, generally used for IOC framework processor bean injection that is not officially supported by PowerJob
+ */
+ private List processorFactoryList;
private String tag;
/**
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/common/WorkerRuntime.java b/powerjob-worker/src/main/java/tech/powerjob/worker/common/WorkerRuntime.java
index f7b07c41..19524e6f 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/common/WorkerRuntime.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/common/WorkerRuntime.java
@@ -1,12 +1,12 @@
package tech.powerjob.worker.common;
-import akka.actor.ActorSystem;
+import lombok.Data;
+import tech.powerjob.remote.framework.transporter.Transporter;
import tech.powerjob.worker.background.OmsLogHandler;
import tech.powerjob.worker.background.ServerDiscoveryService;
-import tech.powerjob.worker.background.WorkerHealthReporter;
import tech.powerjob.worker.core.executor.ExecutorManager;
import tech.powerjob.worker.persistence.TaskPersistenceService;
-import lombok.Data;
+import tech.powerjob.worker.processor.ProcessorLoader;
/**
* store worker's runtime
@@ -18,14 +18,22 @@ import lombok.Data;
public class WorkerRuntime {
private Long appId;
-
+ /**
+ * 当前执行器地址
+ */
private String workerAddress;
-
+ /**
+ * 用户配置
+ */
private PowerJobWorkerConfig workerConfig;
-
- private ActorSystem actorSystem;
-
- private WorkerHealthReporter healthReporter;
+ /**
+ * 通讯器
+ */
+ private Transporter transporter;
+ /**
+ * 处理器加载器
+ */
+ private ProcessorLoader processorLoader;
private ExecutorManager executorManager;
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/AkkaUtils.java b/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/AkkaUtils.java
deleted file mode 100644
index c94d2f2f..00000000
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/AkkaUtils.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package tech.powerjob.worker.common.utils;
-
-import akka.actor.ActorSelection;
-import akka.pattern.Patterns;
-import tech.powerjob.common.exception.PowerJobException;
-import tech.powerjob.common.response.AskResponse;
-import tech.powerjob.common.RemoteConstant;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-
-import java.time.Duration;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.TimeUnit;
-
-/**
- * AKKA 工具类
- *
- * @author tjq
- * @since 2020/3/17
- */
-@Slf4j
-public class AkkaUtils {
-
- /**
- * akka://@:/
- */
- private static final String AKKA_NODE_PATH = "akka://%s@%s/user/%s";
-
- public static String getAkkaWorkerPath(String address, String actorName) {
- return String.format(AKKA_NODE_PATH, RemoteConstant.WORKER_ACTOR_SYSTEM_NAME, address, actorName);
- }
-
- public static String getServerActorPath(String serverAddress) {
- if (StringUtils.isEmpty(serverAddress)) {
- return null;
- }
- return String.format(AKKA_NODE_PATH, RemoteConstant.SERVER_ACTOR_SYSTEM_NAME, serverAddress, RemoteConstant.SERVER_ACTOR_NAME);
- }
-
- /**
- * 可靠传输
- * @param remote 远程 AKKA 节点
- * @param msg 需要传输的对象
- * @return true: 对方接收成功 / false: 对方接收失败(可能传输成功但对方处理失败,需要协同处理 AskResponse 返回值)
- */
- public static boolean reliableTransmit(ActorSelection remote, Object msg) {
- try {
- return easyAsk(remote, msg).isSuccess();
- }catch (Exception e) {
- log.warn("[PowerTransmitter] transmit {} failed", msg, e);
- }
- return false;
- }
-
- public static AskResponse easyAsk(ActorSelection remote, Object msg) {
- try {
- CompletionStage ask = Patterns.ask(remote, msg, Duration.ofMillis(RemoteConstant.DEFAULT_TIMEOUT_MS));
- return (AskResponse) ask.toCompletableFuture().get(RemoteConstant.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- }catch (Exception e) {
- throw new PowerJobException(e);
- }
- }
-
-}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/PowerFileUtils.java b/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/PowerFileUtils.java
new file mode 100644
index 00000000..1d0331ce
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/PowerFileUtils.java
@@ -0,0 +1,30 @@
+package tech.powerjob.worker.common.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import tech.powerjob.common.PowerJobDKey;
+
+/**
+ * 文件工具
+ *
+ * @author tjq
+ * @since 2023/1/22
+ */
+@Slf4j
+public class PowerFileUtils {
+
+ /**
+ * 获取工作目录
+ * @return 允许用户通过启动配置文件自定义存储目录,默认为 user.home
+ */
+ public static String workspace() {
+ String workspaceByDKey = System.getProperty(PowerJobDKey.WORKER_WORK_SPACE);
+ if (StringUtils.isNotEmpty(workspaceByDKey)) {
+ log.info("[PowerFileUtils] [workspace] use custom workspace: {}", workspaceByDKey);
+ return workspaceByDKey;
+ }
+ final String userHome = System.getProperty("user.home").concat("/powerjob/worker");
+ log.info("[PowerFileUtils] [workspace] use user.home as workspace: {}", userHome);
+ return userHome;
+ }
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/SpringUtils.java b/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/SpringUtils.java
deleted file mode 100644
index 953e4713..00000000
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/SpringUtils.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package tech.powerjob.worker.common.utils;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.ApplicationContext;
-
-/**
- * Spring ApplicationContext 工具类
- *
- * @author tjq
- * @since 2020/3/16
- */
-@Slf4j
-public class SpringUtils {
-
- private static boolean supportSpringBean = false;
-
- private static ApplicationContext context;
-
- public static void inject(ApplicationContext ctx) {
- context = ctx;
- supportSpringBean = true;
- }
-
- public static boolean supportSpringBean() {
- return supportSpringBean;
- }
-
- public static T getBean(Class clz) {
- return context.getBean(clz);
- }
-
- @SuppressWarnings("unchecked")
- public static T getBean(String className) throws Exception {
-
- // 1. ClassLoader 存在,则直接使用 clz 加载
- ClassLoader classLoader = context.getClassLoader();
- if (classLoader != null) {
- return (T) context.getBean(classLoader.loadClass(className));
- }
- // 2. ClassLoader 不存在(系统类加载器不可见),尝试用类名称小写加载
- String[] split = className.split("\\.");
- String beanName = split[split.length - 1];
- // 小写转大写
- char[] cs = beanName.toCharArray();
- cs[0] += 32;
- String beanName0 = String.valueOf(cs);
- log.warn("[SpringUtils] can't get ClassLoader from context[{}], try to load by beanName:{}", context, beanName0);
- return (T) context.getBean(beanName0);
- }
-
-}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/TransportUtils.java b/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/TransportUtils.java
new file mode 100644
index 00000000..3a7f1127
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/common/utils/TransportUtils.java
@@ -0,0 +1,117 @@
+package tech.powerjob.worker.common.utils;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import tech.powerjob.common.PowerSerializable;
+import tech.powerjob.common.RemoteConstant;
+import tech.powerjob.common.exception.PowerJobCheckedException;
+import tech.powerjob.common.request.*;
+import tech.powerjob.common.response.AskResponse;
+import tech.powerjob.remote.framework.base.Address;
+import tech.powerjob.remote.framework.base.HandlerLocation;
+import tech.powerjob.remote.framework.base.ServerType;
+import tech.powerjob.remote.framework.base.URL;
+import tech.powerjob.remote.framework.transporter.Transporter;
+import tech.powerjob.worker.common.WorkerRuntime;
+import tech.powerjob.worker.pojo.request.*;
+
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.TimeUnit;
+
+import static tech.powerjob.common.RemoteConstant.*;
+
+/**
+ * 通讯工具
+ *
+ * @author tjq
+ * @since 2023/1/20
+ */
+@Slf4j
+public class TransportUtils {
+
+ public static void ttReportInstanceStatus(TaskTrackerReportInstanceStatusReq req, String address, Transporter transporter) {
+ final URL url = easyBuildUrl(ServerType.SERVER, S4W_PATH, S4W_HANDLER_REPORT_INSTANCE_STATUS, address);
+ transporter.tell(url, req);
+ }
+
+ public static void ttStartPtTask(TaskTrackerStartTaskReq req, String address, Transporter transporter) {
+ final URL url = easyBuildUrl(ServerType.WORKER, WPT_PATH, WPT_HANDLER_START_TASK, address);
+ transporter.tell(url, req);
+ }
+
+ public static void ttStopPtInstance(TaskTrackerStopInstanceReq req, String address, Transporter transporter) {
+ final URL url = easyBuildUrl(ServerType.WORKER, WPT_PATH, WPT_HANDLER_STOP_INSTANCE, address);
+ transporter.tell(url, req);
+ }
+
+ public static void ptReportTask(ProcessorReportTaskStatusReq req, String address, WorkerRuntime workerRuntime) {
+ final URL url = easyBuildUrl(ServerType.WORKER, WTT_PATH, WTT_HANDLER_REPORT_TASK_STATUS, address);
+ workerRuntime.getTransporter().tell(url, req);
+ }
+
+ public static void ptReportSelfStatus(ProcessorTrackerStatusReportReq req, String address, WorkerRuntime workerRuntime) {
+ final URL url = easyBuildUrl(ServerType.WORKER, WTT_PATH, WTT_HANDLER_REPORT_PROCESSOR_TRACKER_STATUS, address);
+ workerRuntime.getTransporter().tell(url, req);
+ }
+
+ public static void reportLogs(WorkerLogReportReq req, String address, Transporter transporter) {
+ final URL url = easyBuildUrl(ServerType.SERVER, S4W_PATH, S4W_HANDLER_REPORT_LOG, address);
+ transporter.tell(url, req);
+ }
+
+ public static void reportWorkerHeartbeat(WorkerHeartbeat req, String address, Transporter transporter) {
+ final URL url = easyBuildUrl(ServerType.SERVER, S4W_PATH, S4W_HANDLER_WORKER_HEARTBEAT, address);
+ transporter.tell(url, req);
+ }
+
+ public static boolean reliablePtReportTask(ProcessorReportTaskStatusReq req, String address, WorkerRuntime workerRuntime) {
+ try {
+ return reliableAsk(ServerType.WORKER, WTT_PATH, WTT_HANDLER_REPORT_TASK_STATUS, address, req, workerRuntime.getTransporter()).isSuccess();
+ } catch (Exception e) {
+ log.warn("[PowerJobTransport] reliablePtReportTask failed: {}", req, e);
+ return false;
+ }
+ }
+
+ public static boolean reliableMapTask(ProcessorMapTaskRequest req, String address, WorkerRuntime workerRuntime) throws PowerJobCheckedException {
+ try {
+ return reliableAsk(ServerType.WORKER, WTT_PATH, WTT_HANDLER_MAP_TASK, address, req, workerRuntime.getTransporter()).isSuccess();
+ } catch (Throwable throwable) {
+ throw new PowerJobCheckedException(throwable);
+ }
+ }
+
+ @SneakyThrows
+ public static boolean reliableTtReportInstanceStatus(TaskTrackerReportInstanceStatusReq req, String address, Transporter transporter) {
+ return reliableAsk(ServerType.SERVER, S4W_PATH, S4W_HANDLER_REPORT_INSTANCE_STATUS, address, req, transporter).isSuccess();
+ }
+
+ @SneakyThrows
+ public static AskResponse reliableQueryJobCluster(WorkerQueryExecutorClusterReq req, String address, Transporter transporter) {
+ return reliableAsk(ServerType.SERVER, S4W_PATH, S4W_HANDLER_QUERY_JOB_CLUSTER, address, req, transporter);
+ }
+
+ @SneakyThrows
+ public static AskResponse reliableQueryContainerInfo(WorkerNeedDeployContainerRequest req, String address, Transporter transporter) {
+ return reliableAsk(ServerType.SERVER, S4W_PATH, S4W_HANDLER_WORKER_NEED_DEPLOY_CONTAINER, address, req, transporter);
+ }
+
+ private static AskResponse reliableAsk(ServerType t, String rootPath, String handlerPath, String address, PowerSerializable req, Transporter transporter) throws Exception {
+ final URL url = easyBuildUrl(t, rootPath, handlerPath, address);
+ final CompletionStage completionStage = transporter.ask(url, req, AskResponse.class);
+ return completionStage
+ .toCompletableFuture()
+ .get(RemoteConstant.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+
+ public static URL easyBuildUrl(ServerType serverType, String rootPath, String handlerPath, String address) {
+ HandlerLocation handlerLocation = new HandlerLocation()
+ .setRootPath(rootPath)
+ .setMethodPath(handlerPath);
+ return new URL()
+ .setServerType(serverType)
+ .setAddress(Address.fromIpv4(address))
+ .setLocation(handlerLocation);
+ }
+
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/container/OmsContainerFactory.java b/powerjob-worker/src/main/java/tech/powerjob/worker/container/OmsContainerFactory.java
index 6993af34..f857e43c 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/container/OmsContainerFactory.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/container/OmsContainerFactory.java
@@ -1,8 +1,5 @@
package tech.powerjob.worker.container;
-import akka.actor.ActorSelection;
-import akka.pattern.Patterns;
-import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.model.DeployedContainerInfo;
import tech.powerjob.common.request.ServerDeployContainerRequest;
import tech.powerjob.common.request.WorkerNeedDeployContainerRequest;
@@ -12,14 +9,14 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
+import tech.powerjob.worker.common.WorkerRuntime;
+import tech.powerjob.worker.common.utils.PowerFileUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import java.io.File;
import java.net.URL;
-import java.time.Duration;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.TimeUnit;
/**
* 容器工厂
@@ -30,25 +27,23 @@ import java.util.concurrent.TimeUnit;
@Slf4j
public class OmsContainerFactory {
- private static final String CONTAINER_DIR = System.getProperty("user.home") + "/powerjob/worker/container/";
+ private static final String CONTAINER_DIR = PowerFileUtils.workspace() + "/container/";
private static final Map CARGO = Maps.newConcurrentMap();
/**
* 获取容器
* @param containerId 容器ID
- * @param serverActor 当容器不存在且 serverActor 非空时,尝试从服务端重新拉取容器
+ * @param workerRuntime 当容器不存在且 serverActor 非空时,尝试从服务端重新拉取容器
* @return 容器示例,可能为 null
*/
- public static OmsContainer fetchContainer(Long containerId, ActorSelection serverActor) {
+ public static OmsContainer fetchContainer(Long containerId, WorkerRuntime workerRuntime) {
OmsContainer omsContainer = CARGO.get(containerId);
if (omsContainer != null) {
return omsContainer;
}
- if (serverActor == null) {
- return null;
- }
+ final String currentServerAddress = workerRuntime.getServerDiscoveryService().getCurrentServerAddress();
// 尝试从 server 加载
log.info("[OmsContainer-{}] can't find the container in factory, try to deploy from server.", containerId);
@@ -56,8 +51,7 @@ public class OmsContainerFactory {
try {
- CompletionStage askCS = Patterns.ask(serverActor, request, Duration.ofMillis(RemoteConstant.DEFAULT_TIMEOUT_MS));
- AskResponse askResponse = (AskResponse) askCS.toCompletableFuture().get(RemoteConstant.DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ AskResponse askResponse = TransportUtils.reliableQueryContainerInfo(request, currentServerAddress, workerRuntime.getTransporter());
if (askResponse.isSuccess()) {
ServerDeployContainerRequest deployRequest = askResponse.getData(ServerDeployContainerRequest.class);
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/container/OmsJarContainer.java b/powerjob-worker/src/main/java/tech/powerjob/worker/container/OmsJarContainer.java
index 2bd27648..8265ac83 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/container/OmsJarContainer.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/container/OmsJarContainer.java
@@ -38,7 +38,7 @@ public class OmsJarContainer implements OmsContainer {
private OhMyClassLoader containerClassLoader;
private ClassPathXmlApplicationContext container;
- private Map processorCache = Maps.newConcurrentMap();
+ private final Map processorCache = Maps.newConcurrentMap();
public OmsJarContainer(Long containerId, String name, String version, File localJarFile) {
this.containerId = containerId;
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/ProcessorBeanFactory.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/ProcessorBeanFactory.java
deleted file mode 100644
index d86cdfd7..00000000
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/ProcessorBeanFactory.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package tech.powerjob.worker.core;
-
-import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
-import com.google.common.collect.Maps;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-
-import java.util.Map;
-
-/**
- * 处理器工厂
- *
- * @author tjq
- * @since 2020/3/23
- */
-@Slf4j
-public class ProcessorBeanFactory {
-
- /**
- * key(用来防止不同jar包同名类的冲突) -> (className -> Processor)
- */
- private final Map> cache;
-
- private static final String LOCAL_KEY = "local";
-
- private static volatile ProcessorBeanFactory processorBeanFactory;
-
- public ProcessorBeanFactory() {
-
- // 初始化对象缓存
- cache = Maps.newConcurrentMap();
- Map className2Processor = Maps.newConcurrentMap();
- cache.put(LOCAL_KEY, className2Processor);
- }
-
- public BasicProcessor getLocalProcessor(String className) {
- return cache.get(LOCAL_KEY).computeIfAbsent(className, ignore -> {
- try {
-
- Class> clz = Class.forName(className);
- return (BasicProcessor) clz.getDeclaredConstructor().newInstance();
-
- }catch (Exception e) {
- log.warn("[ProcessorBeanFactory] load local Processor(className = {}) failed.", className, e);
- ExceptionUtils.rethrow(e);
- }
- return null;
- });
- }
-
- public static ProcessorBeanFactory getInstance() {
- if (processorBeanFactory != null) {
- return processorBeanFactory;
- }
- synchronized (ProcessorBeanFactory.class) {
- if (processorBeanFactory == null) {
- processorBeanFactory = new ProcessorBeanFactory();
- }
- }
- return processorBeanFactory;
- }
-}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/ProcessorInfo.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/ProcessorInfo.java
deleted file mode 100644
index a971911e..00000000
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/ProcessorInfo.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package tech.powerjob.worker.core.processor;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
-
-/**
- * @author Echo009
- * @since 2022/9/23
- */
-@RequiredArgsConstructor
-@Getter
-public class ProcessorInfo {
-
- private final BasicProcessor basicProcessor;
-
- private final ClassLoader classLoader;
-
- public static ProcessorInfo of(BasicProcessor basicProcessor, ClassLoader classLoader) {
- return new ProcessorInfo(basicProcessor, classLoader);
- }
-}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/ProcessorLoader.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/ProcessorLoader.java
deleted file mode 100644
index 9256f337..00000000
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/ProcessorLoader.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package tech.powerjob.worker.core.processor;
-
-import akka.actor.ActorSelection;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import tech.powerjob.common.enums.ProcessorType;
-import tech.powerjob.common.exception.PowerJobException;
-import tech.powerjob.worker.common.WorkerRuntime;
-import tech.powerjob.worker.common.utils.AkkaUtils;
-import tech.powerjob.worker.common.utils.SpringUtils;
-import tech.powerjob.worker.container.OmsContainer;
-import tech.powerjob.worker.container.OmsContainerFactory;
-import tech.powerjob.worker.core.ProcessorBeanFactory;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author Echo009
- * @since 2022/9/19
- */
-@Slf4j
-public class ProcessorLoader {
-
-
- private static final Map CACHE;
-
-
- static {
- // init
- CACHE = new ConcurrentHashMap<>(128);
- }
-
- /**
- * 获取处理器
- * @param workerRuntime 运行时
- * @param processorType 处理器类型
- * @param processorInfo 处理器 id ,一般是全限定类名
- * @return processor
- */
- public static ProcessorInfo loadProcessor(WorkerRuntime workerRuntime, String processorType, String processorInfo) {
- ProcessorInfo processorInfoHolder = null;
- ProcessorType type = ProcessorType.valueOf(processorType);
-
- switch (type) {
- case BUILT_IN:
- // 先从缓存中取
- processorInfoHolder = CACHE.computeIfAbsent(processorInfo, ignore -> {
- // 先使用 Spring 加载
- if (SpringUtils.supportSpringBean()) {
- try {
- return ProcessorInfo.of(SpringUtils.getBean(processorInfo),workerRuntime.getClass().getClassLoader());
- } catch (Exception e) {
- log.warn("[ProcessorLoader] no spring bean of processor(className={}), reason is {}.", processorInfo, ExceptionUtils.getMessage(e));
- }
- }
- // 反射加载
- return ProcessorInfo.of(ProcessorBeanFactory.getInstance().getLocalProcessor(processorInfo),workerRuntime.getClass().getClassLoader());
- });
- break;
- case EXTERNAL:
- String[] split = processorInfo.split("#");
- log.info("[ProcessorLoader] try to load processor({}) in container({})", split[1], split[0]);
-
- String serverPath = AkkaUtils.getServerActorPath(workerRuntime.getServerDiscoveryService().getCurrentServerAddress());
- ActorSelection actorSelection = workerRuntime.getActorSystem().actorSelection(serverPath);
- OmsContainer omsContainer = OmsContainerFactory.fetchContainer(Long.valueOf(split[0]), actorSelection);
- if (omsContainer != null) {
- processorInfoHolder = ProcessorInfo.of(omsContainer.getProcessor(split[1]), omsContainer.getContainerClassLoader());
- } else {
- log.warn("[ProcessorLoader] load container failed. processor info : {}", processorInfo);
- }
- break;
- default:
- log.warn("[ProcessorLoader] unknown processor type: {}.", processorType);
- throw new PowerJobException("unknown processor type of " + processorType);
- }
-
- if (processorInfoHolder == null) {
- log.warn("[ProcessorLoader] fetch Processor(type={},info={}) failed.", processorType, processorInfo);
- throw new PowerJobException("fetch Processor failed, please check your processorType and processorInfo config");
- }
-
- return processorInfoHolder;
-
- }
-
-
-}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/runnable/HeavyProcessorRunnable.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/runnable/HeavyProcessorRunnable.java
index d42ed61b..af28b72d 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/runnable/HeavyProcessorRunnable.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/runnable/HeavyProcessorRunnable.java
@@ -1,13 +1,16 @@
package tech.powerjob.worker.core.processor.runnable;
-import akka.actor.ActorSelection;
+import com.google.common.base.Stopwatch;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
import tech.powerjob.common.enums.ExecuteType;
-import tech.powerjob.worker.common.WorkerRuntime;
+import tech.powerjob.common.serialize.SerializerUtils;
import tech.powerjob.worker.common.ThreadLocalStore;
+import tech.powerjob.worker.common.WorkerRuntime;
import tech.powerjob.worker.common.constants.TaskConstant;
import tech.powerjob.worker.common.constants.TaskStatus;
-import tech.powerjob.worker.common.utils.AkkaUtils;
-import tech.powerjob.common.serialize.SerializerUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.common.utils.WorkflowContextUtils;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
@@ -16,15 +19,11 @@ import tech.powerjob.worker.core.processor.WorkflowContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
import tech.powerjob.worker.core.processor.sdk.BroadcastProcessor;
import tech.powerjob.worker.core.processor.sdk.MapReduceProcessor;
+import tech.powerjob.worker.extension.processor.ProcessorBean;
import tech.powerjob.worker.log.OmsLogger;
import tech.powerjob.worker.persistence.TaskDO;
import tech.powerjob.worker.pojo.model.InstanceInfo;
import tech.powerjob.worker.pojo.request.ProcessorReportTaskStatusReq;
-import com.google.common.base.Stopwatch;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.apache.commons.lang3.StringUtils;
import java.util.Collections;
import java.util.List;
@@ -45,14 +44,10 @@ public class HeavyProcessorRunnable implements Runnable {
private final InstanceInfo instanceInfo;
- private final ActorSelection taskTrackerActor;
+ private final String taskTrackerAddress;
private final TaskDO task;
- private final BasicProcessor processor;
+ private final ProcessorBean processorBean;
private final OmsLogger omsLogger;
- /**
- * 类加载器
- */
- private final ClassLoader classLoader;
/**
* 重试队列,ProcessorTracker 将会定期重新上报处理结果
*/
@@ -61,6 +56,8 @@ public class HeavyProcessorRunnable implements Runnable {
public void innerRun() throws InterruptedException {
+ final BasicProcessor processor = processorBean.getProcessor();
+
String taskId = task.getTaskId();
Long instanceId = task.getInstanceId();
@@ -107,8 +104,11 @@ public class HeavyProcessorRunnable implements Runnable {
private TaskContext constructTaskContext() {
TaskContext taskContext = new TaskContext();
- BeanUtils.copyProperties(task, taskContext);
taskContext.setJobId(instanceInfo.getJobId());
+ taskContext.setInstanceId(task.getInstanceId());
+ taskContext.setSubInstanceId(task.getSubInstanceId());
+ taskContext.setTaskId(task.getTaskId());
+ taskContext.setTaskName(task.getTaskName());
taskContext.setMaxRetryTimes(instanceInfo.getTaskRetryNum());
taskContext.setCurrentRetryTimes(task.getFailedCnt());
taskContext.setJobParams(instanceInfo.getJobParams());
@@ -122,7 +122,7 @@ public class HeavyProcessorRunnable implements Runnable {
}
private WorkflowContext constructWorkflowContext() {
- return new WorkflowContext(instanceInfo.getWfInstanceId(),instanceInfo.getInstanceParams());
+ return new WorkflowContext(instanceInfo.getWfInstanceId(), instanceInfo.getInstanceParams());
}
/**
@@ -131,6 +131,7 @@ public class HeavyProcessorRunnable implements Runnable {
* MAP_REDUCE => {@link MapReduceProcessor#reduce}
*/
private void handleLastTask(String taskId, Long instanceId, TaskContext taskContext, ExecuteType executeType) {
+ final BasicProcessor processor = processorBean.getProcessor();
ProcessResult processResult;
Stopwatch stopwatch = Stopwatch.createStarted();
log.debug("[ProcessorRunnable-{}] the last task(taskId={}) start to process.", instanceId, taskId);
@@ -175,6 +176,7 @@ public class HeavyProcessorRunnable implements Runnable {
* 即执行 {@link BroadcastProcessor#preProcess},并通知 TaskerTracker 创建广播子任务
*/
private void handleBroadcastRootTask(Long instanceId, TaskContext taskContext) {
+ BasicProcessor processor = processorBean.getProcessor();
ProcessResult processResult;
// 广播执行的第一个 task 只执行 preProcess 部分
if (processor instanceof BroadcastProcessor) {
@@ -222,14 +224,14 @@ public class HeavyProcessorRunnable implements Runnable {
// 最终结束状态要求可靠发送
if (TaskStatus.FINISHED_STATUS.contains(status.getValue())) {
- boolean success = AkkaUtils.reliableTransmit(taskTrackerActor, req);
+ boolean success = TransportUtils.reliablePtReportTask(req, taskTrackerAddress, workerRuntime);
if (!success) {
// 插入重试队列,等待重试
statusReportRetryQueue.add(req);
log.warn("[ProcessorRunnable-{}] report task(id={},status={},result={}) failed, will retry later", task.getInstanceId(), task.getTaskId(), status, result);
}
} else {
- taskTrackerActor.tell(req, null);
+ TransportUtils.ptReportTask(req, taskTrackerAddress, workerRuntime);
}
}
@@ -237,7 +239,7 @@ public class HeavyProcessorRunnable implements Runnable {
@SuppressWarnings("squid:S2142")
public void run() {
// 切换线程上下文类加载器(否则用的是 Worker 类加载器,不存在容器类,在序列化/反序列化时会报 ClassNotFoundException)
- Thread.currentThread().setContextClassLoader(classLoader);
+ Thread.currentThread().setContextClassLoader(processorBean.getClassLoader());
try {
innerRun();
} catch (InterruptedException ignore) {
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/sdk/MapProcessor.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/sdk/MapProcessor.java
index d8d8e752..1ec00177 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/sdk/MapProcessor.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/processor/sdk/MapProcessor.java
@@ -2,13 +2,12 @@ package tech.powerjob.worker.core.processor.sdk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.util.CollectionUtils;
-import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.exception.PowerJobCheckedException;
+import tech.powerjob.common.utils.CollectionUtils;
import tech.powerjob.worker.common.ThreadLocalStore;
import tech.powerjob.worker.common.WorkerRuntime;
import tech.powerjob.worker.common.constants.TaskConstant;
-import tech.powerjob.worker.common.utils.AkkaUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.persistence.TaskDO;
import tech.powerjob.worker.pojo.request.ProcessorMapTaskRequest;
@@ -55,8 +54,7 @@ public interface MapProcessor extends BasicProcessor {
ProcessorMapTaskRequest req = new ProcessorMapTaskRequest(task, taskList, taskName);
// 2. 可靠发送请求(任务不允许丢失,需要使用 ask 方法,失败抛异常)
- String akkaRemotePath = AkkaUtils.getAkkaWorkerPath(task.getAddress(), RemoteConstant.TASK_TRACKER_ACTOR_NAME);
- boolean requestSucceed = AkkaUtils.reliableTransmit(workerRuntime.getActorSystem().actorSelection(akkaRemotePath), req);
+ boolean requestSucceed = TransportUtils.reliableMapTask(req, task.getAddress(), workerRuntime);
if (requestSucceed) {
log.info("[Map-{}] map task[name={},num={}] successfully!", task.getInstanceId(), taskName, taskList.size());
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/manager/LightTaskTrackerManager.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/manager/LightTaskTrackerManager.java
index eef65f39..5ed0f60e 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/manager/LightTaskTrackerManager.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/manager/LightTaskTrackerManager.java
@@ -21,8 +21,11 @@ public class LightTaskTrackerManager {
return INSTANCE_ID_2_TASK_TRACKER.get(instanceId);
}
- public static LightTaskTracker removeTaskTracker(Long instanceId) {
- return INSTANCE_ID_2_TASK_TRACKER.remove(instanceId);
+ public static void removeTaskTracker(Long instanceId) {
+ // 忽略印度的 IDE 警告,这个判断非常有用!!!不加这个判断会导致:如果创建 TT(先执行 computeIfAbsent 正在将TT添加到 HashMap) 时报错,TT 主动调用 destroy 销毁(从 HashMap移除该 TT)时死锁
+ if (INSTANCE_ID_2_TASK_TRACKER.containsKey(instanceId)) {
+ INSTANCE_ID_2_TASK_TRACKER.remove(instanceId);
+ }
}
public static void atomicCreateTaskTracker(Long instanceId, Function creator) {
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/processor/ProcessorTracker.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/processor/ProcessorTracker.java
index f3a54543..7bc79f68 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/processor/ProcessorTracker.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/processor/ProcessorTracker.java
@@ -1,28 +1,23 @@
package tech.powerjob.worker.core.tracker.processor;
-import akka.actor.ActorSelection;
import com.google.common.collect.Queues;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.springframework.util.CollectionUtils;
-import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.enums.ExecuteType;
import tech.powerjob.common.enums.ProcessorType;
import tech.powerjob.common.enums.TimeExpressionType;
-import tech.powerjob.common.model.LogConfig;
-import tech.powerjob.common.serialize.JsonUtils;
+import tech.powerjob.common.utils.CollectionUtils;
import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.worker.common.WorkerRuntime;
import tech.powerjob.worker.common.constants.TaskStatus;
-import tech.powerjob.worker.common.utils.AkkaUtils;
-import tech.powerjob.worker.core.processor.ProcessorInfo;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.core.processor.runnable.HeavyProcessorRunnable;
-import tech.powerjob.worker.core.processor.ProcessorLoader;
import tech.powerjob.worker.core.tracker.manager.ProcessorTrackerManager;
+import tech.powerjob.worker.extension.processor.ProcessorBean;
+import tech.powerjob.worker.extension.processor.ProcessorDefinition;
import tech.powerjob.worker.log.OmsLogger;
import tech.powerjob.worker.log.OmsLoggerFactory;
-import tech.powerjob.worker.log.impl.OmsServerLogger;
import tech.powerjob.worker.persistence.TaskDO;
import tech.powerjob.worker.pojo.model.InstanceInfo;
import tech.powerjob.worker.pojo.request.ProcessorReportTaskStatusReq;
@@ -56,7 +51,7 @@ public class ProcessorTracker {
*/
private Long instanceId;
- private ProcessorInfo processorInfo;
+ private ProcessorBean processorBean;
/**
* 在线日志
*/
@@ -76,8 +71,6 @@ public class ProcessorTracker {
private String taskTrackerAddress;
- private ActorSelection taskTrackerActorRef;
-
private ThreadPoolExecutor threadPool;
private ScheduledExecutorService timingPool;
@@ -107,9 +100,6 @@ public class ProcessorTracker {
this.instanceId = request.getInstanceInfo().getInstanceId();
this.taskTrackerAddress = request.getTaskTrackerAddress();
- String akkaRemotePath = AkkaUtils.getAkkaWorkerPath(taskTrackerAddress, RemoteConstant.TASK_TRACKER_ACTOR_NAME);
- this.taskTrackerActorRef = workerRuntime.getActorSystem().actorSelection(akkaRemotePath);
-
this.omsLogger = OmsLoggerFactory.build(instanceId, request.getLogConfig(), workerRuntime);
this.statusReportRetryQueue = Queues.newLinkedBlockingQueue();
this.lastIdleTime = -1L;
@@ -120,7 +110,7 @@ public class ProcessorTracker {
// 初始化定时任务
initTimingJob();
// 初始化 Processor
- processorInfo = ProcessorLoader.loadProcessor(workerRuntime, instanceInfo.getProcessorType(), instanceInfo.getProcessorInfo());
+ processorBean = workerRuntime.getProcessorLoader().load(new ProcessorDefinition().setProcessorType(instanceInfo.getProcessorType()).setProcessorInfo(instanceInfo.getProcessorInfo()));
log.info("[ProcessorTracker-{}] ProcessorTracker was successfully created!", instanceId);
} catch (Throwable t) {
log.warn("[ProcessorTracker-{}] create ProcessorTracker failed, all tasks submitted here will fail.", instanceId, t);
@@ -152,7 +142,7 @@ public class ProcessorTracker {
.setResult(lethalReason)
.setReportTime(System.currentTimeMillis());
- taskTrackerActorRef.tell(report, null);
+ TransportUtils.ptReportTask(report, taskTrackerAddress, workerRuntime);
return;
}
@@ -161,8 +151,7 @@ public class ProcessorTracker {
newTask.setInstanceId(instanceInfo.getInstanceId());
newTask.setAddress(taskTrackerAddress);
- ClassLoader classLoader = processorInfo.getClassLoader();
- HeavyProcessorRunnable heavyProcessorRunnable = new HeavyProcessorRunnable(instanceInfo, taskTrackerActorRef, newTask, processorInfo.getBasicProcessor(), omsLogger, classLoader, statusReportRetryQueue, workerRuntime);
+ HeavyProcessorRunnable heavyProcessorRunnable = new HeavyProcessorRunnable(instanceInfo, taskTrackerAddress, newTask, processorBean, omsLogger, statusReportRetryQueue, workerRuntime);
try {
threadPool.submit(heavyProcessorRunnable);
success = true;
@@ -182,7 +171,7 @@ public class ProcessorTracker {
reportReq.setStatus(TaskStatus.WORKER_RECEIVED.getValue());
reportReq.setReportTime(System.currentTimeMillis());
- taskTrackerActorRef.tell(reportReq, null);
+ TransportUtils.ptReportTask(reportReq, taskTrackerAddress, workerRuntime);
log.debug("[ProcessorTracker-{}] submit task(taskId={}, taskName={}) success, current queue size: {}.",
instanceId, newTask.getTaskId(), newTask.getTaskName(), threadPool.getQueue().size());
@@ -203,7 +192,6 @@ public class ProcessorTracker {
});
// 2. 去除顶层引用,送入GC世界
- taskTrackerActorRef = null;
statusReportRetryQueue.clear();
ProcessorTrackerManager.removeProcessorTracker(instanceId);
@@ -281,7 +269,7 @@ public class ProcessorTracker {
// 不可靠通知,如果该请求失败,则整个任务处理集群缺失一个 ProcessorTracker,影响可接受
ProcessorTrackerStatusReportReq statusReportReq = ProcessorTrackerStatusReportReq.buildIdleReport(instanceId);
statusReportReq.setAddress(workerRuntime.getWorkerAddress());
- taskTrackerActorRef.tell(statusReportReq, null);
+ TransportUtils.ptReportSelfStatus(statusReportReq, taskTrackerAddress, workerRuntime);
destroy();
return;
}
@@ -293,7 +281,7 @@ public class ProcessorTracker {
ProcessorReportTaskStatusReq req = statusReportRetryQueue.poll();
if (req != null) {
req.setReportTime(System.currentTimeMillis());
- if (!AkkaUtils.reliableTransmit(taskTrackerActorRef, req)) {
+ if (!TransportUtils.reliablePtReportTask(req, taskTrackerAddress, workerRuntime)) {
statusReportRetryQueue.add(req);
log.warn("[ProcessorRunnable-{}] retry report finished task status failed: {}", instanceId, req);
return;
@@ -305,7 +293,7 @@ public class ProcessorTracker {
long waitingNum = threadPool.getQueue().size();
ProcessorTrackerStatusReportReq statusReportReq = ProcessorTrackerStatusReportReq.buildLoadReport(instanceId, waitingNum);
statusReportReq.setAddress(workerRuntime.getWorkerAddress());
- taskTrackerActorRef.tell(statusReportReq, null);
+ TransportUtils.ptReportSelfStatus(statusReportReq, taskTrackerAddress, workerRuntime);
log.debug("[ProcessorTracker-{}] send heartbeat to TaskTracker, current waiting task num is {}.", instanceId, waitingNum);
}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/TaskTracker.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/TaskTracker.java
index f3546db1..a1edebc4 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/TaskTracker.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/TaskTracker.java
@@ -1,24 +1,17 @@
package tech.powerjob.worker.core.tracker.task;
-import akka.actor.ActorSelection;
-import akka.pattern.Patterns;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
import tech.powerjob.common.enums.InstanceStatus;
import tech.powerjob.common.model.InstanceDetail;
import tech.powerjob.common.request.ServerScheduleJobReq;
import tech.powerjob.common.request.TaskTrackerReportInstanceStatusReq;
-import tech.powerjob.common.response.AskResponse;
import tech.powerjob.worker.common.WorkerRuntime;
-import tech.powerjob.worker.common.utils.AkkaUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.pojo.model.InstanceInfo;
-import java.time.Duration;
import java.util.Collections;
import java.util.Map;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -67,7 +60,20 @@ public abstract class TaskTracker {
this.instanceId = req.getInstanceId();
this.instanceInfo = new InstanceInfo();
- BeanUtils.copyProperties(req, instanceInfo);
+
+ // PowerJob 值拷贝场景不多,引入三方值拷贝类库可能引入类冲突等问题,综合评估手写 ROI 最高
+ instanceInfo.setJobId(req.getJobId());
+ instanceInfo.setInstanceId(req.getInstanceId());
+ instanceInfo.setWfInstanceId(req.getWfInstanceId());
+ instanceInfo.setExecuteType(req.getExecuteType());
+ instanceInfo.setProcessorType(req.getProcessorType());
+ instanceInfo.setProcessorInfo(req.getProcessorInfo());
+ instanceInfo.setJobParams(req.getJobParams());
+ instanceInfo.setInstanceParams(req.getInstanceParams());
+ instanceInfo.setThreadConcurrency(req.getThreadConcurrency());
+ instanceInfo.setTaskRetryNum(req.getTaskRetryNum());
+ instanceInfo.setLogConfig(req.getLogConfig());
+
// 特殊处理超时时间
if (instanceInfo.getInstanceTimeoutMS() <= 0) {
instanceInfo.setInstanceTimeoutMS(Integer.MAX_VALUE);
@@ -100,25 +106,27 @@ public abstract class TaskTracker {
log.warn("[TaskTracker-{}] create TaskTracker from request({}) failed.", req.getInstanceId(), req, e);
// 直接发送失败请求
TaskTrackerReportInstanceStatusReq response = new TaskTrackerReportInstanceStatusReq();
- BeanUtils.copyProperties(req, response);
+
+ response.setAppId(workerRuntime.getAppId());
+ response.setJobId(req.getJobId());
+ response.setInstanceId(req.getInstanceId());
+ response.setWfInstanceId(req.getWfInstanceId());
+
response.setInstanceStatus(InstanceStatus.FAILED.getV());
response.setResult(String.format("init TaskTracker failed, reason: %s", e.toString()));
response.setReportTime(System.currentTimeMillis());
response.setStartTime(System.currentTimeMillis());
response.setSourceAddress(workerRuntime.getWorkerAddress());
- String serverPath = AkkaUtils.getServerActorPath(workerRuntime.getServerDiscoveryService().getCurrentServerAddress());
- ActorSelection serverActor = workerRuntime.getActorSystem().actorSelection(serverPath);
- serverActor.tell(response, null);
+ TransportUtils.ttReportInstanceStatus(response, workerRuntime.getServerDiscoveryService().getCurrentServerAddress(), workerRuntime.getTransporter());
}
- protected void reportFinalStatusThenDestroy(ActorSelection serverActor, TaskTrackerReportInstanceStatusReq reportInstanceStatusReq) {
+ protected void reportFinalStatusThenDestroy(WorkerRuntime workerRuntime, TaskTrackerReportInstanceStatusReq reportInstanceStatusReq) {
+ String currentServerAddress = workerRuntime.getServerDiscoveryService().getCurrentServerAddress();
// 最终状态需要可靠上报
- CompletionStage ask = Patterns.ask(serverActor, reportInstanceStatusReq, Duration.ofSeconds(15));
boolean serverAccepted = false;
try {
- AskResponse askResponse = (AskResponse) ask.toCompletableFuture().get(15, TimeUnit.SECONDS);
- serverAccepted = askResponse.isSuccess();
+ serverAccepted = TransportUtils.reliableTtReportInstanceStatus(reportInstanceStatusReq, currentServerAddress, workerRuntime.getTransporter());
} catch (Exception e) {
log.warn("[TaskTracker-{}] report finished status failed, req={}.", instanceId, reportInstanceStatusReq, e);
}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/CommonTaskTracker.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/CommonTaskTracker.java
index ef9c2e0a..8853f310 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/CommonTaskTracker.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/CommonTaskTracker.java
@@ -1,12 +1,9 @@
package tech.powerjob.worker.core.tracker.task.heavy;
-import akka.actor.ActorSelection;
-import akka.pattern.Patterns;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.CollectionUtils;
import tech.powerjob.common.PowerJobDKey;
import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.SystemInstanceResult;
@@ -16,17 +13,15 @@ import tech.powerjob.common.exception.PowerJobException;
import tech.powerjob.common.model.InstanceDetail;
import tech.powerjob.common.request.ServerScheduleJobReq;
import tech.powerjob.common.request.TaskTrackerReportInstanceStatusReq;
-import tech.powerjob.common.response.AskResponse;
+import tech.powerjob.common.utils.CollectionUtils;
import tech.powerjob.worker.common.WorkerRuntime;
import tech.powerjob.worker.common.constants.TaskConstant;
import tech.powerjob.worker.common.constants.TaskStatus;
-import tech.powerjob.worker.common.utils.AkkaUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.persistence.TaskDO;
-import java.time.Duration;
import java.util.List;
import java.util.Optional;
-import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@@ -178,7 +173,6 @@ public class CommonTaskTracker extends HeavyTaskTracker {
finished.set(true);
List allTask = taskPersistenceService.getAllTask(instanceId, instanceId);
if (CollectionUtils.isEmpty(allTask) || allTask.size() > 1) {
- success = false;
result = SystemInstanceResult.UNKNOWN_BUG;
log.warn("[TaskTracker-{}] there must have some bug in TaskTracker.", instanceId);
} else {
@@ -229,22 +223,19 @@ public class CommonTaskTracker extends HeavyTaskTracker {
result = SystemInstanceResult.INSTANCE_EXECUTE_TIMEOUT;
}
- String serverPath = AkkaUtils.getServerActorPath(workerRuntime.getServerDiscoveryService().getCurrentServerAddress());
- ActorSelection serverActor = workerRuntime.getActorSystem().actorSelection(serverPath);
-
// 4. 执行完毕,报告服务器
if (finished.get()) {
req.setResult(result);
// 上报追加的工作流上下文信息
req.setAppendedWfContext(appendedWfContext);
req.setInstanceStatus(success ? InstanceStatus.SUCCEED.getV() : InstanceStatus.FAILED.getV());
- reportFinalStatusThenDestroy(serverActor,req);
+ reportFinalStatusThenDestroy(workerRuntime, req);
return;
}
// 5. 未完成,上报状态
req.setInstanceStatus(InstanceStatus.RUNNING.getV());
- serverActor.tell(req, null);
+ TransportUtils.ttReportInstanceStatus(req, workerRuntime.getServerDiscoveryService().getCurrentServerAddress(), workerRuntime.getTransporter());
// 6.1 定期检查 -> 重试派发后未确认的任务
long currentMS = System.currentTimeMillis();
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/FrequentTaskTracker.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/FrequentTaskTracker.java
index f46ea3de..891ce021 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/FrequentTaskTracker.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/FrequentTaskTracker.java
@@ -1,6 +1,5 @@
package tech.powerjob.worker.core.tracker.task.heavy;
-import akka.actor.ActorSelection;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
@@ -9,7 +8,6 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.BeanUtils;
import tech.powerjob.common.enums.ExecuteType;
import tech.powerjob.common.enums.InstanceStatus;
import tech.powerjob.common.enums.TimeExpressionType;
@@ -22,8 +20,8 @@ import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.worker.common.WorkerRuntime;
import tech.powerjob.worker.common.constants.TaskConstant;
import tech.powerjob.worker.common.constants.TaskStatus;
-import tech.powerjob.worker.common.utils.AkkaUtils;
import tech.powerjob.worker.common.utils.LRUCache;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.persistence.TaskDO;
import java.util.*;
@@ -136,10 +134,14 @@ public class FrequentTaskTracker extends HeavyTaskTracker {
List history = Lists.newLinkedList();
recentSubInstanceInfo.forEach((subId, subInstanceInfo) -> {
InstanceDetail.SubInstanceDetail subDetail = new InstanceDetail.SubInstanceDetail();
- BeanUtils.copyProperties(subInstanceInfo, subDetail);
+
+ subDetail.setSubInstanceId(subId);
+ subDetail.setStartTime(subInstanceInfo.getStartTime());
+ subDetail.setFinishedTime(subInstanceInfo.getFinishedTime());
+ subDetail.setResult(subInstanceInfo.getResult());
+
InstanceStatus status = InstanceStatus.of(subInstanceInfo.status);
subDetail.setStatus(status.getV());
- subDetail.setSubInstanceId(subId);
history.add(subDetail);
});
@@ -358,13 +360,8 @@ public class FrequentTaskTracker extends HeavyTaskTracker {
log.warn("[FQTaskTracker-{}] report alert req,time:{}", instanceId, req.getReportTime());
}
- String serverPath = AkkaUtils.getServerActorPath(currentServerAddress);
- if (StringUtils.isEmpty(serverPath)) {
- return;
- }
// 非可靠通知,Server挂掉后任务的kill工作交由其他线程去做
- ActorSelection serverActor = workerRuntime.getActorSystem().actorSelection(serverPath);
- serverActor.tell(req, null);
+ TransportUtils.ttReportInstanceStatus(req, currentServerAddress, workerRuntime.getTransporter());
}
/**
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/HeavyTaskTracker.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/HeavyTaskTracker.java
index ab459392..4f75e0ab 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/HeavyTaskTracker.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/heavy/HeavyTaskTracker.java
@@ -1,24 +1,28 @@
package tech.powerjob.worker.core.tracker.task.heavy;
-import akka.actor.ActorSelection;
import com.fasterxml.jackson.core.type.TypeReference;
+import com.google.common.base.Stopwatch;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
-import tech.powerjob.common.enums.ExecuteType;
-import tech.powerjob.common.enums.InstanceStatus;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
import tech.powerjob.common.RemoteConstant;
+import tech.powerjob.common.enums.ExecuteType;
import tech.powerjob.common.enums.TimeExpressionType;
-import tech.powerjob.common.model.InstanceDetail;
import tech.powerjob.common.request.ServerScheduleJobReq;
-import tech.powerjob.common.request.TaskTrackerReportInstanceStatusReq;
import tech.powerjob.common.request.WorkerQueryExecutorClusterReq;
import tech.powerjob.common.response.AskResponse;
-import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.common.serialize.JsonUtils;
+import tech.powerjob.common.utils.CollectionUtils;
+import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.common.utils.SegmentLock;
import tech.powerjob.worker.common.WorkerRuntime;
import tech.powerjob.worker.common.constants.TaskConstant;
import tech.powerjob.worker.common.constants.TaskStatus;
-import tech.powerjob.worker.common.utils.AkkaUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.common.utils.WorkflowContextUtils;
import tech.powerjob.worker.core.ha.ProcessorTrackerStatusHolder;
import tech.powerjob.worker.core.tracker.manager.HeavyTaskTrackerManager;
@@ -28,19 +32,8 @@ import tech.powerjob.worker.persistence.TaskPersistenceService;
import tech.powerjob.worker.pojo.request.ProcessorTrackerStatusReportReq;
import tech.powerjob.worker.pojo.request.TaskTrackerStartTaskReq;
import tech.powerjob.worker.pojo.request.TaskTrackerStopInstanceReq;
-import com.google.common.base.Stopwatch;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
import javax.annotation.Nullable;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -365,11 +358,9 @@ public abstract class HeavyTaskTracker extends TaskTracker {
// 1. 通知 ProcessorTracker 释放资源
TaskTrackerStopInstanceReq stopRequest = new TaskTrackerStopInstanceReq();
stopRequest.setInstanceId(instanceId);
- ptStatusHolder.getAllProcessorTrackers().forEach(ptIP -> {
- String ptPath = AkkaUtils.getAkkaWorkerPath(ptIP, RemoteConstant.PROCESSOR_TRACKER_ACTOR_NAME);
- ActorSelection ptActor = workerRuntime.getActorSystem().actorSelection(ptPath);
+ ptStatusHolder.getAllProcessorTrackers().forEach(ptAddress -> {
// 不可靠通知,ProcessorTracker 也可以靠自己的定时任务/问询等方式关闭
- ptActor.tell(stopRequest, null);
+ TransportUtils.ttStopPtInstance(stopRequest, ptAddress, workerRuntime.getTransporter());
});
// 2. 删除所有数据库数据
@@ -425,9 +416,7 @@ public abstract class HeavyTaskTracker extends TaskTracker {
// 4. 任务派发
TaskTrackerStartTaskReq startTaskReq = new TaskTrackerStartTaskReq(instanceInfo, task, workerRuntime.getWorkerAddress());
- String ptActorPath = AkkaUtils.getAkkaWorkerPath(processorTrackerAddress, RemoteConstant.PROCESSOR_TRACKER_ACTOR_NAME);
- ActorSelection ptActor = workerRuntime.getActorSystem().actorSelection(ptActorPath);
- ptActor.tell(startTaskReq, null);
+ TransportUtils.ttStartPtTask(startTaskReq, processorTrackerAddress, workerRuntime.getTransporter());
log.debug("[TaskTracker-{}] dispatch task(taskId={},taskName={}) successfully.", instanceId, task.getTaskId(), task.getTaskName());
}
@@ -524,22 +513,24 @@ public abstract class HeavyTaskTracker extends TaskTracker {
return;
}
- String serverPath = AkkaUtils.getServerActorPath(workerRuntime.getServerDiscoveryService().getCurrentServerAddress());
- if (StringUtils.isEmpty(serverPath)) {
+ final String currentServerAddress = workerRuntime.getServerDiscoveryService().getCurrentServerAddress();
+ if (StringUtils.isEmpty(currentServerAddress)) {
log.warn("[TaskTracker-{}] no server available, won't start worker detective!", instanceId);
return;
}
- WorkerQueryExecutorClusterReq req = new WorkerQueryExecutorClusterReq(workerRuntime.getAppId(), instanceInfo.getJobId());
- AskResponse response = AkkaUtils.easyAsk(workerRuntime.getActorSystem().actorSelection(serverPath), req);
- if (!response.isSuccess()) {
- log.warn("[TaskTracker-{}] detective failed due to ask failed, message is {}", instanceId, response.getMessage());
- return;
- }
+
try {
+ WorkerQueryExecutorClusterReq req = new WorkerQueryExecutorClusterReq(workerRuntime.getAppId(), instanceInfo.getJobId());
+ AskResponse response = TransportUtils.reliableQueryJobCluster(req, currentServerAddress, workerRuntime.getTransporter());
+ if (!response.isSuccess()) {
+ log.warn("[TaskTracker-{}] detective failed due to ask failed, message is {}", instanceId, response.getMessage());
+ return;
+ }
+
List workerList = JsonUtils.parseObject(response.getData(), new TypeReference>() {});
ptStatusHolder.register(workerList);
} catch (Exception e) {
- log.warn("[TaskTracker-{}] detective failed!", instanceId, e);
+ log.warn("[TaskTracker-{}] detective failed, currentServer: {}", instanceId, currentServerAddress, e);
}
}
}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/light/LightTaskTracker.java b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/light/LightTaskTracker.java
index d46fc5dd..66da591b 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/light/LightTaskTracker.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/core/tracker/task/light/LightTaskTracker.java
@@ -1,6 +1,5 @@
package tech.powerjob.worker.core.tracker.task.light;
-import akka.actor.ActorSelection;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
@@ -13,10 +12,12 @@ import tech.powerjob.common.request.TaskTrackerReportInstanceStatusReq;
import tech.powerjob.worker.common.WorkerRuntime;
import tech.powerjob.worker.common.constants.TaskConstant;
import tech.powerjob.worker.common.constants.TaskStatus;
-import tech.powerjob.worker.common.utils.AkkaUtils;
+import tech.powerjob.worker.common.utils.TransportUtils;
import tech.powerjob.worker.core.processor.*;
import tech.powerjob.worker.core.tracker.manager.LightTaskTrackerManager;
import tech.powerjob.worker.core.tracker.task.TaskTracker;
+import tech.powerjob.worker.extension.processor.ProcessorBean;
+import tech.powerjob.worker.extension.processor.ProcessorDefinition;
import tech.powerjob.worker.log.OmsLoggerFactory;
import java.util.concurrent.Future;
@@ -50,7 +51,7 @@ public class LightTaskTracker extends TaskTracker {
/**
* 处理器信息
*/
- private final ProcessorInfo processorInfo;
+ private final ProcessorBean processorBean;
/**
* 上下文
*/
@@ -86,7 +87,7 @@ public class LightTaskTracker extends TaskTracker {
// 等待处理
status = TaskStatus.WORKER_RECEIVED;
// 加载 Processor
- processorInfo = ProcessorLoader.loadProcessor(workerRuntime, req.getProcessorType(), req.getProcessorInfo());
+ processorBean = workerRuntime.getProcessorLoader().load(new ProcessorDefinition().setProcessorType(req.getProcessorType()).setProcessorInfo(req.getProcessorInfo()));
executeThread = new AtomicReference<>();
long delay = Integer.parseInt(System.getProperty(PowerJobDKey.WORKER_STATUS_CHECK_PERIOD, "15")) * 1000L;
// 初始延迟加入随机值,避免在高并发场景下所有请求集中在一个时间段
@@ -107,7 +108,7 @@ public class LightTaskTracker extends TaskTracker {
// 提交任务到线程池
processFuture = workerRuntime.getExecutorManager().getLightweightTaskExecutorService().submit(this::processTask);
} catch (Exception e) {
- log.warn("[TaskTracker-{}] fail to create TaskTracker for req:{} ", instanceId, req);
+ log.error("[TaskTracker-{}] fail to create TaskTracker for req:{} ", instanceId, req);
destroy();
throw e;
}
@@ -200,14 +201,14 @@ public class LightTaskTracker extends TaskTracker {
// 开始执行时,提交任务判断是否超时
ProcessResult res = null;
do {
- Thread.currentThread().setContextClassLoader(processorInfo.getClassLoader());
+ Thread.currentThread().setContextClassLoader(processorBean.getClassLoader());
if (res != null && !res.isSuccess()) {
// 重试
taskContext.setCurrentRetryTimes(taskContext.getCurrentRetryTimes() + 1);
log.warn("[TaskTracker-{}] process failed, TaskTracker will have a retry,current retryTimes : {}", instanceId, taskContext.getCurrentRetryTimes());
}
try {
- res = processorInfo.getBasicProcessor().process(taskContext);
+ res = processorBean.getProcessor().process(taskContext);
} catch (InterruptedException e) {
log.warn("[TaskTracker-{}] task has been interrupted !", instanceId, e);
Thread.currentThread().interrupt();
@@ -249,8 +250,6 @@ public class LightTaskTracker extends TaskTracker {
log.info("[TaskTracker-{}] has been destroyed,final status is {},needn't to report status!", instanceId, status);
return;
}
- String serverPath = AkkaUtils.getServerActorPath(workerRuntime.getServerDiscoveryService().getCurrentServerAddress());
- ActorSelection serverActor = workerRuntime.getActorSystem().actorSelection(serverPath);
TaskTrackerReportInstanceStatusReq reportInstanceStatusReq = new TaskTrackerReportInstanceStatusReq();
reportInstanceStatusReq.setAppId(workerRuntime.getAppId());
reportInstanceStatusReq.setJobId(instanceInfo.getJobId());
@@ -303,13 +302,13 @@ public class LightTaskTracker extends TaskTracker {
reportInstanceStatusReq.setEndTime(taskEndTime);
// 微操一下,上报最终状态时重新设置下时间,并且增加一小段偏移,保证在并发上报运行中状态以及最终状态时,最终状态的上报时间晚于运行中的状态
reportInstanceStatusReq.setReportTime(System.currentTimeMillis() + 1);
- reportFinalStatusThenDestroy(serverActor, reportInstanceStatusReq);
+ reportFinalStatusThenDestroy(workerRuntime, reportInstanceStatusReq);
return;
}
// 未完成的任务,只需要上报状态
reportInstanceStatusReq.setInstanceStatus(InstanceStatus.RUNNING.getV());
log.info("[TaskTracker-{}] report status({}) success,real status is {}", instanceId, reportInstanceStatusReq, status);
- serverActor.tell(reportInstanceStatusReq, null);
+ TransportUtils.ttReportInstanceStatus(reportInstanceStatusReq, workerRuntime.getServerDiscoveryService().getCurrentServerAddress(), workerRuntime.getTransporter());
}
private void timeoutCheck() {
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorBean.java b/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorBean.java
new file mode 100644
index 00000000..c7238f33
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorBean.java
@@ -0,0 +1,28 @@
+package tech.powerjob.worker.extension.processor;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
+
+/**
+ * 处理器对象
+ *
+ * @author Echo009
+ * @since 2022/9/23
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+public class ProcessorBean {
+
+ /**
+ * 真正用来执行逻辑的处理器对象
+ */
+ private transient BasicProcessor processor;
+ /**
+ * 加载该处理器对象的 classLoader,可空,空则使用 {@link Object#getClass()#getClassLoader() 代替}
+ */
+ private transient ClassLoader classLoader;
+
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorDefinition.java b/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorDefinition.java
new file mode 100644
index 00000000..aa89ca7e
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorDefinition.java
@@ -0,0 +1,49 @@
+package tech.powerjob.worker.extension.processor;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * 处理器定义
+ * 对外暴露的对象尽量不要直接使用构造器等不方便后续扩展的 API,Getter & Setter 保兼容
+ *
+ * @author Echo009
+ * @since 2023/1/17
+ */
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class ProcessorDefinition implements Serializable {
+
+ /**
+ * 后台配置的处理器类型
+ */
+ private String processorType;
+ /**
+ * 后台配置的处理器信息
+ */
+ private String processorInfo;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ProcessorDefinition that = (ProcessorDefinition) o;
+ return Objects.equals(processorType, that.processorType) && Objects.equals(processorInfo, that.processorInfo);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(processorType, processorInfo);
+ }
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorFactory.java b/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorFactory.java
new file mode 100644
index 00000000..67596aab
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/extension/processor/ProcessorFactory.java
@@ -0,0 +1,31 @@
+package tech.powerjob.worker.extension.processor;
+
+import tech.powerjob.common.enums.ProcessorType;
+
+import java.util.Set;
+
+/**
+ * 处理器工厂
+ * 考虑到当前是一个百花齐放的生态,各种 IOC 框架层出不穷。PowerJob 决定在 4.3.0 剥离对 Spring 的强依赖,并允许开发者自定义 Bean 的初始化逻辑
+ * 不知道怎么用的话,可以看看官方提供的 3 个默认实现,比如对接第三方 IOC 框架就类似于 BuiltInSpringProcessorFactory
+ *
+ * @author tjq
+ * @since 2023/1/17
+ */
+public interface ProcessorFactory {
+
+ /**
+ * 支持的处理器类型,类型不匹配则跳过该 ProcessorFactory 的加载逻辑
+ * 对应的是控制台的'处理器类型' TAB,不做任何定制的情况下,取值范围为 {@link ProcessorType#name()}
+ * @return 支持的处理器类型
+ */
+ Set supportTypes();
+
+ /**
+ * 根据处理器定义构建处理器对象
+ * 注意:Processor 为单例对象,即 PowerJob 对每一个 ProcessorBean 只调用一次 build 方法
+ * @param processorDefinition 处理器定义
+ * @return null or ProcessorBean
+ */
+ ProcessorBean build(ProcessorDefinition processorDefinition);
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/persistence/ConnectionFactory.java b/powerjob-worker/src/main/java/tech/powerjob/worker/persistence/ConnectionFactory.java
index 60013e7e..dfbe2cd0 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/persistence/ConnectionFactory.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/persistence/ConnectionFactory.java
@@ -8,6 +8,7 @@ import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.h2.Driver;
+import tech.powerjob.worker.common.utils.PowerFileUtils;
import javax.sql.DataSource;
import java.io.File;
@@ -25,7 +26,7 @@ public class ConnectionFactory {
private volatile DataSource dataSource;
- private final String H2_PATH = System.getProperty("user.home") + "/powerjob/worker/h2/" + CommonUtils.genUUID() + "/";
+ private final String H2_PATH = PowerFileUtils.workspace() + "/h2/" + CommonUtils.genUUID() + "/";
private final String DISK_JDBC_URL = String.format("jdbc:h2:file:%spowerjob_worker_db;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false", H2_PATH);
private final String MEMORY_JDBC_URL = String.format("jdbc:h2:mem:%spowerjob_worker_db;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false", H2_PATH);
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/persistence/TaskPersistenceService.java b/powerjob-worker/src/main/java/tech/powerjob/worker/persistence/TaskPersistenceService.java
index 97c5794d..f490146c 100644
--- a/powerjob-worker/src/main/java/tech/powerjob/worker/persistence/TaskPersistenceService.java
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/persistence/TaskPersistenceService.java
@@ -1,17 +1,17 @@
package tech.powerjob.worker.persistence;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import lombok.extern.slf4j.Slf4j;
import tech.powerjob.common.RemoteConstant;
+import tech.powerjob.common.utils.CollectionUtils;
import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.common.utils.SupplierPlus;
import tech.powerjob.worker.common.constants.StoreStrategy;
import tech.powerjob.worker.common.constants.TaskConstant;
import tech.powerjob.worker.common.constants.TaskStatus;
import tech.powerjob.worker.core.processor.TaskResult;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.List;
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/processor/PowerJobProcessorLoader.java b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/PowerJobProcessorLoader.java
new file mode 100644
index 00000000..00be4fa5
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/PowerJobProcessorLoader.java
@@ -0,0 +1,56 @@
+package tech.powerjob.worker.processor;
+
+import lombok.extern.slf4j.Slf4j;
+import tech.powerjob.common.exception.PowerJobException;
+import tech.powerjob.worker.extension.processor.ProcessorBean;
+import tech.powerjob.worker.extension.processor.ProcessorDefinition;
+import tech.powerjob.worker.extension.processor.ProcessorFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * PowerJobProcessorLoader
+ *
+ * @author tjq
+ * @since 2023/1/17
+ */
+@Slf4j
+public class PowerJobProcessorLoader implements ProcessorLoader {
+
+ private final List processorFactoryList;
+ private final Map def2Bean = new ConcurrentHashMap<>(128);
+
+ public PowerJobProcessorLoader(List processorFactoryList) {
+ this.processorFactoryList = processorFactoryList;
+ }
+
+ @Override
+ public ProcessorBean load(ProcessorDefinition definition) {
+ return def2Bean.computeIfAbsent(definition, ignore -> {
+ final String processorType = definition.getProcessorType();
+ log.info("[ProcessorFactory] start to load Processor: {}", definition);
+ for (ProcessorFactory pf : processorFactoryList) {
+ final String pfName = pf.getClass().getSimpleName();
+ if (!Optional.ofNullable(pf.supportTypes()).orElse(Collections.emptySet()).contains(processorType)) {
+ log.info("[ProcessorFactory] [{}] can't load type={}, skip!", pfName, processorType);
+ continue;
+ }
+ log.info("[ProcessorFactory] [{}] try to load processor: {}", pfName, definition);
+ try {
+ ProcessorBean processorBean = pf.build(definition);
+ if (processorBean != null) {
+ log.info("[ProcessorFactory] [{}] load processor successfully: {}", pfName, definition);
+ return processorBean;
+ }
+ } catch (Throwable t) {
+ log.error("[ProcessorFactory] [{}] load processor failed: {}", pfName, definition, t);
+ }
+ }
+ throw new PowerJobException("fetch Processor failed, please check your processorType and processorInfo config");
+ });
+ }
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/processor/ProcessorLoader.java b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/ProcessorLoader.java
new file mode 100644
index 00000000..d37a3303
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/ProcessorLoader.java
@@ -0,0 +1,15 @@
+package tech.powerjob.worker.processor;
+
+import tech.powerjob.worker.extension.processor.ProcessorBean;
+import tech.powerjob.worker.extension.processor.ProcessorDefinition;
+
+/**
+ * 内部使用的 Processor 加载器
+ *
+ * @author Echo009
+ * @since 2023/1/20
+ */
+public interface ProcessorLoader {
+
+ ProcessorBean load(ProcessorDefinition definition);
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/BuiltInDefaultProcessorFactory.java b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/BuiltInDefaultProcessorFactory.java
new file mode 100644
index 00000000..764df546
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/BuiltInDefaultProcessorFactory.java
@@ -0,0 +1,43 @@
+package tech.powerjob.worker.processor.impl;
+
+import com.google.common.collect.Sets;
+import lombok.extern.slf4j.Slf4j;
+import tech.powerjob.common.enums.ProcessorType;
+import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
+import tech.powerjob.worker.extension.processor.ProcessorBean;
+import tech.powerjob.worker.extension.processor.ProcessorDefinition;
+import tech.powerjob.worker.extension.processor.ProcessorFactory;
+
+import java.util.Set;
+
+/**
+ * 内建的默认处理器工厂,通过全限定类名加载处理器,但无法享受 IOC 框架的 DI 功能
+ *
+ * @author tjq
+ * @since 2023/1/17
+ */
+@Slf4j
+public class BuiltInDefaultProcessorFactory implements ProcessorFactory {
+
+ @Override
+ public Set supportTypes() {
+ return Sets.newHashSet(ProcessorType.BUILT_IN.name());
+ }
+
+ @Override
+ public ProcessorBean build(ProcessorDefinition processorDefinition) {
+
+ String className = processorDefinition.getProcessorInfo();
+
+ try {
+ Class> clz = Class.forName(className);
+ BasicProcessor basicProcessor = (BasicProcessor) clz.getDeclaredConstructor().newInstance();
+ return new ProcessorBean()
+ .setProcessor(basicProcessor)
+ .setClassLoader(basicProcessor.getClass().getClassLoader());
+ }catch (Exception e) {
+ log.warn("[ProcessorFactory] load local Processor(className = {}) failed.", className, e);
+ }
+ return null;
+ }
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/BuiltInSpringProcessorFactory.java b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/BuiltInSpringProcessorFactory.java
new file mode 100644
index 00000000..e93afe27
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/BuiltInSpringProcessorFactory.java
@@ -0,0 +1,83 @@
+package tech.powerjob.worker.processor.impl;
+
+import com.google.common.collect.Sets;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.ApplicationContext;
+import tech.powerjob.common.enums.ProcessorType;
+import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
+import tech.powerjob.worker.extension.processor.ProcessorBean;
+import tech.powerjob.worker.extension.processor.ProcessorDefinition;
+import tech.powerjob.worker.extension.processor.ProcessorFactory;
+
+import java.util.Set;
+
+/**
+ * 内建的 SpringBean 处理器工厂,用于加载 Spring 相关的Bean,非核心依赖
+ *
+ * @author tjq
+ * @since 2023/1/17
+ */
+@Slf4j
+public class BuiltInSpringProcessorFactory implements ProcessorFactory {
+
+ private final ApplicationContext applicationContext;
+
+ public BuiltInSpringProcessorFactory(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ @Override
+ public Set supportTypes() {
+ return Sets.newHashSet(ProcessorType.BUILT_IN.name());
+ }
+
+ @Override
+ public ProcessorBean build(ProcessorDefinition processorDefinition) {
+
+ try {
+ boolean canLoad = checkCanLoad();
+ if (!canLoad) {
+ log.info("[ProcessorFactory] can't find Spring env, this processor can't load by 'BuiltInSpringProcessorFactory'");
+ return null;
+ }
+
+ BasicProcessor basicProcessor = getBean(processorDefinition.getProcessorInfo(), applicationContext);
+ return new ProcessorBean()
+ .setProcessor(basicProcessor)
+ .setClassLoader(basicProcessor.getClass().getClassLoader());
+ } catch (Throwable t) {
+ log.warn("[ProcessorFactory] load by BuiltInSpringProcessorFactory failed. If you are using Spring, make sure this bean was managed by Spring", t);
+ }
+
+ return null;
+ }
+
+ private boolean checkCanLoad() {
+ try {
+ ApplicationContext.class.getClassLoader();
+ return applicationContext != null;
+ } catch (Throwable ignore) {
+ }
+ return false;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private static T getBean(String className, ApplicationContext ctx) throws Exception {
+ // 1. ClassLoader 存在,则直接使用 clz 加载
+ ClassLoader classLoader = ctx.getClassLoader();
+ if (classLoader != null) {
+ return (T) ctx.getBean(classLoader.loadClass(className));
+ }
+ // 2. ClassLoader 不存在(系统类加载器不可见),尝试用类名称小写加载
+ String[] split = className.split("\\.");
+ String beanName = split[split.length - 1];
+ // 小写转大写
+ char[] cs = beanName.toCharArray();
+ cs[0] += 32;
+ String beanName0 = String.valueOf(cs);
+ log.warn("[SpringUtils] can't get ClassLoader from context[{}], try to load by beanName:{}", ctx, beanName0);
+ return (T) ctx.getBean(beanName0);
+ }
+
+}
diff --git a/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/JarContainerProcessorFactory.java b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/JarContainerProcessorFactory.java
new file mode 100644
index 00000000..26762be5
--- /dev/null
+++ b/powerjob-worker/src/main/java/tech/powerjob/worker/processor/impl/JarContainerProcessorFactory.java
@@ -0,0 +1,55 @@
+package tech.powerjob.worker.processor.impl;
+
+import com.google.common.collect.Sets;
+import lombok.extern.slf4j.Slf4j;
+import tech.powerjob.common.enums.ProcessorType;
+import tech.powerjob.worker.common.WorkerRuntime;
+import tech.powerjob.worker.container.OmsContainer;
+import tech.powerjob.worker.container.OmsContainerFactory;
+import tech.powerjob.worker.extension.processor.ProcessorBean;
+import tech.powerjob.worker.extension.processor.ProcessorDefinition;
+import tech.powerjob.worker.extension.processor.ProcessorFactory;
+
+import java.util.Set;
+
+/**
+ * 加载容器处理器
+ *
+ * @author tjq
+ * @since 2023/1/17
+ */
+@Slf4j
+public class JarContainerProcessorFactory implements ProcessorFactory {
+
+ private final WorkerRuntime workerRuntime;
+
+ public JarContainerProcessorFactory(WorkerRuntime workerRuntime) {
+ this.workerRuntime = workerRuntime;
+ }
+
+ @Override
+ public Set supportTypes() {
+ return Sets.newHashSet(ProcessorType.EXTERNAL.name());
+ }
+
+ @Override
+ public ProcessorBean build(ProcessorDefinition processorDefinition) {
+
+ String processorInfo = processorDefinition.getProcessorInfo();
+ String[] split = processorInfo.split("#");
+ String containerName = split[0];
+ String className = split[1];
+
+ log.info("[ProcessorFactory] try to load processor({}) in container({})", className, containerName);
+
+ OmsContainer omsContainer = OmsContainerFactory.fetchContainer(Long.valueOf(containerName), workerRuntime);
+ if (omsContainer != null) {
+ return new ProcessorBean()
+ .setProcessor(omsContainer.getProcessor(className))
+ .setClassLoader(omsContainer.getContainerClassLoader());
+ } else {
+ log.warn("[ProcessorFactory] load container failed. processor info : {}", processorInfo);
+ }
+ return null;
+ }
+}
diff --git a/powerjob-worker/src/main/resources/oms-worker.akka.conf b/powerjob-worker/src/main/resources/oms-worker.akka.conf
deleted file mode 100644
index 16f7b911..00000000
--- a/powerjob-worker/src/main/resources/oms-worker.akka.conf
+++ /dev/null
@@ -1,70 +0,0 @@
-akka {
-
- loggers = ["akka.event.slf4j.Slf4jLogger"]
- loglevel = "WARNING"
-
- actor {
- # cluster is better(recommend by official document), but I prefer remote
- provider = remote
- allow-java-serialization = off
-
- serializers {
- power-serializer = "tech.powerjob.common.serialize.PowerAkkaSerializer"
- }
-
- serialization-bindings {
- "tech.powerjob.common.PowerSerializable" = power-serializer
- }
- }
- remote {
- artery {
- transport = tcp # See Selecting a transport below
- # over write by code
- canonical.hostname = "127.0.0.1"
- canonical.port = 25520
- }
- }
-
- # dispatcher
- task-tracker-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
- }
-
- processor-tracker-dispatcher {
- type = Dispatcher
- executor = "fork-join-executor"
- fork-join-executor {
- parallelism-min = 2
- parallelism-factor = 2.0
- parallelism-max = 64
- }
- throughput = 10
- }
-
- worker-common-dispatcher {
- type = Dispatcher
- executor = "fork-join-executor"
- fork-join-executor {
- parallelism-min = 2
- parallelism-factor = 2.0
- parallelism-max = 8
- }
- throughput = 10
- }
-}
\ No newline at end of file
diff --git a/powerjob-worker/src/test/java/tech/powerjob/worker/test/CommonTaskTrackerTest.java b/powerjob-worker/src/test/java/tech/powerjob/worker/test/CommonTaskTrackerTest.java
deleted file mode 100644
index d3becf1f..00000000
--- a/powerjob-worker/src/test/java/tech/powerjob/worker/test/CommonTaskTrackerTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package tech.powerjob.worker.test;
-
-import akka.actor.ActorSelection;
-import akka.actor.ActorSystem;
-import tech.powerjob.common.RemoteConstant;
-import tech.powerjob.common.enums.ExecuteType;
-import tech.powerjob.common.enums.TimeExpressionType;
-import tech.powerjob.worker.PowerJobWorker;
-import tech.powerjob.worker.common.PowerJobWorkerConfig;
-import tech.powerjob.worker.common.utils.AkkaUtils;
-import tech.powerjob.common.utils.NetUtils;
-import com.google.common.collect.Lists;
-import com.typesafe.config.ConfigFactory;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-/**
- * 测试完整的 JobInstance 执行流程
- *
- * @author tjq
- * @since 2020/3/25
- */
-public class CommonTaskTrackerTest {
-
- private static ActorSelection remoteTaskTracker;
-
- @BeforeAll
- public static void init() throws Exception {
-
- PowerJobWorkerConfig workerConfig = new PowerJobWorkerConfig();
- workerConfig.setAppName("oms-test");
- workerConfig.setServerAddress(Lists.newArrayList("127.0.0.1:7700"));
- workerConfig.setEnableTestMode(true);
-
- PowerJobWorker worker = new PowerJobWorker();
- worker.setConfig(workerConfig);
- worker.init();
-
- ActorSystem testAS = ActorSystem.create("oms-test", ConfigFactory.load("oms-akka-test.conf"));
- String akkaRemotePath = AkkaUtils.getAkkaWorkerPath(NetUtils.getLocalHost() + ":" + RemoteConstant.DEFAULT_WORKER_PORT, RemoteConstant.TASK_TRACKER_ACTOR_NAME);
- remoteTaskTracker = testAS.actorSelection(akkaRemotePath);
- }
-
- @Test
- public void justStartWorkerToTestServer() throws Exception {
- Thread.sleep(277277277);
- }
-
- @Test
- public void testStandaloneJob() throws Exception {
-
- remoteTaskTracker.tell(TestUtils.genServerScheduleJobReq(ExecuteType.STANDALONE, TimeExpressionType.CRON), null);
- Thread.sleep(5000000);
- }
-
- @Test
- public void testMapReduceJob() throws Exception {
- remoteTaskTracker.tell(TestUtils.genServerScheduleJobReq(ExecuteType.MAP_REDUCE, TimeExpressionType.CRON), null);
- Thread.sleep(5000000);
- }
-
- @Test
- public void testBroadcast() throws Exception {
- remoteTaskTracker.tell(TestUtils.genServerScheduleJobReq(ExecuteType.BROADCAST, TimeExpressionType.CRON), null);
- Thread.sleep(5000000);
- }
-
-}
diff --git a/powerjob-worker/src/test/java/tech/powerjob/worker/test/CommonTest.java b/powerjob-worker/src/test/java/tech/powerjob/worker/test/CommonTest.java
index 093ff9df..080bdf74 100644
--- a/powerjob-worker/src/test/java/tech/powerjob/worker/test/CommonTest.java
+++ b/powerjob-worker/src/test/java/tech/powerjob/worker/test/CommonTest.java
@@ -1,19 +1,10 @@
package tech.powerjob.worker.test;
-import akka.actor.ActorSelection;
-import akka.actor.ActorSystem;
import tech.powerjob.common.enums.ExecuteType;
import tech.powerjob.common.enums.ProcessorType;
-import tech.powerjob.common.RemoteConstant;
import tech.powerjob.common.utils.NetUtils;
-import tech.powerjob.worker.PowerJobWorker;
-import tech.powerjob.worker.common.PowerJobWorkerConfig;
-import tech.powerjob.worker.common.utils.AkkaUtils;
import tech.powerjob.worker.pojo.model.InstanceInfo;
import tech.powerjob.worker.pojo.request.TaskTrackerStartTaskReq;
-import com.typesafe.config.ConfigFactory;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
/**
* 启动公共服务
@@ -23,30 +14,6 @@ import org.junit.jupiter.api.BeforeAll;
*/
public class CommonTest {
- protected static ActorSelection remoteProcessorTracker;
- protected static ActorSelection remoteTaskTracker;
-
- @BeforeAll
- public static void startWorker() throws Exception {
- PowerJobWorkerConfig workerConfig = new PowerJobWorkerConfig();
- workerConfig.setAppName("oms-test");
- workerConfig.setEnableTestMode(true);
-
- PowerJobWorker worker = new PowerJobWorker();
- worker.setConfig(workerConfig);
- worker.init();
-
- ActorSystem testAS = ActorSystem.create("oms-test", ConfigFactory.load("oms-akka-test.conf"));
- String address = NetUtils.getLocalHost() + ":27777";
-
- remoteProcessorTracker = testAS.actorSelection(AkkaUtils.getAkkaWorkerPath(address, RemoteConstant.PROCESSOR_TRACKER_ACTOR_NAME));
- remoteTaskTracker = testAS.actorSelection(AkkaUtils.getAkkaWorkerPath(address, RemoteConstant.TASK_TRACKER_ACTOR_NAME));
- }
-
- @AfterAll
- public static void stop() throws Exception {
- Thread.sleep(120000);
- }
public static TaskTrackerStartTaskReq genTaskTrackerStartTaskReq(String processor) {
diff --git a/powerjob-worker/src/test/java/tech/powerjob/worker/test/FrequentTaskTrackerTest.java b/powerjob-worker/src/test/java/tech/powerjob/worker/test/FrequentTaskTrackerTest.java
deleted file mode 100644
index 0bf630c5..00000000
--- a/powerjob-worker/src/test/java/tech/powerjob/worker/test/FrequentTaskTrackerTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package tech.powerjob.worker.test;
-
-import akka.actor.ActorSelection;
-import akka.actor.ActorSystem;
-import tech.powerjob.common.enums.ExecuteType;
-import tech.powerjob.common.RemoteConstant;
-import tech.powerjob.common.enums.TimeExpressionType;
-import tech.powerjob.common.utils.NetUtils;
-import tech.powerjob.worker.PowerJobWorker;
-import tech.powerjob.worker.common.PowerJobWorkerConfig;
-import tech.powerjob.worker.common.utils.AkkaUtils;
-import com.google.common.collect.Lists;
-import com.typesafe.config.ConfigFactory;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-/**
- * description
- *
- * @author tjq
- * @since 2020/4/9
- */
-public class FrequentTaskTrackerTest {
-
- private static ActorSelection remoteTaskTracker;
-
- @BeforeAll
- public static void init() throws Exception {
-
- PowerJobWorkerConfig workerConfig = new PowerJobWorkerConfig();
- workerConfig.setAppName("oms-test");
- workerConfig.setServerAddress(Lists.newArrayList("127.0.0.1:7700"));
- PowerJobWorker worker = new PowerJobWorker();
- worker.setConfig(workerConfig);
- worker.init();
-
- ActorSystem testAS = ActorSystem.create("oms-test", ConfigFactory.load("oms-akka-test.conf"));
- String akkaRemotePath = AkkaUtils.getAkkaWorkerPath(NetUtils.getLocalHost() + ":" + RemoteConstant.DEFAULT_WORKER_PORT, RemoteConstant.TASK_TRACKER_ACTOR_NAME);
- remoteTaskTracker = testAS.actorSelection(akkaRemotePath);
- }
-
- @Test
- public void testFixRateJob() throws Exception {
- remoteTaskTracker.tell(TestUtils.genServerScheduleJobReq(ExecuteType.STANDALONE, TimeExpressionType.FIXED_RATE), null);
- Thread.sleep(5000000);
- }
-
- @Test
- public void testFixDelayJob() throws Exception {
- remoteTaskTracker.tell(TestUtils.genServerScheduleJobReq(ExecuteType.MAP_REDUCE, TimeExpressionType.FIXED_DELAY), null);
- Thread.sleep(5000000);
- }
-}
diff --git a/powerjob-worker/src/test/java/tech/powerjob/worker/test/ProcessorTrackerTest.java b/powerjob-worker/src/test/java/tech/powerjob/worker/test/ProcessorTrackerTest.java
deleted file mode 100644
index 3a52cd33..00000000
--- a/powerjob-worker/src/test/java/tech/powerjob/worker/test/ProcessorTrackerTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package tech.powerjob.worker.test;
-
-import tech.powerjob.worker.pojo.request.TaskTrackerStartTaskReq;
-import org.junit.jupiter.api.Test;
-
-
-/**
- * 测试任务的启动
- *
- * @author tjq
- * @since 2020/3/24
- */
-public class ProcessorTrackerTest extends CommonTest {
-
- @Test
- public void testBasicProcessor() throws Exception {
-
- TaskTrackerStartTaskReq req = genTaskTrackerStartTaskReq("tech.powerjob.worker.test.processors.TestBasicProcessor");
- remoteProcessorTracker.tell(req, null);
- Thread.sleep(30000);
- }
-
- @Test
- public void testMapReduceProcessor() throws Exception {
- TaskTrackerStartTaskReq req = genTaskTrackerStartTaskReq("tech.powerjob.worker.test.processors.TestMapReduceProcessor");
- remoteProcessorTracker.tell(req, null);
- Thread.sleep(30000);
- }
-}
diff --git a/powerjob-worker/src/test/resources/oms-akka-test.conf b/powerjob-worker/src/test/resources/oms-akka-test.conf
deleted file mode 100644
index 7615d41a..00000000
--- a/powerjob-worker/src/test/resources/oms-akka-test.conf
+++ /dev/null
@@ -1,18 +0,0 @@
-akka {
- actor {
- # for test
- provider = remote
- allow-java-serialization = off
-
- serialization-bindings {
- "OmsSerializable" = jackson-cbor
- }
- }
- remote {
- artery {
- transport = tcp # See Selecting a transport below
- canonical.hostname = "127.0.0.1"
- canonical.port = 25521
- }
- }
-}
\ No newline at end of file