構建高效能ASP.NET網站之三 細節決定成敗

來源:互聯網
上載者:User

問題的描述

 

  首先,描述一下故事的背景:(希望大家耐心的故事讀完)

  在網站中,網頁中的分頁控制項每次顯示10條資料,每次點擊下一頁,就再次去取下一個10條資料。至於分頁的方法怎樣做,方法有很多,相信這點大家都知道。

 

  過程是這樣的:在使用者請求資料的時候(考慮到了使用者的操作和網站的訪問量)我會第一次取出500條資料,然後把資料放在緩衝中,也就是說,我取出了50頁的資料,放在緩衝中,這樣如果,以後使用者請求第一頁到第49頁的時候,就直接從緩衝中拿資料。

  如:

  

 

  第一個資料區塊:

 

  採用索引值對的形式:字典儲存

 

 

  如果使用者請求到了49頁以後,那麼就再次從資料庫中取出下一個資料區塊(包含501到1000資料),然後,現在記憶體中就有了1000條資料。

 

  至於緩衝多久,資料什麼失效,失效後怎麼做,這裡暫不談論。(網站在這種緩衝策略下啟動並執行很好)。 

  代碼如下:

 

List<Product> products=GetDataFromCacheOrDatabase(condition,pageIndex,count….);

 

 

  代碼的意思很清楚,從緩衝中拿資料,如果緩衝中沒有對應的資料,那麼就先從資料庫中拿500條資料,然後放在緩衝中,最後返回10條資料。

 

  後來,因為某些功能的需要,需要返回當前頁的前6頁資料和後6頁的資料,例如:如果當前頁是第12頁,那麼就要返回12頁之前6頁Product(也就是第6,7,8,9,10,11頁的資料),和第12頁後的頁的Product(第13,14,15,16,17,18頁的資料)。 

  如下:

  

 

 

  當然,如果當前頁是第5頁,那麼就把之前所有5頁的資料都返回,另外再加上第5頁之後的6頁資料。

 

  這裡就可能涉及到跨塊擷取資料,如:

  如果當前頁是第48頁的時候,那麼返回前6頁資料是沒有什麼問題的,那麼後6頁的資料就不足了,因為49,40也得資料可以從緩衝的資料區塊中取到,至於51,52,53,54頁的資料,就需要再次從資料庫中讀取,然後再次緩衝(如果事先沒有被緩衝)。

 

 

  最後在緩衝中的資料如下:

 

   

  然後調用方法:(偽碼)

 

 

List<Product> products=GetDataFromCacheOrDatabase(condition,42, 126….); 

 

 

  上面傳入的是從第42頁開始的資料,也就是第48頁的前6頁和後6頁的資料。

  這個方法的內部實現是這樣的:

    1.    首先從第一個資料區塊中取出42頁到50頁的資料

    取出資料後儲存在一個List<Product> firstProductList;

    2.    從第二個資料區塊中取出從51頁到54頁(如果第二個資料區塊在緩衝不存在,就去資料庫中取501-1000條,然後再放在緩衝的第二個資料區塊中)。

    儲存在第二個List<Product> secondProductList

    3. 然後把兩個list合并,返回結果。例如

           secondProductList.Foreach(u=>firstProductList.Add(u));

 

  基本的實現就是這樣,看起來還行,也比較的合理,但是就是因為這個操作,從而導致伺服器記憶體溢出。

  大家想想看是什麼原因。

 

  細節的重要性

 

  其實緩衝的資料不是很多,是不足以讓伺服器記憶體溢出的,但是伺服器還是出現了out of memory的異常。之前一直跑的很好,就是改了代碼之後才出現問題的。

 

  其實這就是由於一個最基本的錯誤產生的:參考型別。

  下面就來分析下:

  首先是從第一個資料區塊中取出資料,然後用

    List<Product> firstProductList 引用指向取出的資料

  然後從第二個資料區塊中取出資料,用

    List<Product> secondProductList指向資料的引用

 

  如

 

 

 

  在第三步中採用

 

    secondProductList.Foreach(u=>firstProductList.Add(u));

  把secondProductList中的資料加入到firstProductList中,就因為是參考型別,其實實際操作的結果是:不斷的在改變第一個資料區塊中的資料,使得第一個資料區塊中的資料逐漸的變多。

  現在當前頁是48頁,採用上面的操作,致使第一個資料區塊中的資料增加了60條,

  如果使用者再次翻頁,到了49頁,那麼第一個資料區塊中的資料又增多了60條

  依此類推,最後導致了伺服器記憶體的不足,致使伺服器崩潰了。原本的“功臣”----緩衝卻成為了罪魁禍首。

 

  其實這個問題的解決,只要改變一點點的代碼就行了:

    List<Product> firstProductList;

    List<Product> secondProductList;

  然後

  List<Product> resultProductList=new List<Product>();然後分別把firstProductList,secondProductList遍曆,加入到resultProductList就行了。

就這麼簡單。

 

  一個小的細節,導致了大的問題。 

  

  不要忽視每一個細節。不要做沒有比較的迴圈等操作,一定要審視代碼,重構代碼。 

  今天就寫到了這裡,囉嗦了這麼多,希望對大家有一點點的協助。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.