線上問題排查,一不當心踩到阿里的 arthas坑了

最近幫新來的校招同窗排查一個線上問題,問題自己不是很難,可是過程當中踩到了一個arthas的坑,挺有意思的。css

同時,也分享下在排查過程當中使用的一些比較實用的工具,包括tcpdump、arthas、simpleHTTPServer等,但願能對你們有所幫助。html

1.問題描述

新開發的一個功能,簡單來講,就是讀取數據庫的數據展現在前臺。java

本地啓動服務調試,用postman調用api,返回數據顯示正常,數據中的中文也正常。python

可是部署到線上環境後,經過chrome瀏覽器調用和postman調用接口,返回的非中文數據正常,可是中文顯示亂碼。linux

2.排查思路

這個問題的第一反應是請求的content-type有問題。nginx

不過在chrome瀏覽器中確認了請求的request和response的content-type都是application/json;charset=UTF-8,沒有問題。git

而後又google了一番亂碼問題,基本上都是說的spring的HttpMessageConverter問題或者content-type,都沒法解決。github

只能深刻排查一番了。web

排查的主要思路就是先肯定亂碼是哪一步產生的。面試

  • 一個就是數據庫裏查出來地方,須要用抓個包確認下,不過咱們本地服務調用是正確的,那麼這一步應該沒有問題。
  • 一個是應用服務返回的地方,須要用抓個包確認下。在線上部署環境裏,用tcpdump把對應的應用服務返回數據是抓個包。
  • 一個就是代碼邏輯中存在數據轉換,這個須要經過arthas看看線上應用的運行時數據狀況。

3.用tcpdump抓包看服務端響應

3.1 什麼是tcpdump呢?

tcpdump是linux下的網絡數據包截獲分析工具。在linux的平常網絡管理中,tcpdump的使用頻率很高,熟練掌握對提升工做效率頗有幫助。

線上問題排查,一不當心踩到阿里的 arthas坑了

 

3.2 報文抓取

爲了獲取對應服務的請求報文,須要登陸對應的服務器(或者k8s的pod)使用tcpdump進行抓取。

做爲一個暖男,我把從安裝到使用都一步步記下來給你 :)

1)安裝工具

若是你的服務器上沒有安裝過tcpdump,能夠先執行如下命令安裝

yum -y install net-tools

2)查看網絡狀態

若是服務上有多個網卡,能夠經過如下命令查看

Netstat -i
線上問題排查,一不當心踩到阿里的 arthas坑了

 

3)部署抓包

tcpdump -i eth0 tcp -w xxx.cap
  • en0表示監聽的網卡
  • tcp表示報文類型
  • -w 指定輸出文件名

還有不少其餘選項能夠過濾使用,你們能夠網上搜一下,這裏就不展開了。

4)調用請求

部署了tcpdump後,對服務器發起api請求。這時候相關的tcp報文都會被輸出到 xxx.cap文件中了。

3.3 報文解析

1)把xxx.cap文件發送本地

通常可使用scp命令,直接發送

scp xxxx.cap admin@10.xxx.xxx.xxx:/path

在傳輸服務器的文件到本地時,若是scp不方便使用,好比一些防火牆限制。

也可使用 python 在服務器上開啓一個 web 服務(端口可自定義)。

線上問題排查,一不當心踩到阿里的 arthas坑了

 

python -m SimpleHTTPServer 18888 &

而後在本地使用 wget 下載文件便可。

2)解析cap文件

本地獲得cap文件後,能夠經過wireshark軟件對cap文件進行解析,獲得以下結果。

線上問題排查,一不當心踩到阿里的 arthas坑了

 

線上問題排查,一不當心踩到阿里的 arthas坑了

 

線上問題排查,一不當心踩到阿里的 arthas坑了

 

對api的報文進行解析後,發現返回對中文已是亂碼了,確認了在服務端發出的響應內容中,已是亂碼了。

因此,只能繼續排查應用自己的問題。

4.用arthas排查線上運行代碼

Arthas 是Alibaba開源的Java診斷工具,當你遇到如下相似問題而一籌莫展時,均可以嘗試使用Arthas(更詳細的用法參考官方文檔:https://arthas.aliyun.com/doc/quick-start.html):

  • 這個類從哪一個 jar 包加載的?爲何會報各類類相關的 Exception?
  • 遇到問題沒法在線上 debug,又不想頻繁加日誌再從新發布
  • 線上遇到某個用戶的數據處理有問題,但線上一樣沒法 debug,線下沒法重現!

4.1快速安裝、啓動

curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar

4.2 運行代碼返回排查

本次排查,就使用了arthas的watch功能(更詳細的用法參考官方文檔:https://arthas.aliyun.com/doc/watch.html),能方便的觀察到指定方法的調用狀況。能觀察到的範圍爲:返回值、拋出異常、入參。

咱們先看看線上運行應用controller層對於請求的響應,無需添加日誌從新部署,咱們立刻就能看到線上代碼的返回結果。

watch xxx.xxx.controller method "{params,returnObj}" -x 2

而後發起api調用,在arthas中顯示結果以下:

線上問題排查,一不當心踩到阿里的 arthas坑了

 


咱們能夠看到,這個controller方法返回的內容就是亂碼了。

所以,說明是代碼邏輯中存在轉換的問題了。

5.問題定位

根據業務邏輯,基本能猜想是從業務中的 byte[] 轉string的時候出現問題了。

找到對應代碼以下,new string()時沒有指定字符集:

線上問題排查,一不當心踩到阿里的 arthas坑了

 

所以會在轉換過程當中,默認讀取系統變量的file.encoding做爲字符集。

線上問題排查,一不當心踩到阿里的 arthas坑了

 

線上問題排查,一不當心踩到阿里的 arthas坑了

 

線上問題排查,一不當心踩到阿里的 arthas坑了

 

而後咱們用arthas直接查看系統變量,果真不是utf8。

線上問題排查,一不當心踩到阿里的 arthas坑了

 

因此,解決方案有兩個。

第一種是在new string(bytes) 時指定字符集。

第二種就是設置系統變量file.encoding=utf-8。

 

6.進一步踩坑

咱們一開始選擇了代碼修復,在代碼中轉換時指定字符集。

線上問題排查,一不當心踩到阿里的 arthas坑了

 

從新發布後,再用arthas觀察一下,發現居然仍是亂碼?!!

而後從新回頭在代碼中看了好久,一直找不到緣由,陷入了僵局。。。

 

忽然,隨手看了下線上,發現線上已經顯示正常了,納尼?是arthas有問題?

而後google了一下,發現不少人碰到arthas顯示中文亂碼的問題。。。

解決方式也比較簡單,啓動arthas的時候,也指定一下字符集。

java -jar -Dfile.encoding=UTF-8 arthas-boot.jar

而後問題解決了。。。呵呵。。。

這時候再觀察arthas的結果已經顯示正常。

這說明了什麼?!!!!

Arthas輸出界面的時候,確定在字符串轉換的時候,也沒有指定字符集。。。。

一腳踩了個連環坑。。。

線上問題排查,一不當心踩到阿里的 arthas坑了

 

7.總結

其實整個問題是比較粗淺的,就是最後這個arthas的中文亂碼讓人有點腦袋疼。。。

固然,最主要仍是簡單分享下tcpdump、arthas、simpleHTTPServer這些小工具,但願能有所幫助吧。

 

都看到最後了,原創不易,點個關注,點個贊吧~
文章持續更新,能夠微信搜索「阿丸筆記 」第一時間閱讀,回覆關鍵字【學習】有我準備的一線大廠面試資料。
知識碎片從新梳理,構建Java知識圖譜: github.com/saigu/JavaK…(歷史文章查閱很是方便)
相關文章
相關標籤/搜索