中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

不修改代碼優(yōu)化ASP.NET網(wǎng)站性能的一些方法

2018-07-20    來(lái)源:編程學(xué)習(xí)網(wǎng)

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

  本文將介紹一些方法用于優(yōu)化ASP.NET網(wǎng)站性能,這些方法都是不需要修改程序代碼的。它們主要分為二個(gè)方面:1. 利用ASP.NET自身的擴(kuò)展性進(jìn)行優(yōu)化。2. 優(yōu)化IIS設(shè)置。

 配置OutputCache

  用緩存來(lái)優(yōu)化網(wǎng)站性能的方法,估計(jì)是無(wú)人不知的。 ASP.NET提供了HttpRuntime.Cache對(duì)象來(lái)緩存數(shù)據(jù),也提供了OutputCache指令來(lái)緩存整個(gè)頁(yè)面輸出。雖然OutputCache指令使用起來(lái)更方便,也有非常好的效果,不過(guò),它需要我們?cè)谀切╉?yè)面中添加這樣一個(gè)指令。

  對(duì)于設(shè)置過(guò)OutputCache的頁(yè)面來(lái)說(shuō),瀏覽器在收到這類頁(yè)面的響應(yīng)后,會(huì)將頁(yè)面響應(yīng)內(nèi)容緩存起來(lái)。只要在指定的緩存時(shí)間之內(nèi),且用戶沒(méi)有強(qiáng)制刷新的操作,那么就根本不會(huì)再次請(qǐng)求服務(wù)端,而對(duì)于來(lái)自其它的瀏覽器發(fā)起的請(qǐng)求,如果緩存頁(yè)已生成,那么就可以直接從緩存中響應(yīng)請(qǐng)求,加快響應(yīng)速度。因此,OutputCache指令對(duì)于性能優(yōu)化來(lái)說(shuō),是很有意義的(除非所有頁(yè)面頁(yè)面都在頻繁更新)。

  在網(wǎng)站的優(yōu)化階段,我們可以用Fiddler之類的工具找出一些內(nèi)容幾乎不會(huì)改變的頁(yè)面,給它們?cè)O(shè)置OutputCache,但是,按照傳統(tǒng)的開(kāi)發(fā)流程,我們需要針對(duì)每個(gè)頁(yè)面文件執(zhí)行以下操作:

  1. 簽出頁(yè)面文件。

  2. 添加OutputCache指令。

  3. 重新發(fā)布頁(yè)面。

  4. 簽入文件(如果遇到多分支并行,還可能需要合并操作)。

  以上這些源代碼管理制度會(huì)讓一個(gè)簡(jiǎn)單的事情復(fù)雜化,那么,有沒(méi)一種更簡(jiǎn)單的方法能解決這個(gè)問(wèn)題呢?

  接下來(lái),本文將介紹一種方法,它利用ASP.NET自身的擴(kuò)展性,以配置文件的方式為頁(yè)面設(shè)置OutputCache參數(shù)。配置文件其它就是一個(gè)XML文件,內(nèi)容如下:

<?xml version="1.0" encoding="utf-8"?>
<OutputCache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Settings>
        <Setting Duration="3" FilePath="/Pages/a3.aspx"  />
        <Setting Duration="10" FilePath="/Pages/a5.aspx"  />
    </Settings>
</OutputCache>

  看了這段配置,我想您應(yīng)該也能猜到它能有什么作用。

  每一行配置參數(shù)為一個(gè)頁(yè)面指定OutputCache所需要的參數(shù),示例文件為了簡(jiǎn)單只使用二個(gè)參數(shù),其它可以支持的參數(shù)請(qǐng)參考OutputCache指令。

  為了能讓這個(gè)配置文件有效,需要在web.config中配置以下內(nèi)容(適用于IIS7):

<system.webServer>
    <modules>
        <add name="SetOutputCacheModule" type="WebSiteOptimize.SetOutputCacheModule, WebSiteOptimize" />
    </modules>
</system.webServer>

在這里,我注冊(cè)了一個(gè)HttpModule,它的全部代碼如下:

public class SetOutputCacheModule : IHttpModule
{
    static SetOutputCacheModule()
    {
        // 加載配置文件
        string xmlFilePath = Path.Combine(HttpRuntime.AppDomainAppPath, "OutputCache.config");
        ConfigManager.LoadConfig(xmlFilePath);
    }

    public void Init(HttpApplication app)
    {
        app.PreRequestHandlerExecute += new EventHandler(app_PreRequestHandlerExecute);
    }

    void app_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;

        Dictionary<string, OutputCacheSetting> settings = ConfigManager.Settings;
        if( settings == null )
            throw new ConfigurationErrorsException("SetOutputCacheModule加載配置文件失敗。");

        // 實(shí)現(xiàn)方法:
        // 查找配置參數(shù),如果找到匹配的請(qǐng)求,就設(shè)置OutputCache
        OutputCacheSetting setting = null;
        if( settings.TryGetValue(app.Request.FilePath, out setting) ) {
            setting.SetResponseCache(app.Context);
        }
    }

  ConfigManager類用于讀取配置文件,并啟用了文件依賴技術(shù),當(dāng)配置文件更新后,程序會(huì)自動(dòng)重新加載:

internal static class ConfigManager
{
    private static readonly string CacheKey = Guid.NewGuid().ToString();

    private static Exception s_loadConfigException;
    private static Dictionary<string, OutputCacheSetting> s_settings;

    public static Dictionary<string, OutputCacheSetting> Settings
    {
        get{
            Exception exceptin = s_loadConfigException;
            if( exceptin != null )
                throw exceptin;

            return s_settings;
        }
    }

    public static void LoadConfig(string xmlFilePath)
    {
        Dictionary<string, OutputCacheSetting> dict = null;

        try {
            OutputCacheConfig config = XmlHelper.XmlDeserializeFromFile<OutputCacheConfig>(xmlFilePath, Encoding.UTF8);
            dict = config.Settings.ToDictionary(x => x.FilePath, StringComparer.OrdinalIgnoreCase);
        }
        catch( Exception ex ) {
            s_loadConfigException = new System.Configuration.ConfigurationException(
                "初始化SetOutputCacheModule時(shí)發(fā)生異常,請(qǐng)檢查" + xmlFilePath + "文件是否配置正確。", ex);
        }


        if( dict != null ) {
            // 注冊(cè)緩存移除通知,以便在用戶修改了配置文件后自動(dòng)重新加載。

            // 參考:細(xì)說(shuō) ASP.NET Cache 及其高級(jí)用法
            //          http://www.cnblogs.com/fish-li/archive/2011/12/27/2304063.html
            CacheDependency dep = new CacheDependency(xmlFilePath);
            HttpRuntime.Cache.Insert(CacheKey, xmlFilePath, dep,
                Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, CacheRemovedCallback);
        }

        s_settings = dict;
    }


    private static void CacheRemovedCallback(string key, object value, CacheItemRemovedReason reason)
    {
        string xmlFilePath = (string)value;

        // 由于事件發(fā)生時(shí),文件可能還沒(méi)有完全關(guān)閉,所以只好讓程序稍等。
        System.Threading.Thread.Sleep(3000);

        // 重新加載配置文件
        LoadConfig(xmlFilePath);
    }
}

  有了AutoSetOutputCacheModule,我們就可以直接使用配置文件為頁(yè)面設(shè)置OutputCache參數(shù),而不需要修改任何頁(yè)面,是不是很容易使用?

  說(shuō)明:MyMVC框架已支持這種功能,所有相關(guān)的可以從MyMVC框架的源碼中獲取。

  建議:對(duì)于一些很少改變的頁(yè)面,緩存頁(yè)是一種很有效的優(yōu)化方法。

 啟用內(nèi)容過(guò)期

  每個(gè)網(wǎng)站都會(huì)有一些資源文件(圖片,JS,CSS),這些文件相對(duì)于ASPX頁(yè)面來(lái)說(shuō),它們的輸出內(nèi)容極有可能在一段長(zhǎng)時(shí)間之內(nèi)不會(huì)有變化,而IIS在響應(yīng)這類資源文件時(shí)不會(huì)生成Cache-Control響應(yīng)頭。在這種情況下,瀏覽器或許會(huì)緩存它們,也許會(huì)再次發(fā)起請(qǐng)求(比如重啟后),總之就是緩存行為不受控制且緩存時(shí)間不夠長(zhǎng)久。

  有沒(méi)有想過(guò)可以把它們?cè)跒g覽器中長(zhǎng)久緩存起來(lái)呢?

  為了告訴瀏覽器將這些文件長(zhǎng)久緩存起來(lái),減少一些無(wú)意義的請(qǐng)求(提高頁(yè)面呈現(xiàn)速度),我們可以在IIS中啟用內(nèi)容過(guò)期,這樣設(shè)置后,IIS就能生成Cache-Control響應(yīng)頭,明確告訴瀏覽器將文件緩存多久。

  在IIS6中,這個(gè)參數(shù)很好找到:

  然而,在IIS7中,這個(gè)參數(shù)不容易被發(fā)現(xiàn),需要以下操作才能找到:

  選擇網(wǎng)站(或者網(wǎng)站子目錄)節(jié)點(diǎn),雙擊【HTTP響應(yīng)標(biāo)頭】

  再點(diǎn)擊右邊的【設(shè)置常用標(biāo)頭】鏈接,

  此時(shí)將會(huì)顯示:

  說(shuō)明:【啟用內(nèi)容過(guò)期】這個(gè)設(shè)置可以基于整個(gè)網(wǎng)站,也可以針對(duì)子目錄,或者一個(gè)具體的文件。

  注意:如果您在IIS7中針對(duì)某個(gè)子目錄或者文件設(shè)置【啟用內(nèi)容過(guò)期】,前面的對(duì)話框看起來(lái)是一模一樣的,

  然而,在IIS6中,我們可以清楚地從對(duì)話框的標(biāo)題欄中知道我們?cè)谧鍪裁矗?/p>

  有時(shí)真感覺(jué)IIS7的界面在退步!

  最后我想說(shuō)一句:可以直接為整個(gè)網(wǎng)站啟用內(nèi)容過(guò)期,ASPX頁(yè)面是不會(huì)被緩存的!

  說(shuō)到這里可能有人會(huì)想:這個(gè)過(guò)期時(shí)間我該設(shè)置多久呢?

  十分鐘,2個(gè)小時(shí),一天,還是一個(gè)月?

  在我看來(lái),這個(gè)時(shí)間越久越好。

  可能有人又會(huì)說(shuō)了:萬(wàn)一我要升級(jí)某個(gè)JS文件怎么辦,時(shí)間設(shè)置久了,用戶怎么更新呢?

  如果你問(wèn)我這個(gè)問(wèn)題,我也只能說(shuō)是你的代碼不合理(畢竟你解決不了升級(jí)問(wèn)題),想知道原因的話,請(qǐng)繼續(xù)閱讀。

 解決資源文件升級(jí)問(wèn)題

  對(duì)于一些規(guī)模不大的網(wǎng)站來(lái)說(shuō),通常會(huì)將資源文件與程序文件一起部署到一個(gè)網(wǎng)站中。

  這時(shí)可能會(huì)采用下面的方式來(lái)引用JS或者CSS文件:

<link type="text/css" href="aaaa.css" rel="Stylesheet" />
<script type="text/javascript" src="bbb.js"></script>

  在這種情況下,如果使用了前面所說(shuō)的【啟用內(nèi)容過(guò)期】方法,那么當(dāng)有JS,CSS文件需要升級(jí)時(shí),由于瀏覽器的緩存還沒(méi)有過(guò)期,所以就不會(huì)請(qǐng)求服務(wù)器,此時(shí)會(huì)使用已緩存的版本,因此可能會(huì)出現(xiàn)各種奇怪的BUG

  對(duì)于前面談到的BUG,我認(rèn)為根源在于引用JS,CSS文件的方式有缺陷,那種方法完全沒(méi)有考慮到版本升級(jí)問(wèn)題,正確的方法有二種:

  1. 給文件名添加版本號(hào),像jquery那樣,每個(gè)版本一個(gè)文件(jquery-1.4.4.min.js)。

  2. 在URL后面添加一個(gè)版本號(hào),讓原先的URL失效。

  第一種方法由于每次升級(jí)都產(chǎn)生了一個(gè)新文件,所以不存在緩存問(wèn)題,但是,維護(hù)一大堆文件的成本可能會(huì)比較大,因此我建議采用第二種方法來(lái)解決。

  在MyMVC的示例代碼中,我使用了下面的方法來(lái)引用這些資源文件:

<%= HtmlExtension.RefCssFileHtml("/css/StyleSheet.css")%>
<%= HtmlExtension.RefJsFileHtml("/js/MyPage/fish.js")%>

  在頁(yè)面運(yùn)行時(shí),會(huì)產(chǎn)生如下的輸出結(jié)果:

<link type="text/css" rel="Stylesheet" href="/css/StyleSheet.css?_t=634642185820000000" />
<script type="text/javascript" src="/js/MyPage/fish.js?_t=634642154020000000"></script>

  這二個(gè)工具方法的實(shí)現(xiàn)代碼如下(在MyMVC的示例代碼中):

private static readonly string s_root = HttpRuntime.AppDomainAppPath.TrimEnd('\\');

public static string RefJsFileHtml(string path)
{
    string filePath = s_root + path.Replace("/", "\\");
    string version = File.GetLastWriteTimeUtc(filePath).Ticks.ToString();
    return string.Format("<script type=\"text/javascript\" src=\"{0}?_t={1}\"></script>\r\n", path, version);
}

public static string RefCssFileHtml(string path)
{
    string filePath = s_root + path.Replace("/", "\\");
    string version = File.GetLastWriteTimeUtc(filePath).Ticks.ToString();
    return string.Format("<link type=\"text/css\" rel=\"Stylesheet\" href=\"{0}?_t={1}\" />\r\n", path, version);
}

  上面這種獲取文件版本號(hào)的方法,是一種比較簡(jiǎn)單的解決方案。每個(gè)引用的地方在生成HTML代碼時(shí),都會(huì)訪問(wèn)文件的最后修改時(shí)間,這會(huì)給磁盤(pán)帶來(lái)一點(diǎn)讀的開(kāi)銷,如果您擔(dān)心這種實(shí)現(xiàn)方式可能會(huì)給性能帶來(lái)影響,那么也可以增加一個(gè)配置文件的方式來(lái)解決(請(qǐng)自行實(shí)現(xiàn)),例如以下結(jié)構(gòu):

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfFileVersion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <FileVersion FilePath="/js/JScript.js" Version="255324" />
    <FileVersion FilePath="/css/StyleSheet.css" Version="2324235" />
</ArrayOfFileVersion>

  如果您認(rèn)為這種配置文件需要手工維護(hù),不夠自動(dòng)化,還可以采用程序的方式自動(dòng)在運(yùn)行時(shí)維護(hù)一個(gè)列表,總之,直接引用資源文件的方法是一種直接耦合,會(huì)給文件升級(jí)帶來(lái)麻煩,我們可以通過(guò)一個(gè)外部方法來(lái)解開(kāi)這個(gè)直接耦合(給FileVersion增加一個(gè)屬性還還可以將內(nèi)部地址改成一個(gè)CDN地址)。

 啟用壓縮

  壓縮響應(yīng)結(jié)果也是常用的網(wǎng)站優(yōu)化方法,由于現(xiàn)在的瀏覽器都已支持壓縮功能,因此,如果在服務(wù)端能壓縮響應(yīng)結(jié)果,對(duì)于網(wǎng)速較慢的用戶來(lái)說(shuō),會(huì)減少很多網(wǎng)絡(luò)傳輸時(shí)間,最終的體驗(yàn)就是網(wǎng)頁(yè)顯示速度變快了!

  IIS6雖然提供壓縮的設(shè)置界面,然而配置是基于服務(wù)器級(jí)別的:

 注意:這里的【應(yīng)用程序文件】不包括aspx,如果需要壓縮aspx的響應(yīng),需要手工修改x:\WINDOWS\system32\inetsrv\MetaBase.xml文件(參考加大字號(hào)部分):

<IIsCompressionScheme    Location ="/LM/W3SVC/Filters/Compression/gzip"
        HcCompressionDll="%windir%\system32\inetsrv\gzip.dll"
        HcCreateFlags="1"
        HcDoDynamicCompression="TRUE"
        HcDoOnDemandCompression="TRUE"
        HcDoStaticCompression="TRUE"
        HcDynamicCompressionLevel="9"
        HcFileExtensions="htm
            html
            txt
            js
            css
            htc"
        HcOnDemandCompLevel="10"
        HcPriority="1"
        HcScriptFileExtensions="asp
            exe
            aspx
            axd"
    >

  說(shuō)明:要修改MetaBase.xml,需要停止IIS Admin Service服務(wù)。

  在IIS7中,我們可以在服務(wù)器級(jí)別配置壓縮參數(shù):

  然后在每個(gè)網(wǎng)站中開(kāi)啟或者關(guān)閉壓縮功能:

  說(shuō)明:IIS7中已經(jīng)不再使用MetaBase.xml,所以我們找不到IIS6的那些設(shè)置了。 IIS7壓縮的過(guò)濾條件不再針對(duì)擴(kuò)展名,而是采用了mimeType規(guī)則(保存在applicationHost.config)。根據(jù)IIS7的壓縮規(guī)則,當(dāng)我們啟用動(dòng)態(tài)壓縮后,會(huì)壓縮aspx的響應(yīng)結(jié)果。

  二種壓縮方法的差別:

  1. 靜態(tài)內(nèi)容壓縮:當(dāng)服務(wù)器在第一次響應(yīng)某個(gè)靜態(tài)文件時(shí),會(huì)生成一個(gè)壓縮后的結(jié)果,并保存到磁盤(pán)中,以便重用。

  2. 動(dòng)態(tài)內(nèi)容壓縮:【每次】在響應(yīng)客戶端之前,壓縮響應(yīng)結(jié)果,在內(nèi)存中完成,因此會(huì)給CPU帶來(lái)一些負(fù)擔(dān)。

  注意:要不要【啟用動(dòng)態(tài)內(nèi)容壓縮】這個(gè)參數(shù),需要評(píng)估服務(wù)器的CPU是否能以承受(觀察任務(wù)管理器或者查看性能計(jì)數(shù)器)。

 刪除無(wú)用的HttpModule

  對(duì)一個(gè)網(wǎng)站來(lái)說(shuō),ASP.NET提供的有些HttpMoudle可能并不是需要的,然而,如果你不去手工禁用它們,它們其實(shí)會(huì)一直運(yùn)行。

  比如 我會(huì)禁用下面這些HttpMoudle:

<httpModules>
    <remove name="Session"/>
    <remove name="RoleManager"/>
    <remove name="PassportAuthentication"/>
    <remove name="Profile"/>
    <remove name="ServiceModel"/>
</httpModules>

對(duì)于使用Forms身份認(rèn)證的網(wǎng)站的來(lái)說(shuō),下面這些HttpModule也是可以禁用的:

<httpModules>
    <remove name="WindowsAuthentication"/>
    <remove name="FileAuthorization"/>
</httpModules>

 其它優(yōu)化選項(xiàng)

  優(yōu)化ASP.NET網(wǎng)站是一個(gè)大的話題,除了博客中介紹的這些方法之外,還有以下方法也是可以參考的:

  1. 升級(jí)服務(wù)器硬件配置。

  2. 使用Windows Server 2008以上版本操作系統(tǒng)(網(wǎng)絡(luò)性能比2003要好)。

  3. 優(yōu)化操作系統(tǒng)配置(例如禁用不需要的服務(wù))。

  4. 禁用調(diào)試模式。

  5. 網(wǎng)站使用專用應(yīng)用程序池。

標(biāo)簽: 代碼 服務(wù)器 服務(wù)器硬件 網(wǎng)絡(luò) 網(wǎng)站優(yōu)化

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:ASP.NET Web Forms的改進(jìn)

下一篇:7 個(gè)流行的.Net開(kāi)發(fā)ORM映射工具