【PowerJob语雀转载】 高级特性-多语言支持

35 阅读6分钟

server 与 worker 之间通过 ****HTTP+JSON 进行通讯,开发者基于 Http 实现每个语言具体的 client。

PowerJob 在设计中,任务的执行是 worker 高度自治的,server 只做一开始的任务派发和后续的状态检测,因此需要实现的规范很少。

推荐先阅读官方的 powerjob-worker Java 版,无论是与 server 的交互还是 worker 内部任务的执行,思路大体上都是一致的。

没有特别约定返回值的请求,可随意返回结果字段,比如 "success"

postman: LINK

简单版:HTTP

复活:HttpProcessor

  • 主要是考虑到开发一个 client 还是有一定成本的(开发 + 维护)
  • 官方仅提供 Java & Python 双 client

完全体:Client

初始化阶段

初始化阶段的所有请求用的都是配置文件中配置的服务器地址(默认为 7700)端口

也只有这两个请求用的是配置文件中的服务器地址

App 校验

校验该 App 是否已在 server 端注册

请求地址:/server/assert?appName=

请求方式:GET

返回值:

{
    "success":true, // true 代表校验通过,false 代表校验不通过,此时应该阻止应用继续启动
    "data":1, // 该 appName 对应的 appId,需要保存该值,后续所有请求都依赖 appId
    "message":"" // success 为 false 时存在,代表错误信息
}

Java 版代码路径:tech.powerjob.worker.PowerJobWorker#assertAppName

服务发现

定时请求 server 获取当前 app 真正的调度服务器地址,所有 worker 的请求都通过该返回地址发送。

请求地址:/server/acquire?appId=%d&currentServer=%s&protocol=HTTP

  • appId 处填入之前返回的 appId
  • currentServer 填当前使用的调度服务器地址,初次请求时可不填
  • clientVersion:客户端版本

请求方式:GET

返回值

{
    "success":true,
    "data":"127.0.0.1:10010", // 当前该 app 所使用的 server 地址,需要保存下来,后续所有请求都通过该地址发送给 server
    "message":""
}

Java 版代码路径:tech.powerjob.worker.background.ServerDiscoveryService#acquire

注意:

  • 该接口极其重要,为了保证高可用性,需要定时请求以获取 server 的最新地址
  • 该接口返回的地址才是 worker 真正需要交互的 server address,因此该返回值必须保存下来且可被 worker 读取并使用

处理 Server 请求

任务执行请求

当 server 调度任务执行时,会发送该请求到 worker,worker 需要接收并解析该请求,并完成任务的运行。

worker 需要提供符合预期的 HTTP 接口来接收 server 的请求:

  • 接口地址:/worker/runJob
  • 请求方式:POST
  • 请求参数
    • 官方文档更新可能不及时,建议直接参考对象 tech.powerjob.common.request.ServerScheduleJobReq
{
	"allWorkerAddress": ["192.168.1.9:27777", "192.168.1.9:27778"],
	"jobId": 202,
	"wfInstanceId": null,
	"instanceId": 241521139652755520,
	"executeType": "STANDALONE",
	"processorType": "EMBEDDED_JAVA",
	"processorInfo": "cn.edu.zju.oms.container.SimpleStandaloneProcessor",
	"instanceTimeoutMS": 0,
	"jobParams": "{"batchSize": 10, "batchNum": 10}",
	"instanceParams": null,
	"threadConcurrency": 5,
	"taskRetryNum": 1,
	"timeExpressionType": "API",
	"timeExpression": null,
	"maxInstanceNum": 0
}
  • allWorkerAddress:Array类型,代表可参与本次任务运行的所有 worker 地址
  • executeType:执行类型,STANDALONE / BROADCAST / MAP_REDUCE / MAP
  • instanceId:任务实例ID
  • instanceTimeoutMS:任务超时时间
  • jobId:任务ID
  • jobParams:任务的控制台参数
  • maxInstanceNum:任务的最大实例数
  • processorInfo:任务的处理器信息
  • processorType:任务的处理器类(其他语言的客户端可以直接忽略这个属性)
  • taskRetryNum:最大 Task 重试次数
  • threadConcurrency:线程并发数
  • timeExpression:时间表达式内容,由 timeExpressionType 决定具体的值类型,可能是数字(秒级任务)
  • timeExpressionType:时间表达式类型,API / CRON / FIXED_RATE / FIXED_DELAY / WORKFLOW

**

任务实例停止执行请求

用户手动停止某个任务时,需要停止该任务实例

worker 需要提供符合预期的 HTTP 接口来接收 server 的请求:

  • 接口地址:/worker/stopInstance
  • 请求类型:POST
  • 请求参数
{
  "instanceId": 239140752452485440
}

任务实例运行状态查询请求

用户查看任务实例详情时,需要从 TaskTracker 查询具体的运行时信息

worker 需要提供符合预期的 HTTP 接口来接收 server 的请求:

  • 接口地址:/worker/queryInstanceStatus
  • 请求类型:POST
  • 请求参数:tech.powerjob.common.request.ServerQueryInstanceStatusReq
{
  "instanceId": 239140752452485440
}
  • 返回值

参考 Java :tech.powerjob.common.model.InstanceDetail

该接口非核心功能,可选择实现

向 server 发送请求

心跳

worker 需要定期向 server 发送心跳包,建议每 15S 发送一次请求

  • 请求地址:/server/workerHeartbeat
  • 请求方式:POST
  • 请求参数:tech.powerjob.common.request.WorkerHeartbeat
{
    "appId":1,
    "appName":"powerjob-agent-test",
		"workerAddress":"192.168.124.29:27778",
    "heartbeatTime":1612792419121,
    "protocol":"HTTP",
    "systemMetrics":{
        "cpuLoad":2.4258,
        "cpuProcessors":8,
        "diskTotal":233.4691,
        "diskUsage":0.0446,
        "diskUsed":10.4179,
        "jvmMaxMemory":3.5557,
        "jvmMemoryUsage":0.1083,
        "jvmUsedMemory":0.385,
      	"extra": "",
        "score":11
    }
}
  • workerAddress:对 powerjob-server 提供 HTTP 的服务地址
  • heartbeatTime:当前时间,13位时间戳
  • protocol:写死 HTTP
  • systemMetrics:当前系统的指标
    • cpuLoad:load1 数据
    • cpuProcessors:CPU 核心数
    • diskTotal:磁盘剩余空间大小,单位 GB
    • diskUsage:磁盘使用率
    • diskUsed:磁盘已使用空间
    • jvmMaxMemory:该进程当前最大可用内存,单位 GB(忽略 JVM)
    • jvmMemoryUsage:该进程当前的内存使用率(忽略 JVM)
    • jvmUsedMemory:该进程当前所使用的内存大小,单位 GB(忽略 JVM)
    • score:按当前各项参数计算得到的分数,分数越高健康度排名越高,会被优先调度

任务实例状态上报

每个运行中的任务都要定时发送状态信息到 server,建议 10S 左右上报一次

请求地址:/server/reportInstanceStatus

请求方式:POST

请求参数:tech.powerjob.common.request.TaskTrackerReportInstanceStatusReq

{
    "jobId":14,
    "instanceId":239146443485479232,
    "reportTime":1612793022034,
    "sourceAddress":"192.168.124.29:27778",
    "instanceStatus":3,
}
  • jobId:任务ID
  • instanceId:当前任务实例ID
  • reportTime:上报时间,直接取当前时间
  • sourceAddress:本机地址
  • instanceStatus:任务状态

返回值:根据 success 判断 server 是否接收并更新成功,若任务结束请求被 server 成功接收,则代表该任务执行完毕,需要关闭任务实例处理的单元并释放相关的资源。

{
  "success": true,
  "message": ""
}

在线日志

可选接口,建议实现,可在控制台直接看到日志

请求路径:/server/reportLog

请求方式:POST

请求参数:tech.powerjob.common.request.WorkerLogReportReq

{
    "instanceLogContents":[
        {
            "instanceId":239148708413833536,
            "logContent":"[DemoMRProcessor] process subTask: {"age":24,"name":"name24"}.",
            "logLevel":2,
            "logTime":1612793526037
        },
        {
            "instanceId":239148708413833536,
            "logContent":"[DemoMRProcessor] process subTask: {"age":25,"name":"name25"}.",
            "logLevel":2,
            "logTime":1612793526037
        }
    ],
    "workerAddress":"192.168.124.29:27778"
}
  • instanceLogContents:数组,包含了若干条日志
    • instanceId:任务实例ID
    • logContent:日志的具体内容
    • logLevel:日志级别,1 ~ 4 代表 DEBUG、INFO、WARN 和 ERROR
    • logTime:日志的记录时间
  • workerAddress:worker 对 server 暴露的地址

Java 参考实现:tech.powerjob.worker.log 包下所有代码