發現了乙個關於 gin 1 3 0 框架的 bug

2022-01-24 09:39:14 字數 1892 閱讀 5789

客戶端同時發起多個http請求,gin接受到請求後,其中乙個介面響應內容為空,另外乙個介面響應內容包含介面1,介面2的響應內容,導致響應資料錯亂(偶現問題)

因為此問題是偶現問題,有時響應資料又是正常的,而且本次新版本這兩個介面**也並沒有修改,所以排查問題花了很長時間,下面是我一步步排查問題的過程.

首先懷疑是**邏輯問題,通過review介面**邏輯後,這兩個介面邏輯都非常簡單,且沒有任何邏輯關聯,所以基本上排除了介面邏輯問題。

懷疑是否是併發請求導致的問題,通過golang並且開啟多個協程模擬併發發起http請求同時呼叫這兩個介面100次,並沒有復現出這種問題,所以可以排除併發請求導致的問題。

因為使用golang同時呼叫這兩個介面沒有復現此問題,懷疑是否是客戶端呼叫的問題,是否共用了乙個http連線傳送請求,導致最終響應結果合併到了一起? review客戶端**後,發現**邏輯也沒有什麼問題,並且通過抓包後卻發現的確是後台響應的資料就有問題,所以可以確認就是後端的問題。

此時有同事建議列印一下兩個介面後台請求和響應的物件記憶體位址看一下,是否是共用了同乙個物件導致,果然列印之後發現,當資料錯亂時,兩個介面使用的是同乙個物件,兩個介面沒有任何邏輯關係,為什麼會使用同乙個請求物件? 為什麼就兩個介面會出現資料錯亂的問題? 難道是gin框架的問題? 此時我們嘗試著除錯**去驗證

此時我觀察到每次這兩個介面請求後面,都跟著另外乙個介面請求,如圖1所示的第2494條請求 /api/client/area/scenes 介面,並且本次新版本功能改動了這塊的邏輯,會不會是受這個介面的影響了,於是我嘗試恢復了這塊的**,恢復後測試多次發現問題無法重現,所以可以斷定是受了這塊**的影響.

然而本次修改的**邏輯主要是為了相容老版本的客戶端,為此介面新增了乙個中介軟體,引入了gin框架的handlecontext(context) 方法,用來做乙個統一的中介軟體,做路由的**,具體**邏輯如圖4所示.

gin框架為golang web開發中,很常用的框架,使用人員非常多,這麼明顯的問題不可能沒人發現,雖然極力的認為不可能是框架的問題,但是事實表明就是這裡的問題,於是通過查詢資料發現,此方法的確可能出現問題,如圖5所示

可以確認gin框架有問題了,可是原因是什麼了?網上並沒有詳細的說明,於是我打算通過除錯閱讀原始碼的方式來測試,在閱讀原始碼的時候我發現,本地**和gin最新的官方原始碼已經不一致,於是我發現本地**版本為1.3.0,而官方**已經更新到1.6.3了, 如圖6所示: 1.6.3已經刪除了 engine.pool.put(c) 此行**

於是我嘗試者把gin版本從1.3.0公升級到1.6.3,看看問題是否已經解決,果然gin版本公升級後,連續測試多次未能重現問題,所以可以確定就是這裡的問題,並且問題已經解決

雖然問題已經解決了,但是為什麼刪除了這一行就可以了? 好像並沒有搞清楚具體的原理是什麼? 於是我嘗試著繼續分析原理

通過如下圖7也可以看到 handlecontext 方法上面有乙個 servehttp 方法,可以明顯看到此方法也呼叫了 engine.pool.put(c) 方法,並且也呼叫了 engine.pool.get().(context) 方法,通過除錯發現 servehttp 為http請求通用的方法,所有請求都會先呼叫 servehttp ,如果呼叫了 handlecontext 則會再呼叫 handlecontext ,具體執行順序如下圖7所示,如圖可以看出來 engine.pool.put(c) 會執行兩次,這樣就會導致在sync.pool存在兩個同樣的物件,在後面的請求中通過 engine.pool.get().(context) 獲取context物件時就會獲取到相同的context物件,導致responsewriter指標一樣,從而導致響應資料輸出到同乙個介面中.

此次問題主要是使用了低版本的gin框架所致,所以可以看出即使再成熟的框架,也可能會存在bug,在實際開發過程中應該及時公升級到框架的最新穩定版本, 這樣可以防止一些潛在的bug,當發現一些未知的問題,不要憑空猜測,要盡可能的除錯**,找到問題的根本原因.

發現了乙個jython的bug

最近想用jython寫乙個simulator,用到struct.pack 結果發現了裡面的乙個bug.如下 import struct dataunits struct.pack hhiiibbhq 0x20,0x1c,0xffffffff,0x00000000,0x0233,0x05,0x00,0...

我發現了VS的乙個秘密

今天在做新聞發布系統的時候,遇到了這樣乙個問題,就是我在寫sqlhelper這個類的時候,明明已經引用了system.data這個命名空間,但是在寫的時候datatable卻寫不出來。大家可以看一下我是怎麼引用的。第二步 選中然後確定 但是我在 裡面並沒有寫using system.data 所以輸...

我發現了VS的乙個秘密

今天在做新聞發布系統的時候,遇到了這樣乙個問題,就是我在寫sqlhelper這個類的時候,明明已經引用了system.data這個命名空間,但是在寫的時候datatable卻寫不出來。大家可以看一下我是怎麼引用的。第二步 選中然後確定 但是我在 裡面並沒有寫using system.data 所以輸...