[fix] fix the hugo 404 in gitee pages
@ -1,5 +1,6 @@
|
|||||||
package com.github.kfcfans.oms.worker;
|
package com.github.kfcfans.oms.worker;
|
||||||
|
|
||||||
|
import com.github.kfcfans.oms.common.RemoteConstant;
|
||||||
import com.github.kfcfans.oms.worker.common.OhMyConfig;
|
import com.github.kfcfans.oms.worker.common.OhMyConfig;
|
||||||
import com.github.kfcfans.oms.worker.common.constants.StoreStrategy;
|
import com.github.kfcfans.oms.worker.common.constants.StoreStrategy;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
@ -22,7 +23,10 @@ public class MainApplication implements Runnable {
|
|||||||
@Option(names = {"-a", "--app"}, description = "worker-agent名称,可通过调度中心控制台创建", required = true)
|
@Option(names = {"-a", "--app"}, description = "worker-agent名称,可通过调度中心控制台创建", required = true)
|
||||||
private String appName;
|
private String appName;
|
||||||
|
|
||||||
@Option(names = {"-p", "--persistence"}, description = "存储策略,枚举值,DISK 或 MEMORY")
|
@Option(names = {"-p", "--port"}, description = "worker-agent的ActorSystem监听端口,不建议更改")
|
||||||
|
private Integer port = RemoteConstant.DEFAULT_WORKER_PORT;
|
||||||
|
|
||||||
|
@Option(names = {"-e", "--persistence"}, description = "存储策略,枚举值,DISK 或 MEMORY")
|
||||||
private String storeStrategy = "DISK";
|
private String storeStrategy = "DISK";
|
||||||
|
|
||||||
@Option(names = {"-s", "--server"}, description = "调度中心地址,多值英文逗号分隔,格式 IP:Port OR domain")
|
@Option(names = {"-s", "--server"}, description = "调度中心地址,多值英文逗号分隔,格式 IP:Port OR domain")
|
||||||
@ -43,6 +47,7 @@ public class MainApplication implements Runnable {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
cfg.setAppName(appName);
|
cfg.setAppName(appName);
|
||||||
|
cfg.setPort(port);
|
||||||
cfg.setServerAddress(Splitter.on(",").splitToList(server));
|
cfg.setServerAddress(Splitter.on(",").splitToList(server));
|
||||||
cfg.setStoreStrategy(StoreStrategy.MEMORY.name().equals(storeStrategy) ? StoreStrategy.MEMORY : StoreStrategy.DISK);
|
cfg.setStoreStrategy(StoreStrategy.MEMORY.name().equals(storeStrategy) ? StoreStrategy.MEMORY : StoreStrategy.DISK);
|
||||||
cfg.setMaxResultLength(length);
|
cfg.setMaxResultLength(length);
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.github.kfcfans.oms.samples.mr;
|
||||||
|
|
||||||
|
import com.github.kfcfans.oms.worker.core.processor.ProcessResult;
|
||||||
|
import com.github.kfcfans.oms.worker.core.processor.TaskContext;
|
||||||
|
import com.github.kfcfans.oms.worker.core.processor.TaskResult;
|
||||||
|
import com.github.kfcfans.oms.worker.core.processor.sdk.MapReduceProcessor;
|
||||||
|
import com.github.kfcfans.oms.worker.log.OmsLogger;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MapReduce 模拟 静态分片
|
||||||
|
* 典型的杀鸡焉用牛刀~
|
||||||
|
*
|
||||||
|
* @author tjq
|
||||||
|
* @since 2020/5/21
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class StaticSliceProcessor extends MapReduceProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessResult process(TaskContext context) throws Exception {
|
||||||
|
OmsLogger omsLogger = context.getOmsLogger();
|
||||||
|
|
||||||
|
// root task 负责分发任务
|
||||||
|
if (isRootTask()) {
|
||||||
|
// 从控制台传递分片参数,架设格式为KV:1=a&2=b&3=c
|
||||||
|
String jobParams = context.getJobParams();
|
||||||
|
Map<String, String> paramsMap = Splitter.on("&").withKeyValueSeparator("=").split(jobParams);
|
||||||
|
|
||||||
|
List<SubTask> subTasks = Lists.newLinkedList();
|
||||||
|
paramsMap.forEach((k, v) -> subTasks.add(new SubTask(Integer.parseInt(k), v)));
|
||||||
|
return map(subTasks, "SLICE_TASK");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object subTask = context.getSubTask();
|
||||||
|
if (subTask instanceof SubTask) {
|
||||||
|
// 实际处理
|
||||||
|
// 当然,如果觉得 subTask 还是很大,也可以继续分发哦
|
||||||
|
|
||||||
|
return new ProcessResult(true, "subTask:" + ((SubTask) subTask).getIndex() + " process successfully");
|
||||||
|
}
|
||||||
|
return new ProcessResult(false, "UNKNOWN BUG");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessResult reduce(TaskContext context, List<TaskResult> taskResults) {
|
||||||
|
// 按需求做一些统计工作... 不需要的话,直接使用 Map 处理器即可
|
||||||
|
return new ProcessResult(true, "xxxx");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
private static class SubTask {
|
||||||
|
private int index;
|
||||||
|
private String params;
|
||||||
|
}
|
||||||
|
}
|
@ -97,6 +97,7 @@ TaskContext为处理的入参,包含了本次处理的上下文信息,具体
|
|||||||
|
|
||||||
|属性名称|意义/用法|
|
|属性名称|意义/用法|
|
||||||
|----|----|
|
|----|----|
|
||||||
|
|jobId|任务ID,开发者一般无需关心此参数|
|
||||||
|instanceId|任务实例ID,全局唯一,开发者一般无需关心此参数|
|
|instanceId|任务实例ID,全局唯一,开发者一般无需关心此参数|
|
||||||
|subInstanceId|子任务实例ID,秒级任务使用,开发者一般无需关心此参数|
|
|subInstanceId|子任务实例ID,秒级任务使用,开发者一般无需关心此参数|
|
||||||
|taskId|采用链式命名法的ID,在某个任务实例内唯一,开发者一般无需关心此参数|
|
|taskId|采用链式命名法的ID,在某个任务实例内唯一,开发者一般无需关心此参数|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
baseURL = "https://kfcfans.gitee.io/ohmyscheduler"
|
baseURL = "https://kfcfans.gitee.io"
|
||||||
languageCode = "en-us"
|
languageCode = "en-us"
|
||||||
title = "OhMyScheduler"
|
title = "OhMyScheduler"
|
||||||
theme = "book"
|
theme = "book"
|
||||||
|
@ -4,7 +4,7 @@ type: docs
|
|||||||
bookToc: false
|
bookToc: false
|
||||||
---
|
---
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 项目地址
|
## 项目地址
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
bookFlatSection: true
|
|
||||||
---
|
|
@ -1,45 +0,0 @@
|
|||||||
# Columns
|
|
||||||
|
|
||||||
Columns help organize shorter pieces of content horizontally for readability.
|
|
||||||
|
|
||||||
|
|
||||||
```html
|
|
||||||
{{</* columns */>}} <!-- begin columns block -->
|
|
||||||
# Left Content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
|
|
||||||
<---> <!-- magic sparator, between columns -->
|
|
||||||
|
|
||||||
# Mid Content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
|
|
||||||
<---> <!-- magic sparator, between columns -->
|
|
||||||
|
|
||||||
# Right Content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
{{</* /columns */>}}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
{{< columns >}}
|
|
||||||
## Left Content
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
|
|
||||||
Miseratus fonte Ditis conubia.
|
|
||||||
|
|
||||||
<--->
|
|
||||||
|
|
||||||
## Mid Content
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter!
|
|
||||||
|
|
||||||
<--->
|
|
||||||
|
|
||||||
## Right Content
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
|
|
||||||
Miseratus fonte Ditis conubia.
|
|
||||||
{{< /columns >}}
|
|
@ -1,22 +0,0 @@
|
|||||||
# Details
|
|
||||||
|
|
||||||
Details shortcode is a helper for `details` html5 element. It is going to replace `expand` shortcode.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
```tpl
|
|
||||||
{{</* details "Title" [open] */>}}
|
|
||||||
## Markdown content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
{{</* /details */>}}
|
|
||||||
```
|
|
||||||
```tpl
|
|
||||||
{{</* details title="Title" open=true */>}}
|
|
||||||
## Markdown content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
{{</* /details */>}}
|
|
||||||
```
|
|
||||||
|
|
||||||
{{< details "Title" open >}}
|
|
||||||
## Markdown content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
{{< /details >}}
|
|
@ -1,35 +0,0 @@
|
|||||||
# Expand
|
|
||||||
|
|
||||||
Expand shortcode can help to decrease clutter on screen by hiding part of text. Expand content by clicking on it.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
### Default
|
|
||||||
|
|
||||||
```tpl
|
|
||||||
{{</* expand */>}}
|
|
||||||
## Markdown content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
{{</* /expand */>}}
|
|
||||||
```
|
|
||||||
|
|
||||||
{{< expand >}}
|
|
||||||
## Markdown content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
{{< /expand >}}
|
|
||||||
|
|
||||||
### With Custom Label
|
|
||||||
|
|
||||||
```tpl
|
|
||||||
{{</* expand "Custom Label" "..." */>}}
|
|
||||||
## Markdown content
|
|
||||||
Lorem markdownum insigne...
|
|
||||||
{{</* /expand */>}}
|
|
||||||
```
|
|
||||||
|
|
||||||
{{< expand "Custom Label" "..." >}}
|
|
||||||
## Markdown content
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
|
|
||||||
Miseratus fonte Ditis conubia.
|
|
||||||
{{< /expand >}}
|
|
@ -1,32 +0,0 @@
|
|||||||
# Hints
|
|
||||||
|
|
||||||
Hint shortcode can be used as hint/alerts/notification block.
|
|
||||||
There are 3 colors to choose: `info`, `warning` and `danger`.
|
|
||||||
|
|
||||||
```tpl
|
|
||||||
{{</* hint [info|warning|danger] */>}}
|
|
||||||
**Markdown content**
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
{{</* /hint */>}}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
{{< hint info >}}
|
|
||||||
**Markdown content**
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
{{< /hint >}}
|
|
||||||
|
|
||||||
{{< hint warning >}}
|
|
||||||
**Markdown content**
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
{{< /hint >}}
|
|
||||||
|
|
||||||
{{< hint danger >}}
|
|
||||||
**Markdown content**
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
{{< /hint >}}
|
|
@ -1,28 +0,0 @@
|
|||||||
# KaTeX
|
|
||||||
|
|
||||||
KaTeX shortcode let you render math typesetting in markdown document. See [KaTeX](https://katex.org/)
|
|
||||||
|
|
||||||
## Example
|
|
||||||
{{< columns >}}
|
|
||||||
|
|
||||||
```latex
|
|
||||||
{{</* katex [display] [class="text-center"] */>}}
|
|
||||||
f(x) = \int_{-\infty}^\infty\hat f(\xi)\,e^{2 \pi i \xi x}\,d\xi
|
|
||||||
{{</* /katex */>}}
|
|
||||||
```
|
|
||||||
|
|
||||||
<--->
|
|
||||||
|
|
||||||
{{< katex display >}}
|
|
||||||
f(x) = \int_{-\infty}^\infty\hat f(\xi)\,e^{2 \pi i \xi x}\,d\xi
|
|
||||||
{{< /katex >}}
|
|
||||||
|
|
||||||
{{< /columns >}}
|
|
||||||
|
|
||||||
## Display Mode Example
|
|
||||||
|
|
||||||
Here is some inline example: {{< katex >}}\pi(x){{< /katex >}}, rendered in the same line. And below is `display` example, having `display: block`
|
|
||||||
{{< katex display >}}
|
|
||||||
f(x) = \int_{-\infty}^\infty\hat f(\xi)\,e^{2 \pi i \xi x}\,d\xi
|
|
||||||
{{< /katex >}}
|
|
||||||
Text continues here.
|
|
@ -1,38 +0,0 @@
|
|||||||
# Mermaid Chart
|
|
||||||
|
|
||||||
[Mermaid](https://mermaidjs.github.io/) is library for generating svg charts and diagrams from text.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
{{< columns >}}
|
|
||||||
```tpl
|
|
||||||
{{</* mermaid [class="text-center"]*/>}}
|
|
||||||
sequenceDiagram
|
|
||||||
Alice->>Bob: Hello Bob, how are you?
|
|
||||||
alt is sick
|
|
||||||
Bob->>Alice: Not so good :(
|
|
||||||
else is well
|
|
||||||
Bob->>Alice: Feeling fresh like a daisy
|
|
||||||
end
|
|
||||||
opt Extra response
|
|
||||||
Bob->>Alice: Thanks for asking
|
|
||||||
end
|
|
||||||
{{</* /mermaid */>}}
|
|
||||||
```
|
|
||||||
|
|
||||||
<--->
|
|
||||||
|
|
||||||
{{< mermaid >}}
|
|
||||||
sequenceDiagram
|
|
||||||
Alice->>Bob: Hello Bob, how are you?
|
|
||||||
alt is sick
|
|
||||||
Bob->>Alice: Not so good :(
|
|
||||||
else is well
|
|
||||||
Bob->>Alice: Feeling fresh like a daisy
|
|
||||||
end
|
|
||||||
opt Extra response
|
|
||||||
Bob->>Alice: Thanks for asking
|
|
||||||
end
|
|
||||||
{{< /mermaid >}}
|
|
||||||
|
|
||||||
{{< /columns >}}
|
|
@ -1,50 +0,0 @@
|
|||||||
# Tabs
|
|
||||||
|
|
||||||
Tabs let you organize content by context, for example installation instructions for each supported platform.
|
|
||||||
|
|
||||||
```tpl
|
|
||||||
{{</* tabs "uniqueid" */>}}
|
|
||||||
{{</* tab "MacOS" */>}} # MacOS Content {{</* /tab */>}}
|
|
||||||
{{</* tab "Linux" */>}} # Linux Content {{</* /tab */>}}
|
|
||||||
{{</* tab "Windows" */>}} # Windows Content {{</* /tab */>}}
|
|
||||||
{{</* /tabs */>}}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
{{< tabs "uniqueid" >}}
|
|
||||||
{{< tab "MacOS" >}}
|
|
||||||
# MacOS
|
|
||||||
|
|
||||||
This is tab **MacOS** content.
|
|
||||||
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
|
|
||||||
Miseratus fonte Ditis conubia.
|
|
||||||
{{< /tab >}}
|
|
||||||
|
|
||||||
{{< tab "Linux" >}}
|
|
||||||
|
|
||||||
# Linux
|
|
||||||
|
|
||||||
This is tab **Linux** content.
|
|
||||||
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
|
|
||||||
Miseratus fonte Ditis conubia.
|
|
||||||
{{< /tab >}}
|
|
||||||
|
|
||||||
{{< tab "Windows" >}}
|
|
||||||
|
|
||||||
# Windows
|
|
||||||
|
|
||||||
This is tab **Windows** content.
|
|
||||||
|
|
||||||
Lorem markdownum insigne. Olympo signis Delphis! Retexi Nereius nova develat
|
|
||||||
stringit, frustra Saturnius uteroque inter! Oculis non ritibus Telethusa
|
|
||||||
protulit, sed sed aere valvis inhaesuro Pallas animam: qui _quid_, ignes.
|
|
||||||
Miseratus fonte Ditis conubia.
|
|
||||||
{{< /tab >}}
|
|
||||||
{{< /tabs >}}
|
|
@ -47,7 +47,10 @@ weight: 1
|
|||||||
|
|
||||||
## 部署调度服务器—Docker
|
## 部署调度服务器—Docker
|
||||||
|
|
||||||
> **建议自己根据项目中的Dockerfile稍作修改,制作自己的Docker镜像,而不是直接使用官方镜像**!原因在于:容器功能需要用到Git和Maven来编译代码库,而公司内部往往都会搭建自己的私有仓库,所以Git容器功能没办法正常运行(即,**官方镜像中的调度服务器不支持Git容器的部署**)。
|
{{< hint warning >}}
|
||||||
|
**建议自己根据项目中的Dockerfile稍作修改,制作自己的Docker镜像,而不是直接使用官方镜像**!原因在于:容器功能需要用到Git和Maven来编译代码库,而公司内部往往都会搭建自己的私有仓库,所以Git容器功能没办法正常运行(即,**官方镜像中的调度服务器不支持Git容器的部署**)。
|
||||||
|
|
||||||
|
{{< /hint >}}
|
||||||
|
|
||||||
[Docker Hub地址](https://hub.docker.com/r/tjqq/oms-server)
|
[Docker Hub地址](https://hub.docker.com/r/tjqq/oms-server)
|
||||||
|
|
||||||
@ -74,7 +77,7 @@ docker run -d
|
|||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
**特别鸣谢**:感谢[某知名上市电商公司前端](https://github.com/fengnan0929)对本项目的大力支持!
|
**特别鸣谢**:感谢[某知名上市电商公司前端开发者](https://github.com/fengnan0929)对本项目的大力支持!
|
||||||
|
|
||||||
## 初始化应用分组
|
## 初始化应用分组
|
||||||
|
|
||||||
|
@ -7,16 +7,6 @@ weight: 2
|
|||||||
|
|
||||||
> 宿主应用即原有的业务应用,假如需要调度执行的任务与当前业务有较为紧密的联系,建议采取该方式。
|
> 宿主应用即原有的业务应用,假如需要调度执行的任务与当前业务有较为紧密的联系,建议采取该方式。
|
||||||
|
|
||||||
> OhMyScheduler当前支持Shell、Python等脚本处理器和Java处理器。脚本处理器只需要开发者完成脚本的编写(xxx.sh / xxx.py),在控制台填入脚本内容即可,本章不再赘述。本章将重点阐述Java处理器开发方法与使用技巧。
|
|
||||||
|
|
||||||
* Java处理器可根据**代码所处位置**划分为内置Java处理器和容器Java处理器,前者直接集成在宿主应用(也就是接入本系统的业务应用)中,一般用来处理业务需求;后者可以在一个独立的轻量级的Java工程中开发,通过**容器技术**(详见容器章节)被worker集群热加载,提供Java的“脚本能力”,一般用于处理灵活多变的需求。
|
|
||||||
* Java处理器可根据**对象创建者**划分为SpringBean处理器和普通Java对象处理器,前者由Spring IOC容器完成处理器的创建和初始化,后者则有OhMyScheduler维护其状态。如果宿主应用支持Spring,**强烈建议使用SpringBean处理器**,开发者仅需要将Processor注册进Spring IOC容器(一个`@Component`注解或一句`bean`配置)。
|
|
||||||
* Java处理器可根据**功能**划分为单机处理器、广播处理器、Map处理器和MapReduce处理器。
|
|
||||||
* 单机处理器对应了单机任务,即某个任务的某次运行只会有某一台机器的某一个线程参与运算。
|
|
||||||
* 广播处理器对应了广播任务,即某个任务的某次运行会**调动集群内所有机器参与运算**。
|
|
||||||
* Map处理器对应了Map任务,即某个任务在运行过程中,**允许产生子任务并分发到其他机器进行运算**。
|
|
||||||
* MapReduce处理器对应了MapReduce任务,在Map任务的基础上,**增加了所有任务结束后的汇总统计**。
|
|
||||||
|
|
||||||
首先,添加相关的jar包依赖,最新依赖版本请参考maven中央仓库:[推荐地址](https://search.maven.org/search?q=oh-my-scheduler-worker)&[备用地址](https://mvnrepository.com/search?q=com.github.kfcfans)
|
首先,添加相关的jar包依赖,最新依赖版本请参考maven中央仓库:[推荐地址](https://search.maven.org/search?q=oh-my-scheduler-worker)&[备用地址](https://mvnrepository.com/search?q=com.github.kfcfans)
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
@ -68,21 +58,66 @@ public class OhMySchedulerConfig {
|
|||||||
|
|
||||||
非Spring应用程序在创建`OhMyWorker`对象后手动调用`ohMyWorker.init()`方法完成初始化即可。
|
非Spring应用程序在创建`OhMyWorker`对象后手动调用`ohMyWorker.init()`方法完成初始化即可。
|
||||||
|
|
||||||
#### 基于agent的执行器初始化
|
***
|
||||||
|
|
||||||
|
**OhMyScheduler日志单独配置**
|
||||||
|
|
||||||
|
目前,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来判断日志配置是否成功(emmm...Markdown显示似乎有点丑,实际上超帅的呢~):
|
||||||
|
|
||||||
|
```text
|
||||||
|
███████ ██ ████ ████ ████████ ██ ██ ██
|
||||||
|
██░░░░░██ ░██ ░██░██ ██░██ ██ ██ ██░░░░░░ ░██ ░██ ░██
|
||||||
|
██ ░░██░██ ░██░░██ ██ ░██ ░░██ ██ ░██ █████ ░██ █████ ░██ ██ ██ ░██ █████ ██████
|
||||||
|
░██ ░██░██████ ░██ ░░███ ░██ ░░███ ░█████████ ██░░░██░██████ ██░░░██ ██████░██ ░██ ░██ ██░░░██░░██░░█
|
||||||
|
░██ ░██░██░░░██░██ ░░█ ░██ ░██ ░░░░░░░░██░██ ░░ ░██░░░██░███████ ██░░░██░██ ░██ ░██░███████ ░██ ░
|
||||||
|
░░██ ██ ░██ ░██░██ ░ ░██ ██ ░██░██ ██░██ ░██░██░░░░ ░██ ░██░██ ░██ ░██░██░░░░ ░██
|
||||||
|
░░███████ ░██ ░██░██ ░██ ██ ████████ ░░█████ ░██ ░██░░██████░░██████░░██████ ███░░██████░███
|
||||||
|
░░░░░░░ ░░ ░░ ░░ ░░ ░░ ░░░░░░░░ ░░░░░ ░░ ░░ ░░░░░░ ░░░░░░ ░░░░░░ ░░░ ░░░░░░ ░░░
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 基于agent的执行器初始化
|
||||||
|
|
||||||
> agent是一个没有任何业务逻辑的执行器(其实就是为worker加了一个main方法)。
|
> agent是一个没有任何业务逻辑的执行器(其实就是为worker加了一个main方法)。
|
||||||
|
|
||||||
代码编译方式启动示例:`java -jar oh-my-scheduler-worker-agent-1.2.0.jar -a my-agent`:
|
代码编译方式启动示例:`java -jar oh-my-scheduler-worker-agent-1.2.0.jar -a my-agent`:
|
||||||
|
|
||||||
```
|
```
|
||||||
Usage: OhMyAgent [-hV] -a=<appName> [-l=<length>] [-p=<storeStrategy>]
|
Usage: OhMyAgent [-hV] -a=<appName> [-e=<storeStrategy>] [-l=<length>]
|
||||||
[-s=<server>]
|
[-p=<port>] [-s=<server>]
|
||||||
OhMyScheduler-Worker代理
|
OhMyScheduler-Worker代理
|
||||||
-a, --app=<appName> worker-agent名称,可通过调度中心控制台创建
|
-a, --app=<appName> worker-agent名称,可通过调度中心控制台创建
|
||||||
|
-e, --persistence=<storeStrategy>
|
||||||
|
存储策略,枚举值,DISK 或 MEMORY
|
||||||
-h, --help Show this help message and exit.
|
-h, --help Show this help message and exit.
|
||||||
-l, --length=<length> 返回值最大长度
|
-l, --length=<length> 返回值最大长度
|
||||||
-p, --persistence=<storeStrategy>
|
-p, --port=<port> worker-agent的ActorSystem监听端口,不建议更改
|
||||||
存储策略,枚举值,DISK 或 MEMORY
|
|
||||||
-s, --server=<server> 调度中心地址,多值英文逗号分隔,格式 IP:Port OR domain
|
-s, --server=<server> 调度中心地址,多值英文逗号分隔,格式 IP:Port OR domain
|
||||||
-V, --version Print version information and exit.
|
-V, --version Print version information and exit.
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: 处理器编写
|
title: 处理器开发
|
||||||
weight: 3
|
weight: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -10,22 +10,270 @@ weight: 3
|
|||||||
* Java处理器可根据**代码所处位置**划分为内置Java处理器和容器Java处理器,前者直接集成在宿主应用(也就是接入本系统的业务应用)中,一般用来处理业务需求;后者可以在一个独立的轻量级的Java工程中开发,通过**容器技术**(详见容器章节)被worker集群热加载,提供Java的“脚本能力”,一般用于处理灵活多变的需求。
|
* Java处理器可根据**代码所处位置**划分为内置Java处理器和容器Java处理器,前者直接集成在宿主应用(也就是接入本系统的业务应用)中,一般用来处理业务需求;后者可以在一个独立的轻量级的Java工程中开发,通过**容器技术**(详见容器章节)被worker集群热加载,提供Java的“脚本能力”,一般用于处理灵活多变的需求。
|
||||||
* Java处理器可根据**对象创建者**划分为SpringBean处理器和普通Java对象处理器,前者由Spring IOC容器完成处理器的创建和初始化,后者则有OhMyScheduler维护其状态。如果宿主应用支持Spring,**强烈建议使用SpringBean处理器**,开发者仅需要将Processor注册进Spring IOC容器(一个`@Component`注解或一句`bean`配置)。
|
* Java处理器可根据**对象创建者**划分为SpringBean处理器和普通Java对象处理器,前者由Spring IOC容器完成处理器的创建和初始化,后者则有OhMyScheduler维护其状态。如果宿主应用支持Spring,**强烈建议使用SpringBean处理器**,开发者仅需要将Processor注册进Spring IOC容器(一个`@Component`注解或一句`bean`配置)。
|
||||||
* Java处理器可根据**功能**划分为单机处理器、广播处理器、Map处理器和MapReduce处理器。
|
* Java处理器可根据**功能**划分为单机处理器、广播处理器、Map处理器和MapReduce处理器。
|
||||||
* 单机处理器对应了单机任务,即某个任务的某次运行只会有某一台机器的某一个线程参与运算。
|
* 单机处理器(`BasicProcessor`)对应了单机任务,即某个任务的某次运行只会有某一台机器的某一个线程参与运算。
|
||||||
* 广播处理器对应了广播任务,即某个任务的某次运行会**调动集群内所有机器参与运算**。
|
* 广播处理器(`BroadcastProcessor`)对应了广播任务,即某个任务的某次运行会**调动集群内所有机器参与运算**。
|
||||||
* Map处理器对应了Map任务,即某个任务在运行过程中,**允许产生子任务并分发到其他机器进行运算**。
|
* Map处理器(`MapProcessor`)对应了Map任务,即某个任务在运行过程中,**允许产生子任务并分发到其他机器进行运算**。
|
||||||
* MapReduce处理器对应了MapReduce任务,在Map任务的基础上,**增加了所有任务结束后的汇总统计**。
|
* MapReduce处理器(`MapReduceProcessor`)对应了MapReduce任务,在Map任务的基础上,**增加了所有任务结束后的汇总统计**。
|
||||||
|
|
||||||
## 初始化宿主应用
|
## 核心方法:process
|
||||||
|
|
||||||
首先,添加相关的jar包依赖,最新依赖版本请参考maven中央仓库:[推荐地址](https://search.maven.org/search?q=oh-my-scheduler-worker)&[备用地址](https://mvnrepository.com/search?q=com.github.kfcfans)
|
任意Java处理器都需要实现处理的核心方法,其接口签名如下:
|
||||||
|
|
||||||
```xml
|
```java
|
||||||
<dependency>
|
ProcessResult process(TaskContext context) throws Exception;
|
||||||
<groupId>com.github.kfcfans</groupId>
|
|
||||||
<artifactId>oh-my-scheduler-worker</artifactId>
|
|
||||||
<version>1.2.0</version>
|
|
||||||
</dependency>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
方法入参`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造成巨大的压力 |
|
||||||
|
|
||||||
|
方法的返回值为`ProcessResult`,代表了本次Task执行的结果,包含`success`和`msg`两个属性,分别用于传递Task是否执行成功和Task需要返回的信息。
|
||||||
|
|
||||||
|
## 单机处理器:BasicProcessor
|
||||||
|
|
||||||
|
单机执行的策略下,server会在所有可用worker中选取健康度最佳的机器进行执行。单机执行任务需要实现接口:`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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 广播处理器:BroadcastProcessor
|
||||||
|
|
||||||
|
广播执行的策略下,所有机器都会被调度执行该任务。为了便于资源的准备和释放,广播处理器在`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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 并行处理器:MapReduceProcessor
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
注:Map处理器相当于MapReduce处理器的阉割版本(阉割了`reduce`方法),此处不再单独举例。
|
||||||
|
|
||||||
|
## 最佳实践:MapReduce实现静态分片
|
||||||
|
|
||||||
|
虽然说这有点傻鸡焉用牛刀的感觉,不过既然目前市场上同类产品都处于静态分片的阶段,我也就在这里给大家举个例子吧~
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Component
|
||||||
|
public class StaticSliceProcessor extends MapReduceProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessResult process(TaskContext context) throws Exception {
|
||||||
|
OmsLogger omsLogger = context.getOmsLogger();
|
||||||
|
|
||||||
|
// root task 负责分发任务
|
||||||
|
if (isRootTask()) {
|
||||||
|
// 从控制台传递分片参数,架设格式为KV:1=a&2=b&3=c
|
||||||
|
String jobParams = context.getJobParams();
|
||||||
|
Map<String, String> paramsMap = Splitter.on("&").withKeyValueSeparator("=").split(jobParams);
|
||||||
|
|
||||||
|
List<SubTask> subTasks = Lists.newLinkedList();
|
||||||
|
paramsMap.forEach((k, v) -> subTasks.add(new SubTask(Integer.parseInt(k), v)));
|
||||||
|
return map(subTasks, "SLICE_TASK");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object subTask = context.getSubTask();
|
||||||
|
if (subTask instanceof SubTask) {
|
||||||
|
// 实际处理
|
||||||
|
// 当然,如果觉得 subTask 还是很大,也可以继续分发哦
|
||||||
|
|
||||||
|
return new ProcessResult(true, "subTask:" + ((SubTask) subTask).getIndex() + " process successfully");
|
||||||
|
}
|
||||||
|
return new ProcessResult(false, "UNKNOWN BUG");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessResult reduce(TaskContext context, List<TaskResult> taskResults) {
|
||||||
|
// 按需求做一些统计工作... 不需要的话,直接使用 Map 处理器即可
|
||||||
|
return new ProcessResult(true, "xxxx");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
private static class SubTask {
|
||||||
|
private int index;
|
||||||
|
private String params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 最佳实践:MapReduce多级分发处理
|
||||||
|
|
||||||
|
利用MapReduce实现 Root -> A -> B/C -> Reduce)的DAG 工作流。
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Component
|
||||||
|
public class DAGSimulationProcessor extends MapReduceProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessResult process(TaskContext context) throws Exception {
|
||||||
|
|
||||||
|
if (isRootTask()) {
|
||||||
|
// L1. 执行根任务
|
||||||
|
|
||||||
|
// 执行完毕后产生子任务 A,需要传递的参数可以作为 TaskA 的属性进行传递
|
||||||
|
TaskA taskA = new TaskA();
|
||||||
|
return map(Lists.newArrayList(taskA), "LEVEL1_TASK_A");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.getSubTask() instanceof TaskA) {
|
||||||
|
// L2. 执行A任务
|
||||||
|
|
||||||
|
// 执行完成后产生子任务 B,C(并行执行)
|
||||||
|
TaskB taskB = new TaskB();
|
||||||
|
TaskC taskC = new TaskC();
|
||||||
|
return map(Lists.newArrayList(taskB, taskC), "LEVEL2_TASK_BC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.getSubTask() instanceof TaskB) {
|
||||||
|
// L3. 执行B任务
|
||||||
|
return new ProcessResult(true, "xxx");
|
||||||
|
}
|
||||||
|
if (context.getSubTask() instanceof TaskC) {
|
||||||
|
// L3. 执行C任务
|
||||||
|
return new ProcessResult(true, "xxx");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ProcessResult(false, "UNKNOWN_TYPE_OF_SUB_TASK");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessResult reduce(TaskContext context, List<TaskResult> taskResults) {
|
||||||
|
// L4. 执行最终 Reduce 任务,taskResults保存了之前所有任务的结果
|
||||||
|
taskResults.forEach(taskResult -> {
|
||||||
|
// do something...
|
||||||
|
});
|
||||||
|
return new ProcessResult(true, "reduce success");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TaskA {
|
||||||
|
}
|
||||||
|
private static class TaskB {
|
||||||
|
}
|
||||||
|
private static class TaskC {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 更多示例
|
||||||
|
|
||||||
|
没看够?更多示例请见:[oh-my-scheduler-worker-samples](https://github.com/KFCFans/OhMyScheduler/tree/master/oh-my-scheduler-worker-samples)
|
||||||
|
|
||||||
|
73
others/guidance/content/docs/startup/4-console-guide.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
---
|
||||||
|
title: 任务管理与在线运维
|
||||||
|
type: docs
|
||||||
|
weight: 4
|
||||||
|
---
|
||||||
|
|
||||||
|
{{< hint info >}}
|
||||||
|
前端控制台允许开发者可视化地进行任务增、删、改、查等管理操作,同时也能直观地看到任务的运行数据,包括运行状态、详情和在线日志等。以下为对控制台的详细介绍:
|
||||||
|
|
||||||
|
{{< /hint >}}
|
||||||
|
|
||||||
|
## 主页
|
||||||
|
|
||||||
|
展示了系统整体的概览和集群Worker列表。
|
||||||
|
|
||||||
|

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

|
||||||
|
* 任务名称:名称,便于记忆与搜索,无特殊用途,请尽量简短(占用数据库字段空间)
|
||||||
|
* 任务描述:描述,无特殊作用,请尽量简短(占用数据库字段空间)
|
||||||
|
* 任务参数:任务处理时能够获取到的参数(即各个Processor的process方法入参`TaskContext`对象的jobParams字段)(进行一次处理器开发就能理解了)
|
||||||
|
* 定时信息:由下拉框和输入框组成
|
||||||
|
* API -> 不需要填写任何参数(填了也不起作用)
|
||||||
|
* CRON -> 填写 CRON 表达式(可以找个[在线生成网站生成](https://www.bejson.com/othertools/cron/))
|
||||||
|
* 固定频率 -> 填写整数,单位毫秒
|
||||||
|
* 固定延迟 -> 填写整数,单位毫秒
|
||||||
|
* 执行配置:由执行类型(单机、广播和MapReduce)、处理器类型和处理器参数组成,后两项相互关联。
|
||||||
|
* 内置Java处理器 -> 填写该处理器的全限定类名(eg, `com.github.kfcfans.oms.processors.demo.MapReduceProcessorDemo`)
|
||||||
|
* Java容器 -> 填写**容器ID#处理器全限定类名**(eg,`1#com.github.kfcfans.oms.container.DemoProcessor`)
|
||||||
|
* 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`上报的日志,点击停止则可以强制终止该任务。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 在线日志
|
||||||
|
|
||||||
|
在线查看Worker执行过程中上报的日志,极大降低debug成本,提升开发效率!
|
||||||
|
|
||||||
|

|
6
others/guidance/content/docs/super/_index.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
weight: 2
|
||||||
|
bookFlatSection: false
|
||||||
|
title: "高级特性"
|
||||||
|
---
|
||||||
|
|
86
others/guidance/content/docs/super/container.md
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
title: 容器
|
||||||
|
weight: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
## 什么是容器?
|
||||||
|
|
||||||
|
### 介绍
|
||||||
|
|
||||||
|
OhMyScheduler的容器技术允许开发者**开发独立于Worker项目之外Java处理器**,简单来说,就是以Maven工程项目的维度去组织一堆Java文件(开发者开发的众多脚本处理器),进而兼具开发效率和可维护性。
|
||||||
|
|
||||||
|
### 用途举例
|
||||||
|
|
||||||
|
* 比如,突然出现了某个数据库数据清理任务,与主业务无关,写进原本的项目工程中不太优雅,这时候就可以单独创建一个用于数据操作的容器,在里面完成处理器的开发,通过OhMyScheduler的容器部署技术在Worker集群上被加载执行。
|
||||||
|
* 比如,常见的日志清理啊,机器状态上报啊,对于广大Java程序员来说,也许并不是很会写shell脚本,此时也可以借用**agent+容器**技术,利用Java完成各项原本需要通过脚本进行的操作。
|
||||||
|
|
||||||
|
(感觉例子举的都不是很好...这个东西嘛,只可意会不可言传,大家努力理解一下吧~超好用哦~)
|
||||||
|
|
||||||
|
## 生成容器模版
|
||||||
|
|
||||||
|
{{< hint info >}}
|
||||||
|
为了方便开发者使用,最新版本的前端页面已经支持容器工程模版的自动生成,开发者仅需要填入相关信息即可下载容器模版开始开发。
|
||||||
|
{{< /hint >}}
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
* Group:对应Maven的`<groupId>`标签,一般填入倒写的公司域名。
|
||||||
|
* Artifact:对于Maven的`<artifactId>`标签,填入代表该容器的唯一标示。
|
||||||
|
* Name:对应Maven的`<name>`标签,填入该容器名称。
|
||||||
|
* Package Name:包名,代表了的容器工程内部所使用的包名,**警告:包名一旦生成后,请勿更改!否则会导致运行时容器加载错误**(当然,如有必须修改包名的需求,可以尝试替换`/resource`下以`oms-worker-container`开头的所有文件相关的值)。
|
||||||
|
* Java Version:容器工程的Java版本,**请务必与容器目标部署Worker平台的Java版本保持一致**。
|
||||||
|
|
||||||
|
## 开发容器工程
|
||||||
|
|
||||||
|
完成容器模版创建后,下载,解压,会得到如下结构的Java工程:
|
||||||
|
|
||||||
|
```
|
||||||
|
oms-template-origin // 工程名称,可以自由更改
|
||||||
|
├── pom.xml
|
||||||
|
└── src
|
||||||
|
├── main
|
||||||
|
│ ├── java
|
||||||
|
│ │ └── cn
|
||||||
|
│ │ └── edu
|
||||||
|
│ │ └── zju
|
||||||
|
│ │ └── tjq
|
||||||
|
│ │ └── container
|
||||||
|
│ │ └── samples // 所有处理器代码必须位于该目录下,其余类随意
|
||||||
|
│ └── resources // 严禁随意更改以下两个配置文件(允许添加,不允许更改现有内容)
|
||||||
|
│ ├── oms-worker-container-spring-context.xml
|
||||||
|
│ └── oms-worker-container.properties
|
||||||
|
└── test
|
||||||
|
└── java
|
||||||
|
```
|
||||||
|
|
||||||
|
之后便可以愉快地在**packageName**下编写处理器代码啦~
|
||||||
|
|
||||||
|
需要示例代码?[客官这边请~](https://gitee.com/KFCFans/OhMyScheduler-Container-Template)
|
||||||
|
|
||||||
|
## 创建容器
|
||||||
|
|
||||||
|
目前,OhMyScheduler支持使用**Git代码库**和**FatJar**来创建容器。创建路径:**容器运维 -> 容器管理 -> 新建容器**。
|
||||||
|
|
||||||
|
{{< hint warning >}}
|
||||||
|
当使用**Git代码库**创建容器时,OhMyScheduler-Server需要完成代码库的下载、编译、构建和上传,**因此需要server运行环境包含可用的Git和Maven环境(包括私服的访问权限)**。
|
||||||
|
{{< /hint >}}
|
||||||
|
|
||||||
|
下图为使用**Git代码库**创建容器的示例,需要填入容器名称和代码库信息等参数:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
下图为使用**FatJar**创建容器的示例,需要上传可用的**FatJar**(注:FatJar值包含了所有依赖的Jar文件):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 部署容器
|
||||||
|
|
||||||
|
{{< hint info >}}
|
||||||
|
完成容器创建后,便可在容器管理界面查看已创建的容器,点击**部署**,可以看到详细的部署信息。
|
||||||
|
{{< /hint >}}
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
{{< hint info >}}
|
||||||
|
部署完成后,可以点击**机器列表**查看已部署该容器的机器信息。
|
||||||
|
{{< /hint >}}
|
128
others/guidance/content/docs/super/openapi.md
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
---
|
||||||
|
title: OpenAPI
|
||||||
|
weight: 2
|
||||||
|
---
|
||||||
|
|
||||||
|
{{< hint info >}}
|
||||||
|
OpenAPI允许开发者通过接口来完成手工的操作,让系统整体变得更加灵活。开发者可以基于API便捷地扩展OhMyScheduler原有的功能。
|
||||||
|
{{< /hint >}}
|
||||||
|
|
||||||
|
## 依赖
|
||||||
|
|
||||||
|
最新依赖版本请参考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>1.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 简单示例
|
||||||
|
|
||||||
|
```text
|
||||||
|
// 初始化 client,需要server地址和应用名称作为参数
|
||||||
|
OhMyClient ohMyClient = new OhMyClient("127.0.0.1:7700", "oms-test");
|
||||||
|
// 调用相关的API
|
||||||
|
ohMyClient.stopInstance(1586855173043L)
|
||||||
|
```
|
||||||
|
|
||||||
|
## API列表
|
||||||
|
|
||||||
|
### 创建/修改任务
|
||||||
|
|
||||||
|
接口签名:`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
|
||||||
|
|
6
others/guidance/content/docs/version/_index.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
weight: 1000
|
||||||
|
bookFlatSection: false
|
||||||
|
title: "更新日志"
|
||||||
|
---
|
||||||
|
|
BIN
others/guidance/static/oms-console-container-deploy.png
Normal file
After Width: | Height: | Size: 191 KiB |
BIN
others/guidance/static/oms-console-container-newfatjar.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
others/guidance/static/oms-console-container-newgit.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
others/guidance/static/oms-console-container-template.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
others/guidance/static/oms-console-jobCreator.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
others/guidance/static/oms-console-jobManager.png
Normal file
After Width: | Height: | Size: 139 KiB |
BIN
others/guidance/static/oms-console-main.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
others/guidance/static/oms-console-onlineLog.png
Normal file
After Width: | Height: | Size: 192 KiB |
BIN
others/guidance/static/oms-console-runningStatus.png
Normal file
After Width: | Height: | Size: 157 KiB |
BIN
others/guidance/static/oms-console-welcome.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
others/guidance/static/oms-logo.png
Normal file
After Width: | Height: | Size: 20 KiB |