• zxb的博客
    • 运维
      • 🧊即插即更:移动硬盘与 U 盘的自动同步方案
      • ⛳FRP穿透个人博客——SSL安全篇
      • 📄Github Action自动化部署Vue3项目
      • 🎲Docker Desktop 代理配置:让镜像拉取更稳更快
      • 🤓FRP穿透搭建个人博客(白嫖SSL版)
      • 🪁FRP穿透搭建个人博客
      • 📄Kubeeasy安装K8s集群(附独家报错解决)
      • 📄不用 Kubernetes,Docker Compose 也能实现零停机蓝绿发布
    • 技术体验
      • 🛡️别再找插件了,美团出品的Tabbit才是真正的AI浏览器
      • 💧GitHub 霸榜!Tabbit平替:给浏览器装上“最强大脑”,这才是真·AI 浏览器插件
    • 自制软件插件
      • 🧋🧧 仪式感拉满!这款开源“年味”小游戏,带你瞬间找回童年快乐!
      • 🕸️摸鱼神器——摸了吗
      • 🔍🚀 思源笔记 S3 插件 v1.0.2 更新:手把手教你配置 PicList 导出
      • 🌊🚀 思源笔记 S3 插件 v1.0.3 更新:一键解锁 BM.md 精美排版!
      • 🥔AE机器人大模型案例
      • Claude Code 终于会"叫"了 —— 一个 10MB 小工具,让 AI 跑完任务发个声
    • 开发小技巧
      • 🪴【保姆级】NAS 骚操作:白嫖百 T 网盘做图床!阿里云/百度秒变“私有云相册”,快到飞起!
    • 后端技术
      • 🚁解决 Spring Session 分布式部署难题:Redis 集成指南
      • 📄使用ThreadLocal实现用户身份认证
      • SpringAI
        • 别再手写 HTTP 客户端调 AI 了!Spring AI 官方出手,一行代码搞定多模型切换
      • 📄使用注解+反射实现自动填充
      • Spring
        • 🔁循环依赖:一个Spring经典坑
        • Spring如何解决依赖循环
        • 🫛什么是Spring Bean
      • Java基础
        • 什么是序列化和反序列化?
        • 📄Java中HashMap的原理
      • 📄分布式系统中的"保险箱":事务Outbox模式深度解析
    • 📑前端技术
      • 🫚axios工具类
      • 🍛Vite项目屏幕适配的两种方案,超详细
      • 📕vue-router小技巧:通过route传参动态设置页面
      • 📄Next.js 中 NEXT_PUBLIC_ 环境变量为何修改后不生效
    • 疑难杂症
      • 🕙SpringWeb报错——CORS问题解决
      • 📄一行 JVM 参数解决 HttpClient 卡死:强制 Java 禁用 IPv6
      • 📄修复github action注入npm包权限问题
zxb的博客疑难杂症

一行 JVM 参数解决 HttpClient 卡死:强制 Java 禁用 IPv6

访问次数 2671 次创建时间 2026-03-27 11:08

问题场景

某天线上服务突然出现偶发性超时,排查了半天,日志里卡在 HttpClient.execute() 一动不动,没有任何异常抛出,线程就那么"假死"了。重启能恢复,但过一阵子又复现,让人头皮发麻。

最终定位到根因:Java 在网络解析时优先尝试了 IPv6,而服务器环境实际只有 IPv4 通,导致连接超时前的等待时间被无限拉长。

报错:

dMiniProgramBackend-debug  | java.net.http.HttpConnectTimeoutException: HTTP connect timed out
WordMiniProgramBackend-debug  |         at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:917)
WordMiniProgramBackend-debug  |         at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:133)
WordMiniProgramBackend-debug  |         at com.xkcoding.http.support.java11.HttpClientImpl.exec(HttpClientImpl.java:67)
WordMiniProgramBackend-debug  |         at com.xkcoding.http.support.java11.HttpClientImpl.get(HttpClientImpl.java:140)
WordMiniProgramBackend-debug  |         at com.xkcoding.http.HttpUtil.get(HttpUtil.java:131)
WordMiniProgramBackend-debug  |         at me.zhyd.oauth.utils.HttpUtils.get(HttpUtils.java:37)
WordMiniProgramBackend-debug  |         at me.zhyd.oauth.request.AuthWechatMiniProgramRequest.getAccessToken(AuthWechatMiniProgramRequest.java:37)
WordMiniProgramBackend-debug  |         at me.zhyd.oauth.request.AuthDefaultRequest.login(AuthDefaultRequest.java:61)
WordMiniProgramBackend-debug  |         at com.word.user.service.impl.UserServiceImpl.login(UserServiceImpl.java:54)
WordMiniProgramBackend-debug  |         at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
WordMiniProgramBackend-debug  |         at java.base/java.lang.reflect.Method.invoke(Method.java:565)
WordMiniProgramBackend-debug  |         at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
WordMiniProgramBackend-debug  |         at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:715)
WordMiniProgramBackend-debug  |         at com.word.user.service.impl.UserServiceImpl$$SpringCGLIB$$0.login(<generated>)
WordMiniProgramBackend-debug  |         at com.word.user.controller.UserController.login(UserController.java:48)
WordMiniProgramBackend-debug  |         at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
WordMiniProgramBackend-debug  |         at java.base/java.lang.reflect.Method.invoke(Method.java:565)
WordMiniProgramBackend-debug  |         at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:252)
WordMiniProgramBackend-debug  |         at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:184)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:934)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:853)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:86)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:866)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1000)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:903)
WordMiniProgramBackend-debug  |         at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:649)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:874)
WordMiniProgramBackend-debug  |         at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:128)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:142)
WordMiniProgramBackend-debug  |         at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:355)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:272)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:110)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:199)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:165)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:77)
WordMiniProgramBackend-debug  |         at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:113)
WordMiniProgramBackend-debug  |         at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:83)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:72)
WordMiniProgramBackend-debug  |         at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
WordMiniProgramBackend-debug  |         at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397)
WordMiniProgramBackend-debug  |         at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
WordMiniProgramBackend-debug  |         at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1779)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:946)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:480)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:57)
WordMiniProgramBackend-debug  |         at java.base/java.lang.Thread.run(Thread.java:1474)
WordMiniProgramBackend-debug  | Caused by: java.net.http.HttpConnectTimeoutException: HTTP connect timed out
WordMiniProgramBackend-debug  |         at java.net.http/jdk.internal.net.http.ResponseTimerEvent.handle(ResponseTimerEvent.java:68)
WordMiniProgramBackend-debug  |         at java.net.http/jdk.internal.net.http.HttpClientImpl.purgeTimeoutsAndReturnNextDeadline(HttpClientImpl.java:1751)
WordMiniProgramBackend-debug  |         at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:1348)
WordMiniProgramBackend-debug  | Caused by: java.net.ConnectException: HTTP connect timed out
WordMiniProgramBackend-debug  |         at java.net.http/jdk.internal.net.http.ResponseTimerEvent.handle(ResponseTimerEvent.java:69)
WordMiniProgramBackend-debug  |         ... 2 more
WordMiniProgramBackend-debug  | 2026-06-07 07:32:31 http-nio-8080-exec-1 me.zhyd.oauth.log.Log(error:45) [ERROR] - Failed to login with oauth authorization.
WordMiniProgramBackend-debug  | me.zhyd.oauth.exception.AuthException: HTTP connect timed out
WordMiniProgramBackend-debug  |         at me.zhyd.oauth.utils.HttpUtils.check(HttpUtils.java:123)
WordMiniProgramBackend-debug  |         at me.zhyd.oauth.utils.HttpUtils.getBody(HttpUtils.java:129)
WordMiniProgramBackend-debug  |         at me.zhyd.oauth.request.AuthWechatMiniProgramRequest.getAccessToken(AuthWechatMiniProgramRequest.java:37)
WordMiniProgramBackend-debug  |         at me.zhyd.oauth.request.AuthDefaultRequest.login(AuthDefaultRequest.java:61)
WordMiniProgramBackend-debug  |         at com.word.user.service.impl.UserServiceImpl.login(UserServiceImpl.java:54)
WordMiniProgramBackend-debug  |         at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
WordMiniProgramBackend-debug  |         at java.base/java.lang.reflect.Method.invoke(Method.java:565)
WordMiniProgramBackend-debug  |         at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
WordMiniProgramBackend-debug  |         at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:715)
WordMiniProgramBackend-debug  |         at com.word.user.service.impl.UserServiceImpl$$SpringCGLIB$$0.login(<generated>)
WordMiniProgramBackend-debug  |         at com.word.user.controller.UserController.login(UserController.java:48)
WordMiniProgramBackend-debug  |         at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
WordMiniProgramBackend-debug  |         at java.base/java.lang.reflect.Method.invoke(Method.java:565)
WordMiniProgramBackend-debug  |         at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:252)
WordMiniProgramBackend-debug  |         at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:184)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:934)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:853)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:86)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:866)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1000)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:903)
WordMiniProgramBackend-debug  |         at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:649)
WordMiniProgramBackend-debug  |         at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:874)
WordMiniProgramBackend-debug  |         at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:128)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:142)
WordMiniProgramBackend-debug  |         at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:355)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:272)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:110)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:199)
WordMiniProgramBackend-debug  |         at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:107)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:165)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:77)
WordMiniProgramBackend-debug  |         at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:113)
WordMiniProgramBackend-debug  |         at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:83)
WordMiniProgramBackend-debug  |         at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:72)
WordMiniProgramBackend-debug  |         at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341)
WordMiniProgramBackend-debug  |         at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397)
WordMiniProgramBackend-debug  |         at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
WordMiniProgramBackend-debug  |         at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1779)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:946)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:480)
WordMiniProgramBackend-debug  |         at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:57)
WordMiniProgramBackend-debug  |         at java.base/java.lang.Thread.run(Thread.java:1474)

根因分析

Java 的网络栈默认是双栈(Dual-Stack) 模式,即 IPv4 和 IPv6 同时启用。当发起一个 HTTP 请求时:

  1. DNS 解析返回域名对应的所有 IP 地址(可能同时包含 A 记录和 AAAA 记录)
  2. Java 默认会优先尝试 IPv6(如果系统支持)
  3. 如果 IPv6 不通(比如服务器没配 IPv6、防火墙拦截了),Java 会傻傻等到超时
  4. 超时后再 fallback 到 IPv4——但此时上层业务可能已经超时了

这在容器化环境(Docker / K8s)中尤其常见,因为容器网络默认就启用了 IPv6 支持。


解决方法

一行参数搞定,在启动命令中加入:

java -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true -jar your-app.jar
参数 作用
-Djava.net.preferIPv4Stack=true 强制 JVM 使用 IPv4 协议栈,彻底禁用 IPv6
-Djava.net.preferIPv4Addresses=true 当 DNS 同时返回 IPv4/IPv6 地址时,优先使用 IPv4

两个参数一起上,双重保险。


Docker 环境配置

如果是 Docker 部署,在 docker-compose.yml 或 Dockerfile 中设置:

# docker-compose.yml
services:
  your-service:
    image: your-image
    environment:
      - JAVA_TOOL_OPTIONS=-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true

为什么用 ​JAVA_TOOL_OPTIONS​​ 而不是 ​JAVA_OPTS​​ ?

  • JAVA_TOOL_OPTIONS​ 是 JVM 原生读取的环境变量,无需应用做任何适配,任何 Java 进程启动时都会自动加载
  • JAVA_OPTS​ 需要你的启动脚本(如 entrypoint.sh)手动拼接,容易遗漏

K8s 同理:

# deployment.yaml
spec:
  containers:
    - name: your-app
      image: your-image
      env:
        - name: JAVA_TOOL_OPTIONS
          value: "-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true"

验证是否生效

启动后检查日志,如果看到类似输出说明已生效:

Picked up JAVA_TOOL_OPTIONS: -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true

也可以用 jinfo 验证运行中的进程:

jinfo -sysprops <pid> | grep preferIPv4

输出:

java.net.preferIPv4Stack = true
java.net.preferIPv4Addresses = true

延伸思考

这其实反映了一个更普遍的教训:默认行为不一定适合你的环境。 Java 的双栈设计在 IPv6 普及的今天看似"先进",但在很多内网、容器网络中反而是坑。类似的还有:

  • -Djava.awt.headless=true:服务器环境没 GUI,不设这个图片处理可能报错
  • -Dfile.encoding=UTF-8:避免跨平台文件编码乱码
  • -Duser.timezone=Asia/Shanghai:统一时区,避免日志时间混乱

建议把这些基础 JVM 参数做成团队的基础镜像或启动脚本模板,一劳永逸。


[!Tip] 一句话总结 ​JAVA_TOOL_OPTIONS="-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true"​ ​ — 加这行到环境变量,HttpClient 假死问题一去不返。

‍

评论

0 条评论

暂无评论,欢迎第一个留言。

验证码
回复评论
验证码
举报内容
验证码
由 b8l8u8e8 提供支持