創建mvc web application,采用code first 的方式,MVC5,EF6.0 整了一個網站。開發完之后。直接publish。就這樣部署到服務器上了。
在使用過程中發現,網站打開的速度有點慢。而且每隔一段時間不使用,網站的打開速度就變慢。
問題分析:
一開始首先想到的是IIS的應用程序池釋放的問題。
后來配置了iis還是過一段時間訪問變慢。
后來為了快速解決這個問題,只能先做了一個bat文件,在服務器端模擬一段時間內訪問這個網站一下。這樣用戶在訪問的時候不會體會到網站的訪問速度變慢的問題。
@echo 正在關掉所有的IE進程(需要設置默認瀏覽器是IE) taskkill /im iexplore.exe /f /t @echo 正在通過ping來延遲80秒鍾,以方便IE打開頁面 ping 127.0.0.1 -n 10 @echo 正在訪問 http://localhost start "C:\Program Files\Internet Explorer\iexplore.exe" http://localhost
這樣隔一段時間變慢的問題已經解決了,但是還沒有查找到這是什么原因。
后來看到一篇文章說 是因為EF 的原因。
EF方面的原因:
第二、優化方案
一、安裝Application Initialization
這是在iis8出來后才有的,iis8內置的功能,而對於iis7.5也提供了一個擴展以支持這個功能。
Application Initialization Module for IIS 7.5
在頁面接近底部的地方,找到適合自己架構的安裝鏈接
- x86 for Windows 7
- x64 for Windows 7 or Windows Server 2008 R2
安裝這個iis模塊后,在iis界面中並沒有模塊圖標和配置界面,還需要安裝:
http://pan.baidu.com/s/1c091WxM
安裝成功之后會多了一個配置如下圖:
如果僅配置程序池StartMode為AlwaysRunning還不放心的話, 也可以同時針對站點開啟preload和DoAppInitAfterRestart。
設置應用程序池如下圖:
設置網站如下圖
配置好后,測試了下,效果十分不錯。 回收程序池后首次打開各站點,延遲都很低。 其實這個模塊的思路和定時從外部觸發一個訪問是一樣的,只是,更好的地方在於,它本身在程序池回收重啟的時候就完成了這件事,而不會讓外部訪問有機會遇到首次訪問的情況。
二、用Ngen安裝生成EF的本地鏡像
For 64 bit run: %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\ngen install EntityFramework.SqlServer.dll
三、禁用第一次ef查詢對表__MigrationHistory的問題
使用了ef的Code first會在第一次ef查詢的時候會對__MigrationHistory訪問,是為了檢查數據庫和model是否匹配,以保證ef能正常運行。通過監測會先執行下面的sql:
- SELECT
- [GroupBy1].[A1] AS [C1]
- FROM ( SELECT
- COUNT(1) AS [A1]
- FROM [dbo].[__MigrationHistory] AS [Extent1]
- ) AS [GroupBy1]
- GO
- SELECT TOP (1)
- [Extent1].[Id] AS [Id],
- [Extent1].[ModelHash] AS [ModelHash]
- FROM [dbo].[EdmMetadata] AS [Extent1]
- ORDER BY [Extent1].[Id] DESC
- GO
這段sql語句其實中只是在開發的時候有用,發布到生產環境,可以把這個給禁用了以提高性能。解決辦法:
- Database.SetInitializer<lanhuBlog.DAL.BlogContext>(null);
四、Model和DAl單獨的分層的
五、EF Pre-Generated Mapping Views(預生成映射視圖)
- using (var dbcontext = new EFDbContext())
- {
- var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext;
- var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
- mappingCollection.GenerateViews(new List<EdmSchemaError>());
- //對程序中定義的所有DbContext逐一進行這個操作
- }
六、補充
如果你覺得這還沒有解決”過了一段時間不訪問頁面然后再次打開頁面變慢“的問題,而且不能忍受第一次訪問還是有點慢,可以設置應用程序池的”閑時超時“和回收”固定時間間隔“長一些或者建一個計划任務定時去訪問使用了ef的頁面,這樣給ef熱身,讓ef不變冷,這樣可以防止長時間不請求網站,應用程序進程停止再次訪問變慢的問題。設置應用程序池的時間如下圖:
閑時超時默認是20分鍾,如果在超過20分鍾都沒有請求這個應用程序池工作進程就要關閉。這里你可以設置根據自己需要設置長一些。