解決Ice 物件大資料量傳輸Bug

smilestone322發表於2015-01-05

轉自: http://blog.chinaunix.net/uid-24439730-id-144103.html

 

ICE 物件之間大資料量傳輸的Bug


    這兩天,上司給了一個之前版本的Bug,說是在現場發現的,讓儘快解決。由於公司專案管理上並不規範,Bug描述資訊很少,主要給了簡短的文字描述,和bug發生時介面截圖,連復現bug的步驟都沒有,最初只是當作效能bug對待的。以下是復現、解決bug的過程。
    通過分析,主要是認為ICE物件之間傳輸的資料量過大導致的問題,因此,搭建了環境,並製造了大資料量傳輸的情形,問題復現還算順利。但除錯、修復bug的過程確著實費了番勁。

1. 系統簡要描述
先描述下系統大致情況吧,如下圖所示
   

+-------------+
|      PHP    |
+-------------+
     | |
+-------------+
| ICE APP A   |
+-------------+
     | |
+-------------+       +--------------+
| ICE APP B   | ———|    DataBase   |
+-------------+       +--------------+


    PHP 伺服器程式呼叫ICE 應用A,有些業務A需要呼叫B,B訪問資料庫獲取到業務資料並通過 ICE 執行時傳送給A;當然PHP與A之間也是通過ICE通訊,IcePHP,系統是不是挺簡單?

2. GDB 除錯
   在Bug復現之後,就開始了GDB除錯,很快發現,在B從資料庫取回20000條記錄後,返回 A 時沒了響應;
於是,接下來在 A 呼叫B 的介面的前後插入了除錯程式碼,重新進行GDB除錯,發現程式碼沒有從 B 返回,根據經驗,要麼發生異常,要麼系統崩潰(很容易排除此可能)。這時去研究了下ICE的API,又發現了一個問題,A呼叫B時是可能丟擲異常的,而寫程式碼的人卻沒有去捕獲。我想,接下來我要做的工作,任何做這技術的人都清楚了,那就是去捕獲這個異常,檢視異常資訊。最終,發現是 MemoryLimitException。
    通過檢視 ICE Manual 知道,是因為傳遞的資料量超過了 Ice.MessageSizeMax 值,只需把該屬性值調大就可以了;不過很遺憾,我改過之後沒起作用,我在想為什麼沒起作用?於是,在程式碼中又插入了些除錯程式碼,取得 A、B 的 Ice.MessageSizeMax 的屬性值,很奇怪的發現 B 的該屬性值為0(即使用預設值,而不是真的為0), 也就是說在配置檔案中的配置沒起作用了。
    我想起在 Ice 文件中曾看到過, 一個 ICE 應用可以有多個通訊器,每個通訊器都是獨立的,各有各的配置(當然可能相同,完全取決於開發者);同時,B 的通訊器器就是A動態生成的,於是猜想可能跟這有關係,即不同的通訊器配置不同,其中使用的就是用預設配置的那個通訊器。
    於是我檢視了 A 生成 B 通訊器的程式碼,果然發現 A沒有給 initialize 函式傳遞配置資料,這導致A所使用的所有B的通訊器都是預設配置,也就是說在配置檔案中對 B 的配置都沒有任何作用了。
    不過,考慮到 PHP 與 A 之間也是 ice 通訊,肯定也存在這個問題。


3. Bug解決
    在定位到問題以後,解決方案也就出爐了:
   (1) 修改 A、B的配置檔案,修改(新增) Ice.MessageSizeMax 屬性值,使他為一個合適的值
   (2) 修改 A 的程式碼,讀取 B 的配置資料,用作分配 B 通訊器的配置
   (3) 修改 PHP 的 ICE配置,設定Ice.MessageSizeMax 屬性值為一個合適的值
  


修改之後,進行測試,問題解決。


 

相關文章