// TestMapReduceJob.go
package main
import (
"encoding/json"
"fmt"
"github.com/alibaba/schedulerx-worker-go/processor"
"github.com/alibaba/schedulerx-worker-go/processor/jobcontext"
"github.com/alibaba/schedulerx-worker-go/processor/mapjob"
"github.com/alibaba/schedulerx-worker-go/processor/taskstatus"
"strconv"
"time"
)
type OrderInfo struct {
Id string `json:"id"`
Value int `json:"value"`
}
func NewOrderInfo(id string, value int) *OrderInfo {
return &OrderInfo{Id: id, Value: value}
}
type TestMapReduceJob struct {
*mapjob.MapReduceJobProcessor
}
func (mr *TestMapReduceJob) Kill(jobCtx *jobcontext.JobContext) error {
//TODO implement me
panic("implement me")
}
// Process the MapReduce model is used to distributed scan orders for timeout confirmation
func (mr *TestMapReduceJob) Process(jobCtx *jobcontext.JobContext) (*processor.ProcessResult, error) {
var (
num = 1000
err error
)
taskName := jobCtx.TaskName()
if jobCtx.JobParameters() != "" {
num, err = strconv.Atoi(jobCtx.JobParameters())
if err != nil {
return nil, err
}
}
if mr.IsRootTask(jobCtx) {
fmt.Println("start root task, taskId=%d", jobCtx.TaskId())
var orderInfos []interface{}
for i := 1; i <= num; i++ {
orderInfos = append(orderInfos, NewOrderInfo(fmt.Sprintf("id_%d", i), i))
}
return mr.Map(jobCtx, orderInfos, "OrderInfo")
} else if taskName == "OrderInfo" {
orderInfo := new(OrderInfo)
if err := json.Unmarshal(jobCtx.Task(), orderInfo); err != nil {
fmt.Printf("task is not OrderInfo, task=%+v\n", jobCtx.Task())
}
fmt.Printf("taskId=%d, orderInfo=%+v\n", jobCtx.TaskId(), orderInfo)
time.Sleep(1 * time.Millisecond)
return processor.NewProcessResult(
processor.WithSucceed(),
processor.WithResult(strconv.Itoa(orderInfo.Value)),
), nil
}
return processor.NewProcessResult(processor.WithFailed()), nil
}
func (mr *TestMapReduceJob) Reduce(jobCtx *jobcontext.JobContext) (*processor.ProcessResult, error) {
allTaskResults := jobCtx.TaskResults()
allTaskStatuses := jobCtx.TaskStatuses()
count := 0
fmt.Printf("reduce: all task count=%d\n", len(allTaskResults))
for key, val := range allTaskResults {
if key == 0 {
continue
}
if allTaskStatuses[key] == taskstatus.TaskStatusSucceed {
num, err := strconv.Atoi(val)
if err != nil {
return nil, err
}
count += num
}
}
fmt.Printf("reduce: succeed task count=%d\n", count)
return processor.NewProcessResult(
processor.WithSucceed(),
processor.WithResult(strconv.Itoa(count)),
), nil
}
4. 注册 client 和 job
package main
import (
"os"
"os/signal"
"syscall"
"time"
"github.com/alibaba/schedulerx-worker-go"
)
func main() {
// This is just an example, the real configuration needs to be obtained from the platform
cfg := &schedulerx.Config{
Endpoint: "acm.aliyun.com",
Namespace: "433d8b23-06e9-408c-aaaa-90d4d1b9a4af",
GroupId: "gojob-test",
AppKey: "xxxxxxx",
}
client, err := schedulerx.GetClient(cfg)
if err != nil {
panic(err)
}
task1 := &HelloWorld{}
task2 := &TestBroadcast{}
task3 := &TestMapJob{
mapjob.NewMapJobProcessor(),
}
task4 := &TestMapReduceJob{
mapjob.NewMapReduceJobProcessor(),
}
// The name HelloWorld registered here must be consistent with the configured on the platform
client.RegisterTask("HelloWorld", task1)
client.RegisterTask("TestBroadcast", task2)
client.RegisterTask("TestMapJob", task3)
client.RegisterTask("TestMapReduceJob", task4)
// wait for the stop signal
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR1, syscall.SIGUSR2)
<-c
time.Sleep(time.Second * 5)
}
schedulerx-worker-go 使用文档
背景
SchedulerX 是阿里云提供的分布式任务调度服务(兼容开源 XXL-JOB/ElasticJob/K8s Job/Spring Schedule),支持 Cron 定时、一次性任务、任务编排、分布式数据处理,具有高可用、可视化、可运维、低延时等能力。
schedulerx-worker-go 是 SchedulerX Go 版本的 SDK,该 SDK 由高德贡献。
功能
使用说明
1. 登录 SchedulerX 控制台创建应用,返回配置信息
2. 拉取 Go 版本 SDK
3. 实现接口,编写业务代码
3.1 单机任务
接口如下:
实现接口,参考Demo :
3.2 广播任务
接口如下:
接口描述:
实现接口, 参考Demo:
3.3 Map任务
接口如下:
接口描述:
实现接口,参考Demo:
3.4 MapReduce任务
接口如下:
继承Map接口,新增接口如下:
实现接口,参考Demo:
4. 注册 client 和 job
4. 通过控制台创建任务
任务类型选择 golang,任务名称写第 4 步的任务名,比如 HelloWorld
示例
参考 example 目录