最近帮一个新校招排查了一个线上问题。题目本身并不难,但过程中踩到一个阿尔萨斯陷阱就很有意思了。.同时,我也分享一些调查过程中用到的实用工具,包括tcpdump、arthas、simpleHTTPServer等,希望对大家有所帮助。1.问题描述新开发的一个功能,简单来说就是从数据库中读取数据,并显示在前台。在本地启动服务调试,用postman调用api,返回数据显示正常,数据中的中文也正常。但是部署到线上环境后,通过chrome浏览器调用和postman调用接口,返回的非中文数据正常,但是中文显示乱码。2.排查思路遇到这个问题第一反应是request的content-type有问题。但是在chrome浏览器中,确认请求的request和response的content-type都是application/json;charset=UTF-8,没有问题。然后google了一下乱码问题,基本上说的是spring的HttpMessageConverter问题或者content-type,无法解决。我只能深入调查。排错的主要思路是先判断是哪一步产生了乱码。一个是在数据库中找到的位置,需要抓包确认,但是我们本地服务调用是正确的,所以这一步应该没有问题。一个是申请服务返回的地方,需要抓包确认。在线部署环境下,对应应用服务返回数据时,使用tcpdump抓包。一是代码逻辑中有数据转换,需要通过artha查看线上应用的运行时数据。3.使用tcpdump抓包看服务器响应3.1什么是tcpdump?tcpdump是linux下的网络包拦截分析工具。在Linux的日常网络管理中,tcpdump的使用频率很高,熟练掌握它对提高工作效率很有帮助。3.2消息抓取为了获取相应服务的请求消息,需要登录相应的服务器(或k8spod),使用tcpdump进行抓取。作为一个暖男,从安装到使用一步一步的写下来给大家:)1)安装工具如果你的服务器没有安装tcpdump,可以先执行以下命令安装yum-yinstallnet-tools2)检查网络状态如果服务上有多个网卡,可以通过以下命令查看netstat-i3)部署抓包tcpdump-ieth0tcp-wxxx.capen0表示要监控的网卡tcp表示数据包类型-w指定输出文件名还有很多其他可以过滤的选项,大家可以上网搜索,这里就不展开了。4)调用请求部署tcpdump后,向服务器发起api请求。这时候相关的tcp包就会输出到xxx.cap文件中。3.3报文分析1)本地发送xxx.cap文件,一般可以使用scp命令直接发送scpxxxx.capadmin@10.xxx.xxx.xxx:/path从服务器传文件到本地时,如果scp使用不方便,比如一些防火墙限制。也可以使用python在服务器上启动一个web服务(端口可以自定义)。python-mSimpleHTTPServer18888&然后使用wget将文件下载到本地。2)解析cap文件在本地获取到cap文件后,可以通过wireshark软件解析cap文件,得到如下结果。分析api报文,发现返回的一对汉字已经是乱码,确认服务器发送的响应内容已经是乱码。所以只能继续排查应用本身的问题。4、使用arthas排查在线运行代码Arthas是阿里巴巴开源的Java诊断工具。当你遇到以下类似问题而束手无策时,可以尝试使用Arthas(更详细的用法参考官方文档:https://arthas.aliyun.com/doc/quick-start.html):这个类是从哪里加载的?为什么会报各种类型的相关Exception?遇到问题无法在线调试,又不想频繁添加日志才重新发布。线上遇到一个用户数据处理的问题,但是线上无法调试,线下也无法重现!4.1快速安装并启动curl-Ohttps://arthas.aliyun.com/arthas-boot.jarjava-jararthas-boot.jar4.2运行代码返回查看本次查看使用了arthas的watch功能(更详细的使用方法参考到官方文档:https://arthas.aliyun.com/doc/watch.html),可以很方便的观察到指定方法的调用。可以观察的范围是:返回值、抛出的异常、入参。我们先看在线运行的应用控制器层对请求的响应。我们不需要添加日志重新部署,马上就可以看到线上代码的返回结果。watchxxx.xxx.controllermethod"{params,returnObj}"-x2然后发起一个api调用,在arthas中显示的结果如下:我们可以看到这个controller方法返回的内容是乱码。因此,说明代码逻辑存在转换问题。5、问题定位根据业务逻辑,基本可以猜到是业务中byte[]转string时出现了问题。找到对应的代码如下,newstring()没有指定字符集:因此在转换过程中,默认会读取系统变量的file.encoding作为字符集。然后我们用arthas直接查看系统变量,果然不是utf8。所以,有两种解决方案。首先是newstring(bytes)时指定字符集。二是设置系统变量file.encoding=utf-8。5.进一步踩坑我们一开始选择了代码修复,在代码中指定了转换时的字符集。重新发布后,再次使用arthas观察,发现还是乱码?!!然后回头看了代码半天,找不到原因,陷入僵局。..突然,随便查了下离线线路,发现在线显示正常,纳尼?是阿尔萨斯的问题吗?然后google了一下,发现很多人都遇到了artha显示中文乱码的问题。..解决方法也比较简单。启动arthas时,还要指定字符集。java-jar-Dfile.encoding=UTF-8arthas-boot.jar然后问题就解决了。..呵呵。..此时观察arthas的结果已经显示正常。这说明什么?!!!!Arthas输出接口时,在转换字符串时一定不能指定字符集。...踩了一个连环坑。..6.总结其实整个问题比较肤浅,就是最后artha的中文乱码让人感觉有点头疼。当然最重要的还是简单分享一下tcpdump、arthas、simpleHTTPServer等小工具,希望能有所帮助。
