【PowerJob语雀转载】 常见问题

241 阅读6分钟

当 powerjob-server 或 powerjob-worker 无法启动时,请您先尝试自主排查问题,可靠的途径有:

  1. 在本文档中查找是否有和您遇到的问题类似的 case
  2. GitHub Issue 搜索相关的问题
  3. 使用搜索引擎(Google、百度)搜索相关的问题
  4. 问问 ChatGPT

如果您无法解决遇到的问题,需要相关的帮助,请前往 GitHub 新建问题(new Issuce -> Question),我们将稍后为您解答。

1. 无法启动

1.1 编译报错

编译报错:不兼容的类型:推断类型不符合上限

-> 请升级最新版本的 OpenJDK 8 或 11

1.2 Worker 无法启动

NoClassDefFoundError

典型的依赖冲突问题,建议使用 mvn dependency:tree 打印依赖树进行问题的排查。****

ClassNotFoundException

解决方案同上

1.3 Server 无法启动

powerjob-server 就是一个普通的 SpringBoot 应用程序,无法启动的原因一般是数据库配置问题、JDK兼容性问题(JDK 8 & 11 测试通过,其余未测试)和操作系统兼容性问题(Linux & macOS & Windows 10 测试通过,Windows 7 可能无法启动),建议自行根据异常堆栈信息进行排查

powerjob-server 日志路径

Docker 启动:在 docker run 命令中通过 -v 指定,默认为 ~/docker/powerjob-server/logs

Jar 启动:~/powerjob-server/logs

serverTimezone 问题

java.sql.SQLException: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value if you want to utilize time zone support.

解决方案:在 JDBC URL 后加上 serverTimezone 信息,如 jdbc:mysql://127.0.0.1:3306/powerjob-daily?useUnicode=true&characterEncoding=UTF-8 &serverTimezone=Asia/Shanghai

高版本JDK问题

PowerJob 兼容 JDK8~17 的版本,高版本 JDK 由于移除了某些包,需要自己手动引入

类似于:java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

高版本JDK移除内置模块导致,参考以下教程添加相关包依赖即可。

stackoverflow.com/questions/5…

<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-core</artifactId>
  <version>2.3.0</version>
</dependency>
<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-impl</artifactId>
  <version>2.3.0</version>
</dependency>

3. Server/Worker 网络问题(执行器无法连接到 server)

PowerJob 中的所有组件(server 和 worker)必须处于 同一个局域网 中,这是系统运行所需要的必须条件。

2. 无法连接(控制台无worker列表)

  • 请检查 worker 是否启动成功
  • 请检查 worker 和 server 是否存在时差,为了保证调度准确性,server 和 worker 最大时差为 60S
  • 请检查 worker 与 server 是否在一个局域网中,如果不在(公网 / NAT / 容器 等场景),则需要特殊处理。

2.1. 通讯层依赖冲突

通讯层依赖冲突导致 worker 无法正常向 server 发送心跳包,无法连接到 server,常见异常有:

java.lang.NoSuchFieldError: ACCESS_CONTROL_ALLOW_PRIVATE_NETWORK at io.vertx.core.http.HttpHeaders.<clinit>(HttpHeaders.java:106)

java.lang.NoClassDefFoundError: Could not initialize class io.vertx.core.http.HttpHeaders at io.vertx.core.http.impl.HttpChannelConnector.applyHttp1xConnectionOptions(HttpChannelConnector.java:171) at io.vertx.core.http.impl.HttpChannelConnector.wrap(HttpChannelConnector.java:135)

java.lang.NoClassDefFoundError: io/netty/handler/codec/compression/StandardCompressionOptions

依赖冲突的重灾区一般集中在 netty,冲突原因可能有:

  • 和项目中引入 jar 包冲突:可通过排包、手动指定版本进行 maven 依赖仲裁,确保 powerjob 依赖不报错
  • 被 Spring 全局管理依赖:项目中使用 Spring Boot parent 或者 dependencies 进行依赖管理时,Spring Boot 中指定了netty的版本,有可能会和 vertx 依赖的 netty 冲突(特别是在 Spring Boot 的低版本中),可以在 pom.xml 文件 properties中,指定 netty 的版本。(详细可参考:LINK
<properties>
    <netty.version>4.1.86.Final</netty.version>

    ...
</properties>

2.2. 绑定网卡/获取 IP 不对

如果发现绑定的网卡/获取的 IP 不对,可以在worker启动时,添加 JVM 启动参数-Dpowerjob.network.interface.preferred=xxx 来指定绑定的网卡(该参数需要填入需要绑定的网卡名称),或通过 -Dpowerjob.network.interface.ignored=xxx 来忽略错误的网卡(该参数支持正则表达式,匹配到的网卡会被忽略)。

终极大招:可通过 JVM 启动参数 -Dpowerjob.network.local.address直接绑定本地使用的某个IP

2.3. 非局域网通讯

可使用 PowerJob 提供的启动参数绑定外部实际通讯 IP(该参数 worker 和 server 共享,均可配置,按需配置):

  • powerjob.network.external.address:外部IP地址,比如公网IP、NAT入口地址
  • powerjob.network.external.port:外部地址的端口
    • worker 侧由于只涉及一个接口,直接使用该参数指定外部地址端口即可
    • server 侧由于涉及多协议,需要单独为每个协议指定映射端口,规则为 powerjob.network.external.port.${协议},比如 HTTP 协议为 powerjob.network.external.port.http

举例,现有

  • server:内网地址为 server-innerIp,公网地址为 server-externalIp
  • worker:内网地址为 worker-innerIp,公网地址为 worker-externalIp。
  • server 与 worker 基于 http 协议通讯,server 的 http 通讯协议端口为 10010,worker 的工作端口为 27777

基于上述场景:

  • server 需要的启动参数:
    • 绑定 server 的外部地址 -Dpowerjob.network.external.address=server-externalIp
    • 绑定 server 某个通讯协议的外部地址端口:-Dpowerjob.network.external.port.http=10010
  • worker 需要的启动参数:
    • 绑定 worker 的外部地址 -Dpowerjob.network.external.address=worker-externalIp
    • 绑定 worker 的外部地址端口(worker 只有一个端口,因此不需要协议)-Dpowerjob.network.external.port=27777

注意点:

  1. powerjob.network.external.address 绑定的是本机的外部地址,而不是请求对象的地址(比如 server 部署在 121.41.47.169 这台机器上,内部绑定 127.0.0.1,external 则绑定 121.41.47.169)
  2. external 的作用是向另一端下发真正可访问的IP地址和端口,这个功能并不是万能的。要实现通讯,依旧需要保证 server 和 worker 最终的 external address 可互通
  3. 注意绑定 external address 后反而破坏局域网条件的场景。比如 docker 内的 server 和 worker,本身互通,但一旦 server 绑定  external address 为宿主地址,那 docker 内的 worker 就无法访问这个地址了,破坏了局域网条件。
  4. HTTP 协议确认可用,akka 协议未测试。
  5. 当前 PowerJob 并没有做过多的安全设计,支持非局域网调度主要是为了解决 docker + 本地 ide 等场景。强烈不建议在 PowerJob 支持用户和权限系统前使用公网调度 。(敬请期待权限版本)
  6. 最后放一张图证明功能可用性,不要怀疑!可用!

3. 常见运行时问题

3.1. 负载均衡问题

  • worker 连接 server 默认用 IP 列表的第一个值,多应用接入情况下更换 IP 顺序即可实现各个 server 都提供服务。当然,最推荐的还是用域名的形式做负载均衡。
  • server 调度 worker 执行任务默认采用的是最优选择策略(可选择为随机),单机任务只会选取CPU/内存状态最佳的机器执行!
  • 当某个节点故障时,PowerJob 有强大的高可用机制进行故障转移,只要系统中有组件存活,调度和任务就能正常进行!

3.2. 精确时间调度/只调度N次问题

CRON表达式支持精确时间调度

比如 0 0 13 8 10 ? 2020-2020 代表 2020年10月8日13:00:00秒

如果确定 CRON 无法支持,请自行通过 OpenAPI 实现。

4. 数据库相关

此处为语雀内容卡片,点击链接查看:www.yuque.com/powerjob/gu…