“這條數據不是我填的”“我的更新被覆蓋了”“兩個設備顯示不一致”——這些是產品上線后最令人頭疼的反饋。
最近我們在一次用戶同步問題排查中,發現表面是“數據丟失”問題,實則是多端數據提交時間戳處理不一致,導致后臺認為老數據為新,覆蓋了正確內容。這類問題通常日志無法直接反映,需要從網絡請求行為層級來全面還原。
本文是一次跨平臺同步數據錯亂排查的抓包實錄,目標是展示如何用多工具組合方式,精確還原并定位導致數據錯誤的根因。
現象:多端編輯同一條數據,最終內容不一致
這是一個允許多端編輯草稿的功能,支持自動保存。用戶在Mac編輯后,又在iOS端補充內容,結果上線后發現,iOS端的“舊數據”覆蓋了Mac上的新輸入。
后臺數據庫記錄顯示兩次請求都成功落庫,時間相近。沒有接口報錯、沒有崩潰、沒有異常日志。系統按流程完成了一切,但結果是錯的。
拆解抓包需求:哪些信息需要被還原?
我們決定還原客戶端提交數據時真實傳輸內容,重點關注以下幾點:
- 請求是否攜帶本地生成的時間戳或版本號?
- 不同端是否使用相同時間基準?
- 服務端是否信任客戶端時間排序?
- 是否存在重復請求/數據重放等行為?
工具分工與分析流程
工具 | 使用目的 | 階段 |
---|---|---|
Charles | 抓取Mac端數據提交請求,記錄Body與Header | 桌面端行為分析 |
Sniffmaster | 抓取iOS端App請求,解密HTTPS并獲取數據體 | 移動端行為還原 |
mitmproxy | 攔截并打印提交請求,分析時間戳與數據變化邏輯 | 請求內容細節驗證 |
Wireshark | 輔助判斷請求是否被重發/中斷/覆蓋 | 網絡層分析 |
抓包發現的第一個關鍵信息:客戶端本地生成時間戳
在Charles中查看Mac客戶端請求時發現,提交內容中有一個字段client_ts
(客戶端時間戳),用于版本判斷。服務端以此值判斷“哪個數據是最新的”。
隨后用Sniffmaster抓取iOS端的請求,發現其client_ts
值明顯小于Mac請求中值,盡管是后發請求。
進一步調查發現,iOS設備的系統時間設定與服務器相差約40秒,導致其生成的時間戳落后。
由于服務端邏輯采用“較大時間戳為準”機制,這直接導致服務端認為“iOS的數據更新較新”,從而用舊數據覆蓋了正確草稿。
請求行為鏈進一步分析:是否存在補發或重復提交
我們啟用mitmproxy腳本,對請求攔截并輸出數據體與Header內容:
def request(flow):if "/draft/submit" in flow.request.path:print(flow.request.content.decode())
同樣,Sniffmaster本身也自帶JavaScript攔截器功能,可以做到抓包的同時直接攔截請求和響應。
分析5次請求發現:
- iOS端存在一次“App重啟后自動重發”的行為,補發的請求再次使用了緩存舊數據和舊時間戳;
- 請求中并無版本ID或唯一ID,無法做去重判斷;
- 服務端也未對內容變化做判定,僅以時間戳排序處理。
網絡層次驗證:是否存在丟包或重傳導致數據重發
通過Wireshark觀察發現:
- 某一次iOS請求因網絡抖動導致連接關閉;
- SDK自動重試機制補發上一次請求,未生成新時間戳,僅重發原數據包;
- 這次重試在服務端無日志記錄為“重發”,僅認定為一次獨立提交。
問題復現與多端驗證策略
為了確保問題可控可復現,我們制定以下驗證流程:
- 設置iOS設備系統時間落后1分鐘;
- 在Mac上提交內容,確保服務器記錄版本時間;
- 在iOS端重啟App并打開編輯頁面;
- 不修改數據,觀察其是否自動提交;
- 使用Sniffmaster和mitmproxy再次抓包確認數據結構一致性;
該流程成功復現了“舊內容覆蓋新內容”的行為鏈。
修復策略與流程優化
本問題不在于請求報錯或接口失敗,而是數據同步機制未能區分“補發的舊數據”與“用戶主動提交的新數據”。
綜合抓包信息后,我們調整:
- 客戶端提交請求增加唯一版本ID(UUID),服務端以其為準判斷冪等;
- 所有平臺統一調用系統時間基準(UTC)而非本地系統時間;
- SDK補發請求添加“來源標識”,避免誤判為新提交;
- 針對“草稿覆蓋”場景設計雙向合并提示機制;
總結:可用不等于正確,抓包的價值在于還原行為路徑
抓包并不總是為了處理接口錯誤,更多時候,它幫助我們理解系統在真實運行時的每一個步驟,尤其是那些“行為正確但結果錯誤”的場景。
在這次分析中,Sniffmaster在還原iOS端真實請求、解密HTTPS內容、識別字段差異方面起到了作用,但整個問題的分析離不開Charles、mitmproxy與Wireshark的協同。
最終我們不是發現了Bug,而是找到了“被誤判為正確”的一系列行為。這也是抓包的意義:不僅僅看得見,還得看得全、看得準。