diff --git a/oh-my-scheduler-server/Dockerfile b/oh-my-scheduler-server/Dockerfile index 3221da4a..ed2b6c95 100644 --- a/oh-my-scheduler-server/Dockerfile +++ b/oh-my-scheduler-server/Dockerfile @@ -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 # 挂载数据卷,将文件直接输出到宿主机(注意,此处挂载的是匿名卷,即在宿主机位置随机) diff --git a/oh-my-scheduler-server/src/main/java/com/github/kfcfans/oms/server/web/controller/ContainerController.java b/oh-my-scheduler-server/src/main/java/com/github/kfcfans/oms/server/web/controller/ContainerController.java index 8b8cd9b9..c04f52aa 100644 --- a/oh-my-scheduler-server/src/main/java/com/github/kfcfans/oms/server/web/controller/ContainerController.java +++ b/oh-my-scheduler-server/src/main/java/com/github/kfcfans/oms/server/web/controller/ContainerController.java @@ -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]; diff --git a/oh-my-scheduler-worker-agent/Dockerfile b/oh-my-scheduler-worker-agent/Dockerfile index e7dec374..41903b75 100644 --- a/oh-my-scheduler-worker-agent/Dockerfile +++ b/oh-my-scheduler-worker-agent/Dockerfile @@ -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"] \ No newline at end of file diff --git a/oh-my-scheduler-worker-agent/src/main/java/com/github/kfcfans/oms/worker/MainApplication.java b/oh-my-scheduler-worker-agent/src/main/java/com/github/kfcfans/oms/worker/MainApplication.java index 88e141db..3858dd22 100644 --- a/oh-my-scheduler-worker-agent/src/main/java/com/github/kfcfans/oms/worker/MainApplication.java +++ b/oh-my-scheduler-worker-agent/src/main/java/com/github/kfcfans/oms/worker/MainApplication.java @@ -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; diff --git a/oh-my-scheduler-worker-agent/src/main/resources/logback.xml b/oh-my-scheduler-worker-agent/src/main/resources/logback.xml index 922b32af..a397f659 100644 --- a/oh-my-scheduler-worker-agent/src/main/resources/logback.xml +++ b/oh-my-scheduler-worker-agent/src/main/resources/logback.xml @@ -26,7 +26,7 @@ - ${LOG_PATH}/oms-server-error.log + ${LOG_PATH}/oms-agent-error.log ${LOG_PATH}/oms-agent-error.%d{yyyy-MM-dd}.log 7 @@ -46,7 +46,7 @@ - ${LOG_PATH}/oms-server-application.log + ${LOG_PATH}/oms-agent-application.log ${LOG_PATH}/oms-agent-application.%d{yyyy-MM-dd}.log 7 diff --git a/others/doc/ConsoleGuide.md b/others/doc/ConsoleGuide.md deleted file mode 100644 index 7c05d975..00000000 --- a/others/doc/ConsoleGuide.md +++ /dev/null @@ -1,58 +0,0 @@ -# STEP3: 任务管理 & 运行状态查看 ->通过前端控制台管理调度任务,查看运行情况和结果等。 - -### 系统首页 -> 展示了系统整体的概览和集群Worker列表。 - -![首页](../img/oms-console-main.png) - -### 任务创建 -> 创建需要被调度执行的任务,入口为**主页 -> 任务管理 -> 新建任务**。 - -![任务创建](../img/oms-console-jobCreator.png) -* 任务名称:名称,便于记忆与搜索,无特殊用途,请尽量简短(占用数据库字段空间) -* 任务描述:描述,无特殊作用,请尽量简短(占用数据库字段空间) -* 任务参数:任务处理时能够获取到的参数(即各个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` - * 最大执行机器数量:限定调动执行的机器数量 - -* 报警配置:选择任务执行失败后报警通知的对象,需要事先录入。 - -### 任务管理 ->可以方便地查看和管理系统当前录入的任务信息。 - -![任务管理](../img/oms-console-jobManager.png) - -### 运行状态 ->可以方便地查看当前运行的任务实例,点击详情即可获取详细的信息,点击日志可以查看通过`omsLogger`上报的日志,点击停止则可以强制终止该任务。 - -![运行状态](../img/oms-console-runningStatus.png) - -### 在线日志 - -![在线日志](../img/oms-console-onlineLog.png) \ No newline at end of file diff --git a/others/doc/OpenApiGuide.md b/others/doc/OpenApiGuide.md deleted file mode 100644 index f0b3943e..00000000 --- a/others/doc/OpenApiGuide.md +++ /dev/null @@ -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 - - com.github.kfcfans - oh-my-scheduler-client - ${oms.client.latest.version} - -``` - -### 简单示例 - -```text -// 初始化 client,需要server地址和应用名称作为参数 -OhMyClient ohMyClient = new OhMyClient("127.0.0.1:7700", "oms-test"); -// 调用相关的API -ohMyClient.stopInstance(1586855173043L) -``` - -## 功能列表 -#### 创建/修改任务 -接口签名:`ResultDTO saveJob(ClientJobInfo newJobInfo)` - -入参:任务信息(详细说明见下表,也可以参考[前端任务创建各参数的正确填法](./ConsoleGuide.md)) - -返回值:ResultDTO,根据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 fetchJob(Long jobId)` - -入参:任务ID - -返回值:根据success判断操作是否成功,若请求成功则返回任务的详细信息 - -#### 禁用某个任务 -接口签名:`ResultDTO disableJob(Long jobId)` - -入参:任务ID - -返回值:根据success判断操作是否成功 - -#### 启用某个任务 -接口签名:`ResultDTO enableJob(Long jobId)` - -入参:任务ID - -返回值:根据success判断操作是否成功 - -#### 删除某个任务 -接口签名:`ResultDTO deleteJob(Long jobId)` - -入参:任务ID - -返回值:根据success判断操作是否成功 - -#### 立即运行某个任务 -接口签名:`ResultDTO runJob(Long jobId, String instanceParams)` - -入参:任务ID + **任务实例参数**(Processor#process方法入参`TaskContext`对象的instanceParams字段) - -返回值:根据success判断操作是否成功,操作成功返回对应的任务实例ID(instanceId) - -#### 停止某个任务实例 -接口签名:`ResultDTO stopInstance(Long instanceId)` - -入参:任务实例ID - -返回值:根据success判断操作是否成功 - -#### 查询某个任务实例 -接口签名:`ResultDTO fetchInstanceInfo(Long instanceId)` - -入参:任务实例ID - -返回值:根据success判断操作是否成功,操作成功返回任务实例的详细信息 - -#### 查询某个任务实例的状态 -接口签名:`ResultDTO fetchInstanceStatus(Long instanceId)` - -入参:任务实例ID - -返回值:根据success判断操作是否成功,操作成功返回任务实例的状态码,对应的枚举为:InstanceStatus \ No newline at end of file diff --git a/others/doc/ProcessorDevGuide.md b/others/doc/ProcessorDevGuide.md deleted file mode 100644 index 696aa378..00000000 --- a/others/doc/ProcessorDevGuide.md +++ /dev/null @@ -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 - - com.github.kfcfans - oh-my-scheduler-worker - ${oms.worker.latest.version} - -``` -#### 初始化客户端: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 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 - - ${LOG_PATH}/oms-worker.log - - ${LOG_PATH}/oms-worker.%d{yyyy-MM-dd}.log - 7 - - - %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n - UTF-8 - - true - - - - - -``` -无论如何,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 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 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 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 idList; - } -} -``` - -更多示例请见:[oh-my-scheduler-worker-samples](../../oh-my-scheduler-worker-samples) - diff --git a/others/doc/SystemInitGuide.md b/others/doc/SystemInitGuide.md deleted file mode 100644 index 8a832baa..00000000 --- a/others/doc/SystemInitGuide.md +++ /dev/null @@ -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的系统,都需要先在控制台完成初始化,即应用注册与用户录入。初始化操作在首页完成。 - -![Welcome Page](../img/oms-console-welcome.png) -* 每一个系统初次接入OhMyScheduler时,都需要通过**应用注册**功能录入`appName`(接入应用的名称,需要保证唯一)和`appDescription`(描述信息,无实际用处),至此,应用初始化完成,准备开发处理器(Processor)享受分布式调度和计算的便利之处吧~ -* 注册完成后,输入`appName`即可进入控制台。 -* **用户注册**可录入用户信息,用于之后任务的报警配置。 diff --git a/others/guidance/content/_index.md b/others/guidance/content/_index.md index bc65903b..ae503724 100644 --- a/others/guidance/content/_index.md +++ b/others/guidance/content/_index.md @@ -8,7 +8,9 @@ bookToc: false ## 项目地址 -[GitHub](https://github.com/KFCFans/OhMyScheduler) | [Gitee](https://gitee.com/KFCFans/OhMyScheduler) +GitHub:[![GitHub stars](https://img.shields.io/github/stars/kfcfans/OhMyScheduler?style=social)](https://github.com/KFCFans/OhMyScheduler) [![GitHub forks](https://img.shields.io/github/forks/kfcfans/OhMyScheduler?style=social)](https://github.com/KFCFans/OhMyScheduler) + +Gitee : [![star](https://gitee.com/KFCFans/OhMyScheduler/badge/star.svg?theme=dark)](https://gitee.com/KFCFans/OhMyScheduler) [![fork](https://gitee.com/KFCFans/OhMyScheduler/badge/fork.svg?theme=dark)](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处理器完成任务的分发,调动整个集群加速计算。 ## 同类产品对比 diff --git a/others/guidance/content/docs/startup/1-server-startup.md b/others/guidance/content/docs/startup/1-server-startup.md index 751d0a3d..7c49b872 100644 --- a/others/guidance/content/docs/startup/1-server-startup.md +++ b/others/guidance/content/docs/startup/1-server-startup.md @@ -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) 部署流程: diff --git a/others/guidance/content/docs/startup/2-worker-startup.md b/others/guidance/content/docs/startup/2-worker-startup.md index e641627d..aa57bead 100644 --- a/others/guidance/content/docs/startup/2-worker-startup.md +++ b/others/guidance/content/docs/startup/2-worker-startup.md @@ -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) \ No newline at end of file diff --git a/others/guidance/content/docs/version/_index.md b/others/guidance/content/docs/version/_index.md index 864e95a8..03e2e7df 100644 --- a/others/guidance/content/docs/version/_index.md +++ b/others/guidance/content/docs/version/_index.md @@ -1,6 +1,6 @@ --- -weight: 1000 +weight: 3 bookFlatSection: false -title: "更新日志" +title: "版本与升级" --- diff --git a/others/img/oms-console-jobCreator.png b/others/img/oms-console-jobCreator.png deleted file mode 100644 index 29a883db..00000000 Binary files a/others/img/oms-console-jobCreator.png and /dev/null differ diff --git a/others/img/oms-console-jobManager.png b/others/img/oms-console-jobManager.png deleted file mode 100644 index d902898f..00000000 Binary files a/others/img/oms-console-jobManager.png and /dev/null differ diff --git a/others/img/oms-console-main.png b/others/img/oms-console-main.png deleted file mode 100644 index fcb7a784..00000000 Binary files a/others/img/oms-console-main.png and /dev/null differ diff --git a/others/img/oms-console-onlineLog.png b/others/img/oms-console-onlineLog.png deleted file mode 100644 index 9cbf7c84..00000000 Binary files a/others/img/oms-console-onlineLog.png and /dev/null differ diff --git a/others/img/oms-console-runningStatus.png b/others/img/oms-console-runningStatus.png deleted file mode 100644 index eb0d8350..00000000 Binary files a/others/img/oms-console-runningStatus.png and /dev/null differ diff --git a/others/img/oms-console-welcome.png b/others/img/oms-console-welcome.png deleted file mode 100644 index fde4396c..00000000 Binary files a/others/img/oms-console-welcome.png and /dev/null differ diff --git a/others/script/build_docker.sh b/others/script/build_docker.sh new file mode 100755 index 00000000..7bd954a1 --- /dev/null +++ b/others/script/build_docker.sh @@ -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 \ No newline at end of file diff --git a/others/script/build_server_docker.sh b/others/script/build_server_docker.sh deleted file mode 100755 index af48b7c2..00000000 --- a/others/script/build_server_docker.sh +++ /dev/null @@ -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 \ No newline at end of file