按照慣例先談談最近狀況,最近不是恰好跨年嗎?看到不少人都在寫年度總結,因此我也在寫年度總結文章(其實以前我基本沒有寫過的,今年有點感觸,也想記錄一下),結果發現寫起來有點多,以前還想着元旦前發出來,結果元旦事後,今天我也還在寫,並且還寫不完,不過也差很少了,預計明天會發出來。而後最近需求比較多,工做比較忙,同時遇到了一個比較麻煩的需求,就想着記錄一下,先充當一下這周的文章任務😂。html
最近,我在公司作這樣的一個事情,整理老舊的api服務,須要統計接口的每一個請求的ip和請求參數,找出對應的調用的ip,以便通知業務方修改成新的api服務。其中咱們的這個api服務調用有分爲thrift調用和http調用,因爲以前的舊的服務設計比較簡陋,沒有經過dubbo 等註冊中心調用,也沒有完整的監控(不要問我爲何沒有,我也很無奈😭),致使我想找出調用ip也找不到,日誌裏面沒有記錄。java
剛開始咱們是想修改原業務代碼,加上調用ip和請求參數的日誌打印的。本來覺得不會有什麼問題,可是咱們準備開始動手改造的時候,發現http協議提供的接口,比較好改造,直接 httpRequest 能夠獲取到客戶端ip ,請求參數也很好打印。接着咱們打算動手也修改一下thrift 接口的那部分,本來覺得都是接口,估計thrift框架也會提供對應的方式獲取(咱們使用的原生的apche thrift 框架來提供服務),因而網上找了一下,發現thrift 接口好像並 http 接口那麼好改造,網上說須要加個監聽類,監聽請求,相似如下狀況:git
/** * 調用RPC服務的時候觸發 * 每調用一次方法,就會觸發一次 */ public void processContext(ServerContext serverContext, TTransport inputTransport, TTransport outputTransport) { /** * 把TTransport對象轉換成TSocket,而後在TSocket裏面獲取Socket,就能夠拿到客戶端IP (這裏有可能轉化不成功的,inputTransport 不必定爲 TSocket 類來的,還有可能爲 TFrmef ,這裏依賴於thrift 提供服務的方式 ) */ TSocket socket = (TSocket)inputTransport; System.out.println(socket.getSocket().getRemoteSocketAddress()); }
參考:兩種方式獲取Thrift調用的客戶端IP地址
https://blog.csdn.net/mn960mn/article/details/50585278apache
可是,咱們實際操做的時候,建了這個監聽類,起了本身的本地服務,並用單元測試去測試的時候,發現報瞭如下這樣的一個錯誤。ubuntu
org.apache.thrift.transport.TFramedTransport cannot be cast to org.apache.thrift.transport.TSocket
說TFramedTransport 不能轉成 TSocket 這個類 ,估計是實例類跟要強轉的類不一致。api
一開始,還覺得本身的寫錯了,對着網上的博客檢查瞭如下沒有問題。只是發現這個實際實例化出來的類不是 TSocket 類型。試了幾回後,發現仍是不行,因而有根據這個錯誤在網上找了一下,TFramedTransport 獲取 IP(參考這個錯誤描述: https://www.oschina.net/question/858822_2182069) 。這才發現,咱們的thrift接口提供方式跟網上說的不同,而咱們這種狀況,若是須要獲取Client Ip ,有這幾種方式:1. 修改thrift 框架源碼, 2. 從新繼承TFramedTransport類重寫裏面的一個方法。微信
看到這兩種方法,咱們一會兒就放棄了,本來想着只是簡單加個監控,沒想着修改太多東西,若是爲了見這樣一個監控,改動那麼大的,懼怕影響業務(咱們這個api服務仍是挺多業務方在使用的)。網絡
因而,咱們考慮起第二種方案,使用抓包去打印出客戶端ip和請求參數。tcpdump
是一開始就會想到的工具,當用 tcpdump 去抓包的時候,發現 thrift 接口有些是亂碼的。接着就網上找一下是否thrift接口的監控工具,一圈下來,說 thrift-tool ,wireshark(tshark)可使用,而後又去試了,安裝了挺久的,發現因爲咱們機器的ubuntu的版本過久了,安裝不了最新的 thrift-tool (這個是安裝以後,還要依賴tcpdump的版本,tcpdump版本太老也不行,tcpdump命令重裝也重裝了好久😰,最後發現也安裝不了指定版本)和 wireshark ,發現都沒有辦法使用這兩種工具。考慮到咱們這個api服務都部署在不少老的物理機上面,考慮兼容性問題和能夠方便在其餘機器上也部署(咱們這個api服務分別部署在10多臺的物理機上)。框架
因而又從新考慮回tcpdump 命令了兜兜轉轉一圈又回到原點, tcpdump 🐮逼。簡單實驗了一下,抓包的出的thrift請求參數和響應結構,若是是英文的,大部分仍是能正常顯示的,能夠根據 判斷是否包含 接口請求參數英文關鍵字 和判斷目標ip和端口,獲取到對應的請求參數和的請求ip。若是發送的參數爲英文tcpdump直接抓包是能顯示大部分參數的,須要完整的參數信息也能夠經過直接在業務代碼中加監控,thrift 接口在代碼中監控發送請求參數仍是挺簡單的,主要是獲取請求ip有點麻煩。socket
大概命令是這樣的(這裏假設read爲請求參數關鍵字)
tcpdump -i any -A -s 0 'tcp port 9521' | grep -E "read|> [0-9\.]+9521"
這樣就能夠獲取到 thrift 接口請求到的 9521 端口 的訪問ip和請求參數,不過打印出來的日誌,還須要本身的去處理一下的。基本上的請求參數的上一行就是該請求的ip。
這篇文章主要介紹瞭解決獲取 thrift接口 的請求參數和客戶端請求 ip 的問題。算做記錄一下本身的解決問題的流程。其中順便了解一下抓包工具 wireshark 的使用,以前一直有據說過這個軟件,可是一直沒有實際使用過,感受的確好用。 另外算做也提醒本身在搭建api服務的時候,記得作好每次接口調用ip和請求ip的監控,否則後面接手的人查起來真的想崩潰,例如:我😪。
這篇也算一篇比較水的文章吧,不過我本身從此次解決問題中仍是學到了不少東西的,稍微記錄一下:
tcp and ip.addr == 127.0.0.1 and thrift
命令設置在 dispaly filter 來獲取目標的請求, thrift 表示協議,不過若是wireshark 版本過低的話,能夠識別不了這個協議。sudo tshark -s 512 -i eth0 -n -f 'tcp dst port 9521' -l
tshark 的命令,捕捉tcp 的請求的,參考: https://www.cnblogs.com/liun1994/p/6142505.html