Payara Micro在Kubernetes中随机未开放8080端口的排查求助
Payara Micro 6.2024.7-jdk21 随机未开放8080端口问题排查
环境与核心问题
- 运行环境:DigitalOcean Kubernetes集群,使用镜像
payara/micro:6.2024.7-jdk21 - 核心问题:Pod内8080端口随机未开放,触发就绪探针失败导致容器重启;重启后恢复正常,无流量时也会随机出现该问题
- 部署策略:蓝绿部署,HPA最小副本数设为2
已执行的测试与观察结果
- 容器启动后立即执行
netstat -tuln,无开放端口 - Payara Micro启动后通常可见8080和6900端口,偶尔缺失8080
- 日志中出现关键异常:
- 严重错误:
SEVERE: Error adding HttpProbes. NetworkListener http-listeners GrizzlyProxy is NULL. - 类加载相关细粒度错误:
FINE: Failed to clear ResourceBundle references for web application [unknown] java.lang.NoSuchFieldException: loaderRef at java.base/java.lang.Class.getDeclaredField(Class.java:2782) at org.glassfish.web.loader.WebappClassLoader.clearReferencesResourceBundles(WebappClassLoader.java:2773) ...(省略重复栈轨迹)FINE: Method not found: clearProperties java.lang.NoSuchMethodException: jakarta.el.BeanELResolver.clearProperties(java.lang.ClassLoader) at java.base/java.lang.Class.getMethod(Class.java:2395) at org.glassfish.web.loader.CachingReflectionUtil.lambda$getMethodFromCache$1(CachingReflectionUtil.java:76) ...(省略重复栈轨迹)
- 严重错误:
- 端口未开放时,应用仍显示部署成功:
INFO: { "Instance Configuration": { "Host": "some-app-green-5768f94d4b-ct2n2", "Http Port(s)": "8080", "Https Port(s)": "", "Instance Name": "Poor-Flyingfish", "Instance Group": "MicroShoal", "Hazelcast Member UUID": "e4a1bcea-1da1-4952-92af-4d282b93dcb1", "Deployed": [ { "Name": "someapp", "Type": "war", "Context Root": "/app" } ] } } - Kubernetes环境检查:
kubectl get networkpolicy -A无结果,事件日志仅记录就绪探针失败
相关配置信息
Dockerfile片段
FROM --platform=linux/amd64 payara/micro:6.2024.7-jdk21 COPY dist/ /opt/payara/deployments/ COPY conf/mysql-connector-j-8.2.0.jar /opt/payara/deployments/mysql-connector-j-8.2.0.jar COPY conf/configure-datasource.sh /opt/payara/scripts/configure-datasource.sh ENV JVM_ARGS="-XX:MaxHeapFreeRatio=50" CMD ["--enableRequestTracing", "2", "--addjars", "/opt/payara/deployments/mysql-connector-j-8.2.0.jar", "--postbootcommandfile", "/opt/payara/scripts/configure-datasource.sh", "--deploy", "/opt/payara/deployments/someapp.war", "--contextroot", "/app", "--port", "8080", "--clustermode", "kubernetes:namespace-ns,backend-service"]
启动后脚本(configure-datasource.sh)片段
set configs.config.server-config.thread-pools.thread-pool.http-thread-pool.min-thread-pool-size=5 set configs.config.server-config.thread-pools.thread-pool.http-thread-pool.max-thread-pool-size=350 set configs.config.server-config.thread-pools.thread-pool.thread-pool-1.min-thread-pool-size=3 set configs.config.server-config.thread-pools.thread-pool.thread-pool-1.max-thread-pool-size=250 set configs.config.server-config.web-container.session-config.session-properties.timeout-in-seconds=432000 set-metrics-configuration --enabled=false set configs.config.server-config.network-config.protocols.protocol.http-listener.http.cookie-same-site-enabled=true set configs.config.server-config.network-config.protocols.protocol.http-listener.http.cookie-same-site-value=None set configs.config.server-config.network-config.protocols.protocol.http-listener.http.compressable-mime-type=text/plain,text/html,text/xml,text/css,application/xml,application/xhtml+xml,application/rss+xml,application/javascript,image/svg+xml,application/json set configs.config.server-config.network-config.protocols.protocol.http-listener.http.compression=on set configs.config.server-config.network-config.protocols.protocol.http-listener.http.compression-level=6 set configs.config.server-config.network-config.protocols.protocol.http-listener.http.file-cache.enabled=true set configs.config.server-config.network-config.protocols.protocol.http-listener.http.file-cache.max-age-seconds=3600 set configs.config.server-config.network-config.protocols.protocol.http-listener.http.file-cache.max-cache-size-bytes=52857600 set configs.config.server-config.network-config.protocols.protocol.http-listener.http.file-cache.max-files-count=5000
可能的原因与解决方案
1. Grizzly网络监听器初始化竞态
日志中的NetworkListener http-listeners GrizzlyProxy is NULL是核心线索,说明Payara的Grizzly HTTP服务器初始化失败,导致8080端口未绑定。
- 解决方案:
- 升级Payara Micro版本:该版本可能存在初始化竞态bug,尝试升级到最新6.x稳定版,官方大概率已修复此类随机启动失败问题
- 显式指定监听器绑定:在启动命令中添加
--networkListener http-listener=0.0.0.0:8080,强制绑定端口,避免自动配置的不确定性 - 调整启动顺序:将应用部署命令放在postboot脚本执行之后,或者在脚本中添加短暂延迟,避免配置修改与监听器初始化的冲突
2. JDK版本适配问题
日志中的类加载反射异常(NoSuchFieldException、NoSuchMethodException)表明JDK21与Payara内部类加载逻辑存在适配问题,间接影响监听器启动。
- 解决方案:
- 降级JDK版本:暂时切换到JDK17测试,确认是否是JDK21的兼容性问题
- 禁用类加载器清理优化:通过JVM参数
-Dorg.glassfish.web.loader.WebappClassLoader.clearReferences=false关闭类加载器清理逻辑,避免反射调用失败
3. Kubernetes资源竞争
K8s节点的CPU、内存波动可能导致Payara启动时初始化超时,监听器未完成绑定。
- 解决方案:
- 配置Pod资源请求与限制:为Pod设置合理的
resources.requests.cpu、resources.requests.memory,避免启动时资源不足 - 优化就绪探针:增加
initialDelaySeconds(如设为60)和periodSeconds(如设为10),给Payara足够的启动时间,避免误判
- 配置Pod资源请求与限制:为Pod设置合理的
4. 启动脚本配置冲突
postboot脚本中修改了多项HTTP监听器配置,可能与Payara Micro的默认初始化流程冲突。
- 解决方案:
- 简化启动脚本:逐步移除配置项,排查是否某一项配置导致监听器初始化失败(例如先移除文件缓存、压缩相关配置)
- 使用静态配置文件:将配置项写入
microprofile-config.properties或Payara的domain.xml片段,替代动态修改的postboot脚本,避免启动时的配置竞态
内容的提问来源于stack exchange,提问作者Pedro K-Lar
相关产品推荐
相关产品推荐

