关于远程调试的几点尝试

阿凡达2018-07-09 09:49

关于远程调试的几点尝试

0.背景

最近刚刚转做后端开发,作为一个入门级菜鸟,遇到bug在所难免。为了快速定位bug原因,自然想到了对webapp在测试环境下进行远程调试,本来以为及其自然的事情,实现起来却一波三折。主要门槛在于办公网络和测试机房无法直接连通,IDE的远程调试功能就这样废了。经过讨论得到可行的解决方案如下:

  • 办公网部署一套应用,可以直接调试。
  • 放弃debug,增加详细的debug日志定位问题。

对于方案一,在项目初期或许可行,但是随着依赖和复杂度的上升,在办公网要正常部署运行起来几乎不现实。

方案二是一个看似可行的选择,但是日志的完整性对经验要求较高,刚刚入门很难事先覆盖全面,遇到问题再补日志的话又费时费力,效率太低。而且对于不可重现的bug,一旦重启破坏现场之后,只能根据qa同学的描述分析代码。

那有没有办法可以突破网络的限制呢?

1.尝试方案

要突破网络限制,通过外网访问到测试环境,只要反向代理即可,可是Nginx无法转发connect指令,而JVM调试协议目前IDE又采用TCP通道。socks代理原理上可以搞定,但是为了方便控制和权限管理,还是决定自己造轮子,实现tcp的转发。

 

整个服务分为三部分

LocalProxy

本地代理,IDE直连,对IDE来说充当要调试Target,其负责链路的初始化,以及后续把所有的调试指令和数据转发给GatewayServer

GatewayServer

需要部署在有外网ip的测试机上,负责访问管理服务,完成认证并向管理服务请求通达实际调试目标的路径

RemoteServer

部署在调试目标的同一机器上,负责传递数据给JVM调试端口,监控调试状态,重启目标程序。

除此之外,还有一个管理服务,负责用户权限管理,调试机器管理,以及分配认证token给local proxy,以及根据当前的负载情况分配最佳路径。

方案看起来可行,可是当开发完成准备部署的时候却被运维同学“无情”的拒绝了(大哭),由于目前测试环境的一些不可描述的原因,不适合部署这套服务。

2.继续尝试

既然如此,那有没有办法在不改变现有网络配置的情况下,让调试也能跑起来呢?

现在办公网访问测试环境只有两种方法,Nginx反向代理Http服务以及SSH通过跳板机访问。

于是对方案进行修改和简化

主要改动点在于去掉Gateway Server,由Nginx充当。

Local Proxy 由TcpServer和HttpClient组成,拿到调试数据,把tcp数据封装在Http Request中发送给Remote Prxoy。

Remote Proxy 由HttpServer和Tcp Client组成,获取到Http Request的数据之后,以tcp的方式发送给目标JVM

在实现过程由于jdwp协议并非完全切合http的请求响应模式,所以单次请求以一个完整的jdwp协议报文为分割。

JVM的回传的数据采用Http Long Poll实现。

3.后续

几经周折总算找到一个可行的办法,目前整个流程还有很多地方需要优化,感谢书记同学的帮助,如有感兴趣的同学欢迎找我一起讨论。

本文来自网易实践者社区,经作者唐杰授权发布。