mirror of
https://github.com/PowerJob/PowerJob.git
synced 2025-07-17 00:00:04 +08:00
[fix] opt dockerfile & almost to release
This commit is contained in:
parent
46081f002a
commit
537b2e6433
@ -8,8 +8,8 @@ ENV APP_NAME=oh-my-scheduler-server
|
||||
ENV PARAMS=""
|
||||
# 将应用 jar 包拷入 docker
|
||||
COPY oms-server.jar /oms-server.jar
|
||||
# 暴露端口(HTTP + AKKA-Server + AKKA-Client)
|
||||
EXPOSE 7700 10086 27777
|
||||
# 暴露端口(HTTP + AKKA-Server)
|
||||
EXPOSE 7700 10086
|
||||
# 创建 docker 文件目录(盲猜这是用户目录)
|
||||
RUN mkdir -p /root/oms-server
|
||||
# 挂载数据卷,将文件直接输出到宿主机(注意,此处挂载的是匿名卷,即在宿主机位置随机)
|
||||
|
@ -15,6 +15,7 @@ import com.github.kfcfans.oms.server.web.request.GenerateContainerTemplateReques
|
||||
import com.github.kfcfans.oms.server.web.request.SaveContainerInfoRequest;
|
||||
import com.github.kfcfans.oms.server.web.response.ContainerInfoVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -94,6 +95,10 @@ public class ContainerController {
|
||||
AppInfoDO appInfoDO = appInfoRepository.findById(appId).orElseThrow(() -> new IllegalArgumentException("can't find app by id:" + appId));
|
||||
String targetServer = appInfoDO.getCurrentServer();
|
||||
|
||||
if (StringUtils.isEmpty(targetServer)) {
|
||||
return ResultDTO.failed("No workers have even registered!");
|
||||
}
|
||||
|
||||
// 转发 HTTP 请求
|
||||
if (!OhMyServer.getActorSystemAddress().equals(targetServer)) {
|
||||
String targetIp = targetServer.split(":")[0];
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 没有 javac 需求,用 JRE 镜像
|
||||
# agent 没有 javac 需求,用 JRE 镜像
|
||||
FROM openjdk:8-jre-slim
|
||||
MAINTAINER tengjiqi@gmail.com
|
||||
|
||||
@ -6,11 +6,9 @@ ENV APP_NAME=oh-my-scheduler-worker-agent
|
||||
ENV PARAMS=""
|
||||
|
||||
COPY oms-agent.jar /oms-agent.jar
|
||||
# 暴露端口(HTTP + AKKA-Server + AKKA-Client)
|
||||
EXPOSE 7700 10086 27777
|
||||
# 创建 docker 文件目录(盲猜这是用户目录)
|
||||
RUN mkdir -p /root/oms-agent
|
||||
# 暴露端口(AKKA-Client)
|
||||
EXPOSE 27777
|
||||
# 挂载数据卷,将文件直接输出到宿主机(注意,此处挂载的是匿名卷,即在宿主机位置随机)
|
||||
VOLUME /root/oms
|
||||
VOLUME /root
|
||||
# 启动应用
|
||||
ENTRYPOINT ["sh","-c","java -jar /oms-agent.jar $PARAMS"]
|
@ -30,7 +30,7 @@ public class MainApplication implements Runnable {
|
||||
private String storeStrategy = "DISK";
|
||||
|
||||
@Option(names = {"-s", "--server"}, description = "调度中心地址,多值英文逗号分隔,格式 IP:Port OR domain")
|
||||
private String server = "127.0.0.1:7700";
|
||||
private String server = "localhost:7700";
|
||||
|
||||
@Option(names = {"-l", "--length"}, description = "返回值最大长度")
|
||||
private int length = 1024;
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
<!-- 系统所有异常日志(ERROR)双写 start -->
|
||||
<appender name="ERROR_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_PATH}/oms-server-error.log</file>
|
||||
<file>${LOG_PATH}/oms-agent-error.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>${LOG_PATH}/oms-agent-error.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
<MaxHistory>7</MaxHistory>
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
<!-- 系统主日志 start -->
|
||||
<appender name="DEFAULT_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_PATH}/oms-server-application.log</file>
|
||||
<file>${LOG_PATH}/oms-agent-application.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>${LOG_PATH}/oms-agent-application.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
<MaxHistory>7</MaxHistory>
|
||||
|
@ -1,58 +0,0 @@
|
||||
# STEP3: 任务管理 & 运行状态查看
|
||||
>通过前端控制台管理调度任务,查看运行情况和结果等。
|
||||
|
||||
### 系统首页
|
||||
> 展示了系统整体的概览和集群Worker列表。
|
||||
|
||||

|
||||
|
||||
### 任务创建
|
||||
> 创建需要被调度执行的任务,入口为**主页 -> 任务管理 -> 新建任务**。
|
||||
|
||||

|
||||
* 任务名称:名称,便于记忆与搜索,无特殊用途,请尽量简短(占用数据库字段空间)
|
||||
* 任务描述:描述,无特殊作用,请尽量简短(占用数据库字段空间)
|
||||
* 任务参数:任务处理时能够获取到的参数(即各个Processor的process方法入参`TaskContext`对象的jobParams字段)(进行一次处理器开发就能理解了)
|
||||
* 定时信息:由下拉框和输入框组成
|
||||
* API -> 不需要填写任何参数(填了也不起作用)
|
||||
* CRON -> 填写 CRON 表达式(可以找个[在线生成网站生成](https://www.bejson.com/othertools/cron/))
|
||||
* 固定频率 -> 填写整数,单位毫秒
|
||||
* 固定延迟 -> 填写整数,单位毫秒
|
||||
* 执行配置:由执行类型(单机、广播和MapReduce)、处理器类型和处理器参数组成,后两项相互关联。
|
||||
* 内置Java处理器 -> 填写该处理器的全限定类名(eg, `com.github.kfcfans.oms.processors.demo.MapReduceProcessorDemo`)
|
||||
* SHELL -> 填写需要处理的脚本(直接复制文件内容)或脚本下载连接(http://xxx)
|
||||
* PYTHON -> 填写完整的python脚本或下载连接(http://xxx)
|
||||
|
||||
* 运行配置
|
||||
* 最大实例数:该任务同时执行的数量(任务和实例就像是类和对象的关系,任务被调度执行后被称为实例)
|
||||
* 单机线程并发数:该实例执行过程中每个Worker使用的线程数量(MapReduce任务生效,其余无论填什么,都只会使用1个线程或3个线程...)
|
||||
* 运行时间限制:限定任务的最大运行时间,超时则视为失败,单位**毫秒**,0代表不限制超时时间。
|
||||
|
||||
* 重试配置:
|
||||
* 任务重试次数:实例级别,失败了整个任务实例重试,会更换TaskTracker(本次任务实例的Master节点),代价较大,大型Map/MapReduce慎用。
|
||||
* 子任务重试次数:Task级别,每个子Task失败后单独重试,会更换ProcessorTracker(本次任务实际执行的Worker节点),代价较小,推荐使用。
|
||||
* 注:对于单机任务来说,假如任务重试次数和子任务重试次数都配置了1且都执行失败,实际执行次数会变成4次!推荐任务实例重试配置为0,子任务重试次数根据实际情况配置。
|
||||
|
||||
* 机器配置:用来标明允许执行任务的机器状态,避开那些摇摇欲坠的机器,0代表无任何限制。
|
||||
* 最低CPU核心数:填写浮点数,CPU可用核心数小于该值的Worker将不会执行该任务。
|
||||
* 最低内存(GB):填写浮点数,可用内存小于该值的Worker将不会执行该任务。
|
||||
* 最低磁盘(GB):填写浮点数,可用磁盘空间小于该值的Worker将不会执行该任务。
|
||||
* 集群配置
|
||||
* 执行机器地址:指定集群中的某几台机器执行任务(debug的好帮手),多值英文逗号分割,如`192.168.1.1:27777,192.168.1.2:27777`
|
||||
* 最大执行机器数量:限定调动执行的机器数量
|
||||
|
||||
* 报警配置:选择任务执行失败后报警通知的对象,需要事先录入。
|
||||
|
||||
### 任务管理
|
||||
>可以方便地查看和管理系统当前录入的任务信息。
|
||||
|
||||

|
||||
|
||||
### 运行状态
|
||||
>可以方便地查看当前运行的任务实例,点击详情即可获取详细的信息,点击日志可以查看通过`omsLogger`上报的日志,点击停止则可以强制终止该任务。
|
||||
|
||||

|
||||
|
||||
### 在线日志
|
||||
|
||||

|
@ -1,111 +0,0 @@
|
||||
# STEP4: OpenAPI
|
||||
|
||||
## 快速开始
|
||||
>OpenAPI允许开发者通过接口来完成手工的操作,让系统整体变得更加灵活,启用OpenAPI需要依赖`oh-my-scheduler-client`库。
|
||||
|
||||
最新依赖版本请参考Maven中央仓库:[推荐地址](https://search.maven.org/search?q=oh-my-scheduler-client)&[备用地址](https://mvnrepository.com/search?q=com.github.kfcfans)。
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.github.kfcfans</groupId>
|
||||
<artifactId>oh-my-scheduler-client</artifactId>
|
||||
<version>${oms.client.latest.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 简单示例
|
||||
|
||||
```text
|
||||
// 初始化 client,需要server地址和应用名称作为参数
|
||||
OhMyClient ohMyClient = new OhMyClient("127.0.0.1:7700", "oms-test");
|
||||
// 调用相关的API
|
||||
ohMyClient.stopInstance(1586855173043L)
|
||||
```
|
||||
|
||||
## 功能列表
|
||||
#### 创建/修改任务
|
||||
接口签名:`ResultDTO<Long> saveJob(ClientJobInfo newJobInfo)`
|
||||
|
||||
入参:任务信息(详细说明见下表,也可以参考[前端任务创建各参数的正确填法](./ConsoleGuide.md))
|
||||
|
||||
返回值:ResultDTO<Long>,根据success判断操作是否成功。若操作成功,data字段返回任务ID
|
||||
|
||||
|属性|说明|
|
||||
|----|----|
|
||||
|jobId|任务ID,可选,null代表创建任务,否则填写需要修改的任务ID|
|
||||
|jobName|任务名称|
|
||||
|jobDescription|任务描述|
|
||||
|jobParams|任务参数,Processor#process方法入参`TaskContext`对象的jobParams字段|
|
||||
|timeExpressionType|时间表达式类型,枚举值|
|
||||
|timeExpression|时间表达式,填写类型由timeExpressionType决定,比如CRON需要填写CRON表达式|
|
||||
|executeType|执行类型,枚举值|
|
||||
|processorType|处理器类型,枚举值|
|
||||
|processorInfo|处理器参数,填写类型由processorType决定,如Java处理器需要填写全限定类名,如:com.github.kfcfans.oms.processors.demo.MapReduceProcessorDemo|
|
||||
|maxInstanceNum|最大实例数,该任务同时执行的数量(任务和实例就像是类和对象的关系,任务被调度执行后被称为实例)|
|
||||
|concurrency|单机线程并发数,表示该实例执行过程中每个Worker使用的线程数量|
|
||||
|instanceTimeLimit|任务实例运行时间限制,0代表无任何限制,超时会被打断并判定为执行失败|
|
||||
|instanceRetryNum|任务实例重试次数,整个任务失败时重试,代价大,不推荐使用|
|
||||
|taskRetryNum|Task重试次数,每个子Task失败后单独重试,代价小,推荐使用|
|
||||
|minCpuCores|最小可用CPU核心数,CPU可用核心数小于该值的Worker将不会执行该任务,0代表无任何限制|
|
||||
|minMemorySpace|最小内存大小(GB),可用内存小于该值的Worker将不会执行该任务,0代表无任何限制|
|
||||
|minDiskSpace|最小磁盘大小(GB),可用磁盘空间小于该值的Worker将不会执行该任务,0代表无任何限制|
|
||||
|designatedWorkers|指定机器执行,设置该参数后只有列表中的机器允许执行该任务,0代表无任何限制|
|
||||
|maxWorkerCount|最大执行机器数量,限定调动执行的机器数量,空代表无限制|
|
||||
|notifyUserIds|接收报警的用户ID列表|
|
||||
|enable|是否启用该任务,未启用的任务不会被调度|
|
||||
|
||||
#### 查找任务
|
||||
接口签名:`ResultDTO<JobInfoDTO> fetchJob(Long jobId)`
|
||||
|
||||
入参:任务ID
|
||||
|
||||
返回值:根据success判断操作是否成功,若请求成功则返回任务的详细信息
|
||||
|
||||
#### 禁用某个任务
|
||||
接口签名:`ResultDTO<Void> disableJob(Long jobId)`
|
||||
|
||||
入参:任务ID
|
||||
|
||||
返回值:根据success判断操作是否成功
|
||||
|
||||
#### 启用某个任务
|
||||
接口签名:`ResultDTO<Void> enableJob(Long jobId)`
|
||||
|
||||
入参:任务ID
|
||||
|
||||
返回值:根据success判断操作是否成功
|
||||
|
||||
#### 删除某个任务
|
||||
接口签名:`ResultDTO<Void> deleteJob(Long jobId)`
|
||||
|
||||
入参:任务ID
|
||||
|
||||
返回值:根据success判断操作是否成功
|
||||
|
||||
#### 立即运行某个任务
|
||||
接口签名:`ResultDTO<Long> runJob(Long jobId, String instanceParams)`
|
||||
|
||||
入参:任务ID + **任务实例参数**(Processor#process方法入参`TaskContext`对象的instanceParams字段)
|
||||
|
||||
返回值:根据success判断操作是否成功,操作成功返回对应的任务实例ID(instanceId)
|
||||
|
||||
#### 停止某个任务实例
|
||||
接口签名:`ResultDTO<Void> stopInstance(Long instanceId)`
|
||||
|
||||
入参:任务实例ID
|
||||
|
||||
返回值:根据success判断操作是否成功
|
||||
|
||||
#### 查询某个任务实例
|
||||
接口签名:`ResultDTO<InstanceInfoDTO> fetchInstanceInfo(Long instanceId)`
|
||||
|
||||
入参:任务实例ID
|
||||
|
||||
返回值:根据success判断操作是否成功,操作成功返回任务实例的详细信息
|
||||
|
||||
#### 查询某个任务实例的状态
|
||||
接口签名:`ResultDTO<Integer> fetchInstanceStatus(Long instanceId)`
|
||||
|
||||
入参:任务实例ID
|
||||
|
||||
返回值:根据success判断操作是否成功,操作成功返回任务实例的状态码,对应的枚举为:InstanceStatus
|
@ -1,234 +0,0 @@
|
||||
# STEP2: 处理器开发
|
||||
>OhMyScheduler支持Python、Shell和Java处理器,前两种处理器为脚本处理器,功能简单,在控制台直接配置即可,本章主要介绍内置于Java项目的处理器开发。
|
||||
|
||||
## 宿主应用接入
|
||||
#### 添加依赖
|
||||
* 最新依赖版本请参考Maven中央仓库:[推荐地址](https://search.maven.org/search?q=oh-my-scheduler-worker)&[备用地址](https://mvnrepository.com/search?q=com.github.kfcfans)。
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>com.github.kfcfans</groupId>
|
||||
<artifactId>oh-my-scheduler-worker</artifactId>
|
||||
<version>${oms.worker.latest.version}</version>
|
||||
</dependency>
|
||||
```
|
||||
#### 初始化客户端:OhMyScheduler-Worker
|
||||
> 客户端启动类为`OhMyWorker`,需要设置配置文件`OhMyConfig`并启动,以下为配置文件说明和配置示例。
|
||||
|
||||
OhMyConfig属性说明:
|
||||
|
||||
|属性名称|含义|默认值|
|
||||
|----|----|----|
|
||||
|appName|宿主应用名称,需要提前在控制台完成注册|无,必填项,否则启动报错|
|
||||
|serverAddress|服务器(OhMyScheduler-Server)地址列表|无,必填项,否则启动报错|
|
||||
|storeStrategy|本地存储策略,枚举值磁盘/内存,大型MapReduce等会产生大量Task的任务推荐使用磁盘降低内存压力,否则建议使用内存加速计算|StoreStrategy.DISK(磁盘)|
|
||||
|maxResultLength|每个Task返回结果的默认长度,超长将被截断。过长可能导致网络拥塞|8096|
|
||||
|enableTestMode|是否启用测试模式,启用后无需Server也能顺利启动OhMyScheduler-Worker,用于处理器本地的单元测试|false|
|
||||
|
||||
OhMyWorker启动配置(Spring/SpringBoot模式):
|
||||
```java
|
||||
@Configuration
|
||||
public class OhMySchedulerConfig {
|
||||
@Bean
|
||||
public OhMyWorker initOMS() throws Exception {
|
||||
|
||||
// 服务器HTTP地址(端口号为 server.port,而不是 ActorSystem port)
|
||||
List<String> serverAddress = Lists.newArrayList("127.0.0.1:7700", "127.0.0.1:7701");
|
||||
|
||||
// 1. 创建配置文件
|
||||
OhMyConfig config = new OhMyConfig();
|
||||
config.setAppName("oms-test");
|
||||
config.setServerAddress(serverAddress);
|
||||
// 如果没有大型 Map/MapReduce 的需求,建议使用内存来加速计算
|
||||
// 为了本地模拟多个实例,只能使用 MEMORY 启动(文件只能由一个应用占有)
|
||||
config.setStoreStrategy(StoreStrategy.MEMORY);
|
||||
|
||||
// 2. 创建 Worker 对象,设置配置文件
|
||||
OhMyWorker ohMyWorker = new OhMyWorker();
|
||||
ohMyWorker.setConfig(config);
|
||||
return ohMyWorker;
|
||||
}
|
||||
}
|
||||
```
|
||||
非Spring应用程序在创建`OhMyWorker`对象后手动调用`ohMyWorker.init()`方法完成初始化即可。
|
||||
|
||||
### 配置日志
|
||||
目前,OhMyScheduler-Worker并没有实现自己的LogFactory(如果有需求的话请提ISSUE,可以考虑实现),原因如下:
|
||||
1. OhMyScheduler-Worker的日志基于`Slf4J`输出,即采用了基于门面设计模式的日志框架,宿主应用无论如何都可以搭起Slf4J与实际的日志框架这座桥梁。
|
||||
2. 减轻了部分开发工作量,不再需要实现自己的LogFactory(虽然不怎么难就是了...)。
|
||||
|
||||
为此,为了顺利且友好地输出日志,请在日志配置文件(logback.xml/log4j2.xml/...)中为`OhMyScheduler-Worker`单独进行日志配置,比如(logback示例):
|
||||
```xml
|
||||
<appender name="OMS_WORKER_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_PATH}/oms-worker.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>${LOG_PATH}/oms-worker.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
<MaxHistory>7</MaxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<append>true</append>
|
||||
</appender>
|
||||
|
||||
<logger name="com.github.kfcfans.oms.worker" level="INFO" additivity="false">
|
||||
<appender-ref ref="OMS_WORKER_APPENDER" />
|
||||
</logger>
|
||||
```
|
||||
无论如何,OhMyScheduler-Worker启动时都会打印Banner(如下所示),您可以通过Banner来判断日志配置是否成功:
|
||||
```text
|
||||
███████ ██ ████ ████ ████████ ██ ██ ██
|
||||
██░░░░░██ ░██ ░██░██ ██░██ ██ ██ ██░░░░░░ ░██ ░██ ░██
|
||||
██ ░░██░██ ░██░░██ ██ ░██ ░░██ ██ ░██ █████ ░██ █████ ░██ ██ ██ ░██ █████ ██████
|
||||
░██ ░██░██████ ░██ ░░███ ░██ ░░███ ░█████████ ██░░░██░██████ ██░░░██ ██████░██ ░██ ░██ ██░░░██░░██░░█
|
||||
░██ ░██░██░░░██░██ ░░█ ░██ ░██ ░░░░░░░░██░██ ░░ ░██░░░██░███████ ██░░░██░██ ░██ ░██░███████ ░██ ░
|
||||
░░██ ██ ░██ ░██░██ ░ ░██ ██ ░██░██ ██░██ ░██░██░░░░ ░██ ░██░██ ░██ ░██░██░░░░ ░██
|
||||
░░███████ ░██ ░██░██ ░██ ██ ████████ ░░█████ ░██ ░██░░██████░░██████░░██████ ███░░██████░███
|
||||
░░░░░░░ ░░ ░░ ░░ ░░ ░░ ░░░░░░░░ ░░░░░ ░░ ░░ ░░░░░░ ░░░░░░ ░░░░░░ ░░░ ░░░░░░ ░░░
|
||||
```
|
||||
|
||||
## 处理器开发
|
||||
>开发者需要根据实际需求实现`BasicProcessor`接口或继承`BroadcastProcessor`、`MapProcessor`或`MapReduceProcessor`抽象类实现处理器的开发。处理器的核心方法为`ProcessResult process(TaskContext context)`,以下为详细说明:
|
||||
|
||||
ProcessResult为处理返回结果,包含`success`和`msg`两个属性。
|
||||
|
||||
TaskContext为处理的入参,包含了本次处理的上下文信息,具体属性如下:
|
||||
|
||||
|属性名称|意义/用法|
|
||||
|----|----|
|
||||
|jobId|任务ID,开发者一般无需关心此参数|
|
||||
|instanceId|任务实例ID,全局唯一,开发者一般无需关心此参数|
|
||||
|subInstanceId|子任务实例ID,秒级任务使用,开发者一般无需关心此参数|
|
||||
|taskId|采用链式命名法的ID,在某个任务实例内唯一,开发者一般无需关心此参数|
|
||||
|taskName|task名称,Map/MapReduce任务的子任务的值为开发者指定,否则为系统默认值,开发者一般无需关心此参数|
|
||||
|jobParams|任务参数,其值等同于控制台录入的**任务参数**,常用!|
|
||||
|instanceParams|任务实例参数,其值等同于使用OpenAPI运行任务实例时传递的参数,常用!|
|
||||
|maxRetryTimes|Task的最大重试次数|
|
||||
|currentRetryTimes|Task的当前重试次数,和maxRetryTimes联合起来可以判断当前是否为该Task的最后一次运行机会|
|
||||
|subTask|子Task,Map/MapReduce处理器专属,开发者调用map方法时传递的子任务列表中的某一个|
|
||||
|omsLogger|在线日志,用法同Slf4J,记录的日志可以直接通过控制台查看,非常便捷和强大!不过使用过程中需要注意频率,可能对Server造成巨大的压力|
|
||||
|
||||
#### 单机处理器
|
||||
>单机执行的策略下,server会在所有可用worker中选取健康度最佳的机器进行执行。单机执行任务需要实现接口:`com.github.kfcfans.oms.worker.core.processor.sdk.BasicProcessor`,代码示例如下:
|
||||
|
||||
```java
|
||||
// 支持 SpringBean 的形式
|
||||
@Component
|
||||
public class BasicProcessorDemo implements BasicProcessor {
|
||||
|
||||
@Resource
|
||||
private MysteryService mysteryService;
|
||||
|
||||
@Override
|
||||
public ProcessResult process(TaskContext context) throws Exception {
|
||||
|
||||
// 在线日志功能,可以直接在控制台查看任务日志,非常便捷
|
||||
OmsLogger omsLogger = context.getOmsLogger();
|
||||
omsLogger.info("BasicProcessorDemo start to process, current JobParams is {}.", context.getJobParams());
|
||||
|
||||
// TaskContext为任务的上下文信息,包含了在控制台录入的任务元数据,常用字段为
|
||||
// jobParams(任务参数,在控制台录入),instanceParams(任务实例参数,通过 OpenAPI 触发的任务实例才可能存在该参数)
|
||||
|
||||
// 进行实际处理...
|
||||
mysteryService.hasaki();
|
||||
|
||||
// 返回结果,该结果会被持久化到数据库,在前端页面直接查看,极为方便
|
||||
return new ProcessResult(true, "result is xxx");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 广播执行处理器
|
||||
>广播执行的策略下,所有机器都会被调度执行该任务。为了便于资源的准备和释放,广播处理器在`BasicProcessor`的基础上额外增加了`preProcess`和`postProcess`方法,分别在整个集群开始之前/结束之后**选一台机器**执行相关方法。代码示例如下:
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class BroadcastProcessorDemo extends BroadcastProcessor {
|
||||
|
||||
@Override
|
||||
public ProcessResult preProcess(TaskContext taskContext) throws Exception {
|
||||
// 预执行,会在所有 worker 执行 process 方法前调用
|
||||
return new ProcessResult(true, "init success");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessResult process(TaskContext context) throws Exception {
|
||||
// 撰写整个worker集群都会执行的代码逻辑
|
||||
return new ProcessResult(true, "release resource success");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessResult postProcess(TaskContext taskContext, List<TaskResult> taskResults) throws Exception {
|
||||
|
||||
// taskResults 存储了所有worker执行的结果(包括preProcess)
|
||||
|
||||
// 收尾,会在所有 worker 执行完毕 process 方法后调用,该结果将作为最终的执行结果
|
||||
return new ProcessResult(true, "process success");
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### MapReduce处理器
|
||||
>MapReduce是最复杂也是最强大的一种执行器,它允许开发者完成任务的拆分,将子任务派发到集群中其他Worker执行,是执行大批量处理任务的不二之选!实现MapReduce处理器需要继承`MapReduceProcessor`类,具体用法如下示例代码所示。
|
||||
|
||||
```java
|
||||
@Component
|
||||
public class MapReduceProcessorDemo extends MapReduceProcessor {
|
||||
|
||||
@Override
|
||||
public ProcessResult process(TaskContext context) throws Exception {
|
||||
// 判断是否为根任务
|
||||
if (isRootTask()) {
|
||||
|
||||
// 构造子任务
|
||||
List<SubTask> subTaskList = Lists.newLinkedList();
|
||||
|
||||
/*
|
||||
* 子任务的构造由开发者自己定义
|
||||
* eg. 现在需要从文件中读取100W个ID,并处理数据库中这些ID对应的数据,那么步骤如下:
|
||||
* 1. 根任务(RootTask)读取文件,流式拉取100W个ID,并按1000个一批的大小组装成子任务进行派发
|
||||
* 2. 非根任务获取子任务,完成业务逻辑的处理
|
||||
*/
|
||||
|
||||
// 调用 map 方法,派发子任务
|
||||
return map(subTaskList, "DATA_PROCESS_TASK");
|
||||
}
|
||||
|
||||
// 非子任务,可根据 subTask 的类型 或 TaskName 来判断分支
|
||||
if (context.getSubTask() instanceof SubTask) {
|
||||
// 执行子任务,注:子任务人可以 map 产生新的子任务,可以构建任意级的 MapReduce 处理器
|
||||
return new ProcessResult(true, "PROCESS_SUB_TASK_SUCCESS");
|
||||
}
|
||||
|
||||
return new ProcessResult(false, "UNKNOWN_BUG");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessResult reduce(TaskContext taskContext, List<TaskResult> taskResults) {
|
||||
|
||||
// 所有 Task 执行结束后,reduce 将会被执行
|
||||
// taskResults 保存了所有子任务的执行结果
|
||||
|
||||
// 用法举例,统计执行结果
|
||||
AtomicLong successCnt = new AtomicLong(0);
|
||||
taskResults.forEach(tr -> {
|
||||
if (tr.isSuccess()) {
|
||||
successCnt.incrementAndGet();
|
||||
}
|
||||
});
|
||||
// 该结果将作为任务最终的执行结果
|
||||
return new ProcessResult(true, "success task num:" + successCnt.get());
|
||||
}
|
||||
|
||||
// 自定义的子任务
|
||||
private static class SubTask {
|
||||
private Long siteId;
|
||||
private List<Long> idList;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
更多示例请见:[oh-my-scheduler-worker-samples](../../oh-my-scheduler-worker-samples)
|
||||
|
@ -1,39 +0,0 @@
|
||||
# STEP1: 调度中心部署 & 初始化
|
||||
## 调度中心部署
|
||||
#### 要求
|
||||
* 运行环境:JDK8+
|
||||
* 编译环境:Maven3+
|
||||
* 关系数据库:任意Spring Data JPA支持的关系型数据库(MySQL/Oracle/MS SQLServer...)
|
||||
* mongoDB(可选):任意支持GridFS的mongoDB版本(4.2.6测试通过,其余未经测试,仅从理论角度分析可用)
|
||||
|
||||
#### 流程
|
||||
>注意,由于调度系统的特殊性,请务必**确保数据库和调度服务器处于同一个时区**。
|
||||
|
||||
1. 部署数据库:由于任务调度中心的数据持久层基于`Spring Data Jpa`实现,**开发者仅需要完成数据库的创建**,即运行SQL`CREATE database if NOT EXISTS oms-product default character set utf8mb4 collate utf8mb4_unicode_ci;`。
|
||||
* 注1:任务调度中心支持多环境部署(日常、预发、线上),其分别对应三个数据库:oms-daily、oms-pre和oms-product。
|
||||
* 注2:手动建表SQL文件:[oms-sql.sql](../oms-sql.sql)
|
||||
* 注3:部署完成后建议查看时区信息:`show variables like "%time_zone%";`,务必使`time_zone`代表的时区与JDBC连接URL中`serverTimezone`字段代表的时区一致!
|
||||
|
||||
2. 部署调度服务器(OhMyScheduler-Server),需要先修改配置文件(同样为了支持多环境部署,采用了daily、pre和product3套配置文件),之后自行编译部署运行。
|
||||
* 注1:OhMyScheduler-Server支持集群部署,具备完全的水平扩展能力。建议部署多个实例以实现高可用&高性能。
|
||||
* 注2:通过启动参数`--spring.profiles.active=product`来指定使用某套配置文件(默认为daily)
|
||||
* application-xxx.properties文件配置说明如下表所示:
|
||||
* |配置项|含义|可选|
|
||||
|----|----|----|
|
||||
|spring.datasource.core.xxx|关系型数据库连接配置|否|
|
||||
|spring.mail.xxx|邮件配置|是,未配置情况下将无法使用邮件报警功能|
|
||||
|spring.data.mongodb.xxx|MongoDB连接配置|是,未配置情况下将无法使用在线日志功能|
|
||||
|oms.log.retention.local|本地日志保留天数,负数代表永久保留|否|
|
||||
|oms.log.retention.remote|远程日志保留天数,负数代表永久保留|否|
|
||||
|oms.alarm.bean.names|扩展的报警服务Bean,多值逗号分割,默认为邮件报警|否|
|
||||
|
||||
3. 部署前端页面(可选):每一个OhMyScheduler-Server内部自带了前端页面,不过Tomcat做Web服务器的性能就呵呵了~有需求(追求)的用户自行使用[源码](https://github.com/KFCFans/OhMyScheduler-Console)打包部署即可。
|
||||
* 需要修改`main.js`中的`axios.defaults.baseURL`为实际的OhMyScheduler-Server地址
|
||||
|
||||
## 初始化
|
||||
> 每一个需要接入OhMyScheduler的系统,都需要先在控制台完成初始化,即应用注册与用户录入。初始化操作在首页完成。
|
||||
|
||||

|
||||
* 每一个系统初次接入OhMyScheduler时,都需要通过**应用注册**功能录入`appName`(接入应用的名称,需要保证唯一)和`appDescription`(描述信息,无实际用处),至此,应用初始化完成,准备开发处理器(Processor)享受分布式调度和计算的便利之处吧~
|
||||
* 注册完成后,输入`appName`即可进入控制台。
|
||||
* **用户注册**可录入用户信息,用于之后任务的报警配置。
|
@ -8,7 +8,9 @@ bookToc: false
|
||||
|
||||
## 项目地址
|
||||
|
||||
[GitHub](https://github.com/KFCFans/OhMyScheduler) | [Gitee](https://gitee.com/KFCFans/OhMyScheduler)
|
||||
GitHub:[](https://github.com/KFCFans/OhMyScheduler) [](https://github.com/KFCFans/OhMyScheduler)
|
||||
|
||||
Gitee : [](https://gitee.com/KFCFans/OhMyScheduler) [](https://gitee.com/KFCFans/OhMyScheduler)
|
||||
|
||||
## 产品介绍
|
||||
|
||||
@ -17,7 +19,7 @@ bookToc: false
|
||||
* 使用简单:提供前端Web界面,允许开发者可视化地完成调度任务的管理(增、删、改、查)、任务运行状态监控和运行日志查看等功能。
|
||||
* 定时策略完善:支持CRON表达式、固定频率、固定延迟和API四种定时调度策略。
|
||||
* 执行模式丰富:支持单机、广播、Map、MapReduce四种执行模式,其中Map/MapReduce处理器能使开发者寥寥数行代码便获得集群分布式计算的能力。
|
||||
* 执行器支持广泛:支持Spring Bean、普通Java对象、Shell、Python等处理器,应用范围广(比如广播执行+Shell脚本用来清理日志)
|
||||
* 执行器支持广泛:支持Spring Bean、内置/外置Java类、Shell、Python等处理器,应用范围广。
|
||||
* 运维便捷:支持在线日志功能,执行器产生的日志可以在前端控制台页面实时显示,降低debug成本,极大地提高开发效率。
|
||||
* 依赖精简:最小仅依赖关系型数据库(MySQL/Oracle/MS SQLServer...),扩展依赖为MongoDB(用于存储庞大的在线日志)。
|
||||
* 高可用&高性能:调度服务器经过精心设计,一改其他调度框架基于数据库锁的策略,实现了无锁化调度。部署多个调度服务器可以同时实现高可用和性能的提升(支持无限的水平扩展)。
|
||||
@ -26,7 +28,7 @@ bookToc: false
|
||||
## 适用场景
|
||||
|
||||
* 有定时执行需求的业务场景:如每天凌晨全量同步数据、生成业务报表等。
|
||||
* 有需要全部机器一同执行的业务场景:如日志清理。
|
||||
* 有需要全部机器一同执行的业务场景:如使用广播执行模式清理集群日志。
|
||||
* 有需要分布式处理的业务场景:比如需要更新一大批数据,单机执行耗时非常长,可以使用Map/MapReduce处理器完成任务的分发,调动整个集群加速计算。
|
||||
|
||||
## 同类产品对比
|
||||
|
@ -52,7 +52,7 @@ weight: 1
|
||||
|
||||
{{< /hint >}}
|
||||
|
||||
[Docker Hub地址](https://hub.docker.com/r/tjqq/oms-server)
|
||||
[Docker Hub地址](https://hub.docker.com/r/tjqq/oms-server/tags)
|
||||
|
||||
部署流程:
|
||||
|
||||
|
@ -106,6 +106,22 @@ public class OhMySchedulerConfig {
|
||||
|
||||
> agent是一个没有任何业务逻辑的执行器(其实就是为worker加了一个main方法)。
|
||||
|
||||
{{< hint info >}}
|
||||
**推荐直接使用Docker部署:[oms-agent](https://hub.docker.com/r/tjqq/oms-agent/tags)**
|
||||
|
||||
{{< /hint >}}
|
||||
|
||||
与server一样,启动参数通过环境变量`-e PARAMS`传入,全部参数请见底部。
|
||||
|
||||
```shell
|
||||
docker run -d
|
||||
-e PARAMS="--app oms-agent-test --server 192.168.1.1:7700,192.168.1.2:7700"
|
||||
-p 27777:27777 --name my-oms-agent
|
||||
-v ~/docker/my-oms-agent:/root tjqq/oms-agent:$version
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
代码编译方式启动示例:`java -jar oh-my-scheduler-worker-agent-1.2.0.jar -a my-agent`:
|
||||
|
||||
```
|
||||
@ -123,4 +139,3 @@ OhMyScheduler-Worker代理
|
||||
|
||||
```
|
||||
|
||||
Docker镜像:[Docker Hub](https://hub.docker.com/r/tjqq/oms-agent)
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
weight: 1000
|
||||
weight: 3
|
||||
bookFlatSection: false
|
||||
title: "更新日志"
|
||||
title: "版本与升级"
|
||||
---
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 90 KiB |
Binary file not shown.
Before Width: | Height: | Size: 139 KiB |
Binary file not shown.
Before Width: | Height: | Size: 73 KiB |
Binary file not shown.
Before Width: | Height: | Size: 192 KiB |
Binary file not shown.
Before Width: | Height: | Size: 157 KiB |
Binary file not shown.
Before Width: | Height: | Size: 54 KiB |
75
others/script/build_docker.sh
Executable file
75
others/script/build_docker.sh
Executable file
@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
# -p:允许后面跟一个字符串作为提示 -r:保证读入的是原始内容,不会发生任何转义
|
||||
read -r -p "请输入Dockedr镜像版本:" version
|
||||
echo "即将构建的 server 镜像:oms-server:$version"
|
||||
echo "即将构建的 agent 镜像:oms-agent:$version"
|
||||
read -r -p "任意键继续:"
|
||||
|
||||
# 一键部署脚本,请勿挪动脚本
|
||||
cd `dirname $0`/../.. || exit
|
||||
|
||||
read -r -p "是否进行maven构建(y/n):" needmvn
|
||||
if [ "$needmvn" = "y" ] || [ "$needmvn" = "Y" ]; then
|
||||
echo "================== 构建 jar =================="
|
||||
mvn clean package -DskipTests -Pdev -U -e
|
||||
echo "================== 拷贝 jar =================="
|
||||
/bin/cp -rf oh-my-scheduler-server/target/*.jar oh-my-scheduler-server/oms-server.jar
|
||||
/bin/cp -rf oh-my-scheduler-worker-agent/target/*.jar oh-my-scheduler-worker-agent/oms-agent.jar
|
||||
ls -l oh-my-scheduler-server/oms-server.jar
|
||||
ls -l oh-my-scheduler-worker-agent/oms-agent.jar
|
||||
fi
|
||||
|
||||
echo "================== 关闭老应用 =================="
|
||||
docker stop oms-server
|
||||
docker stop oms-agent
|
||||
docker stop oms-agent2
|
||||
echo "================== 删除老容器 =================="
|
||||
docker container rm oms-server
|
||||
docker container rm oms-agent
|
||||
docker container rm oms-agent2
|
||||
read -r -p "是否重新构建镜像(y/n):" rebuild
|
||||
if [ "$rebuild" = "y" ] || [ "$rebuild" = "Y" ]; then
|
||||
echo "================== 删除旧镜像 =================="
|
||||
docker rmi -f tjqq/oms-server:$version
|
||||
docker rmi -f tjqq/oms-agent:$version
|
||||
echo "================== 构建 oms-server 镜像 =================="
|
||||
docker build -t tjqq/oms-server:$version oh-my-scheduler-server/. || exit
|
||||
echo "================== 构建 oms-agent 镜像 =================="
|
||||
docker build -t tjqq/oms-agent:$version oh-my-scheduler-worker-agent/. || exit
|
||||
|
||||
read -r -p "是否正式发布该镜像(y/n):" needrelease
|
||||
if [ "$needrelease" = "y" ] || [ "$needrelease" = "Y" ]; then
|
||||
read -r -p "三思!请确保当前处于已发布的Master分支!(y/n):" needrelease
|
||||
if [ "$needrelease" = "y" ] || [ "$needrelease" = "Y" ]; then
|
||||
echo "================== 正在推送 server 镜像到中央仓库 =================="
|
||||
docker push tjqq/oms-server:$version
|
||||
echo "================== 正在推送 agent 镜像到中央仓库 =================="
|
||||
docker push tjqq/oms-agent:$version
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
read -r -p "是否启动 server & agent(y/n):" startup
|
||||
if [ "$startup" = "y" ] || [ "$startup" = "Y" ]; then
|
||||
# 启动应用(端口映射、数据路径挂载)
|
||||
## -d:后台运行
|
||||
## -p:指定端口映射,主机端口:容器端口
|
||||
## --name:指定容器名称
|
||||
## -v(--volume):挂载目录,宿主机目录:docker内目录,写入docker内路径的数据会被直接写到宿主机上,常用于日志文件
|
||||
## --net=host:容器和宿主机共享网络(容器直接使用宿主机IP,性能最好,但网络隔离较差)
|
||||
echo "================== 准备启动 oms-server =================="
|
||||
docker run -d -e PARAMS="--spring.profiles.active=pre" -p 7700:7700 -p 10086:10086 --name oms-server -v ~/docker/oms-server:/root/oms-server tjqq/oms-server:$version
|
||||
sleep 1
|
||||
# tail -f -n 1000 ~/docker/oms-server/logs/oms-server-application.log
|
||||
|
||||
sleep 30
|
||||
echo "================== 准备启动 oms-client =================="
|
||||
serverIP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' oms-server)
|
||||
serverAddress="$serverIP:7700"
|
||||
echo "使用的Server地址:$serverAddress"
|
||||
docker run -d -e PARAMS="--app oms-agent-test --server $serverAddress" -p 27777:27777 --name oms-agent -v ~/docker/oms-agent:/root tjqq/oms-agent:$version
|
||||
docker run -d -e PARAMS="--app oms-agent-test --server $serverAddress" -p 27778:27777 --name oms-agent2 -v ~/docker/oms-agent2:/root tjqq/oms-agent:$version
|
||||
|
||||
tail -f -n 100 ~/docker/oms-agent/oms/logs/oms-agent-application.log
|
||||
fi
|
@ -1,60 +0,0 @@
|
||||
#!/bin/bash
|
||||
# -p:允许后面跟一个字符串作为提示 -r:保证读入的是原始内容,不会发生任何转义
|
||||
read -r -p "请输入Dockedr镜像版本:" version
|
||||
echo "即将构建的 server 镜像:oms-server:$version"
|
||||
echo "即将构建的 agent 镜像:oms-agent:$version"
|
||||
read -r -p "任意键继续:"
|
||||
|
||||
# 一键部署脚本,请勿挪动脚本
|
||||
cd `dirname $0`/../.. || exit
|
||||
|
||||
read -r -p "是否进行maven构建(y/n):" needmvn
|
||||
if [ "$needmvn" = "y" ] || [ "$needmvn" = "Y" ]; then
|
||||
echo "================== 构建 jar =================="
|
||||
mvn clean package -DskipTests -Pdev -U -e
|
||||
echo "================== 拷贝 jar =================="
|
||||
/bin/cp -rf oh-my-scheduler-server/target/*.jar oh-my-scheduler-server/oms-server.jar
|
||||
/bin/cp -rf oh-my-scheduler-worker-agent/target/*.jar oh-my-scheduler-worker-agent/oms-agent.jar
|
||||
ls -l oh-my-scheduler-server/oms-server.jar
|
||||
ls -l oh-my-scheduler-worker-agent/oms-agent.jar
|
||||
fi
|
||||
|
||||
echo "================== 关闭老应用 =================="
|
||||
docker stop oms-server
|
||||
docker stop oms-agent
|
||||
echo "================== 删除老容器 =================="
|
||||
docker container rm oms-server
|
||||
docker container rm oms-agent
|
||||
echo "================== 删除旧镜像 =================="
|
||||
docker rmi -f tjqq/oms-server:$version
|
||||
docker rmi -f tjqq/oms-agent:$version
|
||||
echo "================== 构建应用镜像 =================="
|
||||
docker build -t tjqq/oms-server:$version oh-my-scheduler-server/. || exit
|
||||
docker build -t tjqq/oms-agent:$version oh-my-scheduler-worker-agent/. || exit
|
||||
echo "================== 准备启动应用 =================="
|
||||
|
||||
read -r -p "是否正式发布该镜像(y/n):" needrelease
|
||||
if [ "$needrelease" = "y" ] || [ "$needrelease" = "Y" ]; then
|
||||
read -r -p "三思!请确保当前处于已发布的Master分支!(y/n):" needrelease
|
||||
if [ "$needrelease" = "y" ] || [ "$needrelease" = "Y" ]; then
|
||||
echo "================== 正在推送 server 镜像到中央仓库 =================="
|
||||
docker push tjqq/oms-server:$version
|
||||
echo "================== 正在推送 agent 镜像到中央仓库 =================="
|
||||
docker push tjqq/oms-agent:$version
|
||||
fi
|
||||
fi
|
||||
|
||||
read -r -p "是否启动 server & agent(y/n):" startup
|
||||
if [ "$startup" = "y" ] || [ "$startup" = "Y" ]; then
|
||||
# 启动应用(端口映射、数据路径挂载)
|
||||
## -d:后台运行
|
||||
## -p:指定端口映射,容器端口:宿主机端口
|
||||
## --name:指定容器名称
|
||||
## -v(--volume):挂载目录,宿主机目录:docker内目录,写入docker内路径的数据会被直接写到宿主机上,常用于日志文件
|
||||
## -net=host:容器和宿主机共享网络(容器直接使用宿主机IP,性能最好,但网络隔离较差)
|
||||
docker run -d -e PARAMS="--spring.profiles.active=product" -p 7700:7700 -p 10086:10086 -p 27777:27777 --name oms-server -v ~/docker/oms-server:/root/oms-server tjqq/oms-server:$version
|
||||
sleep 1
|
||||
tail --pid=$$ -f -n 1000 ~/docker/oms-server/application.log
|
||||
|
||||
docker run -d -e PARAMS="--app oms-agent-test"
|
||||
fi
|
Loading…
x
Reference in New Issue
Block a user