服務器遷移踩的坑

一、問題由來

  當前參與開發的項目已經上線,並且發佈了很多個版本,在服務器上面穩定運行。最近接到通知,需要做服務器遷移,

遷移的東西很多,服務應用需要遷移,數據庫需要遷移,redis緩存數據庫緩存需要遷移,還有網關服務,配置中心服務等等。

反正一聽到這個消息,就知道工作量不小,還好這一塊主要是負責人在做,自己作為開發人員也會參與遷移,比如協助測試

人員判斷問題是由於業務引起的還是系統遷移導致的。如果在測試過程中發現其他問題,也需要積極的配合解決。

測試環境首先進行遷移後,測試人員正在進行系統功能正確性的驗證,測試結果一切正常。然後高級測試人員開始進行系統

性能的測試,立馬發現問題,有兩個對外提供服務的接口性能不達標,讓我們開發去看一下是怎麼回事。自己立馬找測試人員去

測試,測試的結果確實很慢,好幾次請求都需要20s左右才能返回數據,這麼慢系統還怎麼用呢?

二、問題分析

   發現問題後,我立馬在原來的測試環境進行驗證,並沒有復現同樣的問題,原來的測試環境請求同樣的接口,傳遞同樣的參數

請求時間都正常,1s內能夠正常返回數據,那這到底是怎麼回事呢?下一步能夠想到的辦法就是在這兩個接口中的關鍵位置打印日誌,

通過打印的日誌來判斷到底是哪個地方出的問題。自己在最開始開發的時候只打印了少量的日誌,還不足以排查目前遇到的問題。添加

日誌後,重新部署,發現某一個數據過濾的方法被頻繁調用,並且每調用一次就需要從緩存中去取一次數據,負責人初步判斷就是由於

這個方法在執行的時候,花的時間太長,導致程序執行慢,讓我立馬去查看。

三、解決方案

  初步找到問題後,自己開始對這個問題進行分析,兩個接口裏面都處理了同一種類型的數據,那基本可以判斷就是在處理這種類型

數據的時候太慢,導致性能出現問題。接口獲取數據的方式很簡單,先從緩存中獲取數據,然後過濾,之後是做計算處理,有的數據不能

直接返回,最後是轉換為調用方需要的格式進行返回。問題就出在數據過濾這一步,過濾的方式也很簡單,首先循環原有的列表數據,拿到

主鍵ID,在嵌套循環用戶請求時傳入的多個編碼進行過濾,從緩存中取數據。假設列表數據有100條,用戶傳入的過濾編碼有5個,那麼

從緩存中取數據的次數就是100 * 5 = 500次;

  按照系統原有的設計,所有編碼對應的權限數據,都會存入緩存中,因此優化方案為,先從緩存中根據用戶傳入的編碼,取出當前用戶所

具有的權限列表,然後在根據這個權限列表去過濾列表數據。方案敲定之後,自己着手進行代碼改造,大致花了一兩個小時的時間才改造

完成。還是以上面示例,這時候取緩存的次數變為5次,就將用戶傳入的編碼對應的權限全部取出,取緩存的次數大大地減少。代碼修改

完成後,再次部署代碼進行測試,發現效率大大提升,單次請求的時間降低到2s左右。性能以肉眼可見的方式大幅度提升。

  代碼層面做優化後,繼續回來分析問題,原有測試環境也是採用同樣的處理方式,為什麼沒有出現這個問題呢?這就讓人很疑惑,代碼

是有優化的空間,之前生產上面的服務都是正常運行的,也沒有出現問題。然後繼續分析,生產上面的數據量比較少,只有不到200條的

數據。出問題的新環境,測試數據量在三百多導致請求非常緩慢,原有測試環境數據量也是在三四百的樣子卻正常。那基本可以判斷一點,新

環境的服務器性能比較差。修改完代碼重新部署後,性能已經極大的提升,可還是不能滿足系統設計的要求。經過負責人的進一步排查,確定是

redis服務器非常慢導致的一部分原因,原有測試環境redis使用的物理服務器,所以性能很好。新環境使用redis雲服務器,網絡耗時太久,

導致性能跟不上。自此,總算是搞清楚導致接口查詢慢的所有原因,問題解決方案也已經敲定,讓自己學習到的最重要的一點就是嵌套循環一定

要慎用,一不留神就會導致效率大大地打折扣,認真吸取這次深刻的到經驗教訓!