当 powerjob-server 或 powerjob-worker 无法启动时,请您先尝试自主排查问题,可靠的途径有:
- 在本文档中查找是否有和您遇到的问题类似的 case
- 去 GitHub Issue 搜索相关的问题
- 使用搜索引擎(Google、百度)搜索相关的问题
- 问问 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
- 绑定 server 的外部地址
- worker 需要的启动参数:
-
- 绑定 worker 的外部地址
-Dpowerjob.network.external.address=worker-externalIp - 绑定 worker 的外部地址端口(worker 只有一个端口,因此不需要协议)
-Dpowerjob.network.external.port=27777
- 绑定 worker 的外部地址
注意点:
- powerjob.network.external.address 绑定的是本机的外部地址,而不是请求对象的地址(比如 server 部署在 121.41.47.169 这台机器上,内部绑定 127.0.0.1,external 则绑定 121.41.47.169)
- external 的作用是向另一端下发真正可访问的IP地址和端口,这个功能并不是万能的。要实现通讯,依旧需要保证 server 和 worker 最终的 external address 可互通
- 注意绑定 external address 后反而破坏局域网条件的场景。比如 docker 内的 server 和 worker,本身互通,但一旦 server 绑定 external address 为宿主地址,那 docker 内的 worker 就无法访问这个地址了,破坏了局域网条件。
- HTTP 协议确认可用,akka 协议未测试。
- 当前 PowerJob 并没有做过多的安全设计,支持非局域网调度主要是为了解决 docker + 本地 ide 等场景。强烈不建议在 PowerJob 支持用户和权限系统前使用公网调度 。(敬请期待权限版本)
- 最后放一张图证明功能可用性,不要怀疑!可用!
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…