目录

  • 前言
  • 现象
  • 分析原因
  • 解决方法
  • 思考感悟


前言

jvm启动参数应该非常熟悉了,但是最近在测试环境想要远程debug的时候发现怎么也连不上,接下来记录一下整个排查过程

现象

版本(抛开版本就是耍流氓~)
jdk8

远程debug参数添加之后一直没有生效, 报如图1所示的错误。环境为k8s的service部署模式

图一:

kubenetes 长连接怎么实现 kubectl connection refused_kubenetes 长连接怎么实现

分析原因

首先,因为环境是k8s的service模式部署的,所以刚开始我查看了我的debug端口是否打开了8999,发现是kubeProxy监听的所有主机。

kubenetes 长连接怎么实现 kubectl connection refused_jvm_02


tips:其实这里给大家一个提示,如果端口没有被监听,我们的客户端报的应该是connect timeout,所以如果是拒绝链接,那么可以肯定的是一定有进程监听你访问的端口

其次,查看自己的pod容器是否成功的进行了端口映射,命令 kubeclt describe pod <PodName>

kubenetes 长连接怎么实现 kubectl connection refused_kubenetes 长连接怎么实现_03


在容器的地方我们发现了三个tcp协议的端口映射,其中8999是我的debug端口,到这里基本上可以排除端口映射的问题了。

tips:后面会写一篇yaml文件配置端口映射的文章,这里不解释如何进行端口映射的方法了,这里给大家解释一下过程,首先远程机器连接到宿主机(k8s中称为node)的8999端口,被kube-proxy进程监听到,然后通过映射将报文发送给对应的pod(该pod是一个独立的网络栈,详情搜pause)的8999端口,pod再通过映射将报文发送给其下的docker容器(docker也是一个独立的网络栈)的8999端口,而监听docker端口的才是我们的程序。然后,接下来思路定位才定位到自己的程序是否出现问题,其实刚开始docker中没有netstat命令导致我没办法查看是否我的程序在监听端口,我其实很早就怀疑自己的程序了,但是没有完全怀疑,然后一直找办法判断是否自己的程序能够监听8999端口,最后,我找到curl可以在docker中使用,所以看了看help发现可以当telnet使用!于是使用了 curl -v <ip>:<port>

kubenetes 长连接怎么实现 kubectl connection refused_kubernetes_04


tips:尝试了几个没有监听的端口发现,curl中没有被监听的端口是会被拒绝的,而监听的端口不会拒绝,会是其他信息,比如

kubenetes 长连接怎么实现 kubectl connection refused_docker_05


到这里基本就判定自己的程序有问题,然后,通过苦苦搜索才发现,原来有一个惊天大秘密,自己从来没有注意过的。。。

java命令语法:

kubenetes 长连接怎么实现 kubectl connection refused_docker_06


我们注意到 其实下面的options全都应该放在 -jar 的前面才能生效,如此问题解决。。。

kubenetes 长连接怎么实现 kubectl connection refused_kubenetes 长连接怎么实现_07


包括help中的所有options都适用

解决方法

将所有options都放到-jar前面才会生效

思考感悟

其实这个问题我问过之前一起工作过的前同事,因为之前一起开发成熟的项目,所以开发流水线化导致我们都没有注意过这种问题,后来我问过他发现他也不知道,但是配置确实是在前面,他也不知道为什么在前面。。。。作为初学者的我们,其实这些细节和坑确实需要我们自己去踩过才能知道为什么。而这种排查问题的经验恰恰是书本给不了我们的宝贵财产。