簡體   English   中英

IIS應用程序池回收+石英計划

[英]IIS app pool recycle + quartz scheduling

我正在IIS 7.5上運行一個Web應用程序,它需要偶爾回收(否則內存使用會失去處理,我正在調查!)。

當它再循環時,它實際上不會運行,直到另一個請求進入,石英不會運行。

有沒有辦法讓IIS在回收應用程序池后立即自動啟動1個工作流程,以確保石英始終在線?

是!

http://weblogs.asp.net/scottgu/archive/2009/09/15/auto-start-asp-net-applications-vs-2010-and-net-4-0-series.aspx詳細介紹了它,基本上你需要:

  1. 編輯C:\\ Windows \\ System32 \\ inetsrv \\ config \\ applicationHost.config以包含:

     <applicationPools> <add name="MyAppWorkerProcess" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" /> </applicationPools> 
  2. 聲明應該作為您網站的“熱身”運行的內容

     <sites> <site name="MySite" id="1"> <application path="/" serviceAutoStartEnabled="true" serviceAutoStartProvider="PreWarmMyCache" /> </site> </sites> <serviceAutoStartProviders> <add name="PreWarmMyCache" type="PreWarmCache, MyAssembly" /> </serviceAutoStartProviders> 
  3. 使用您想要的任何“預熱”邏輯配置您的應用程序:

     public class PreWarmCache : System.Web.Hosting.IProcessHostPreloadClient { public void Preload(string[] parameters) { // Perform initialization and cache loading logic here... } } 

注意:如果您需要的只是w3wp.exe進程存在,我相信只需要第1步。 如果你還需要其他項目(比如某些東西要加載到內存中),那么也會使用第2步和第3步。

從IIS 8.0開始,可以選擇模擬對根頁面的請求,從而進行完整的應用程序初始化:應用程序池高級設置 - > Preload enabled = true。

當然,startMode應該是AlwaysRunning。

有關如何啟用此功能的更多詳細信息,請參見此處

我解決了這個問題。 雖然Stephen的回答將使應用程序保持運行,但在Spring.Net環境中,框架不會啟動,Quartz也無法運行。 我整理了一個IProcessHostPreloadClient實現,它將啟動對應用程序的實際請求,以便運行所有機器。 這也發布在我的博客上

public class Preloader : System.Web.Hosting.IProcessHostPreloadClient
{
    public void Preload(string[] parameters)
    {
        var uris = System.Configuration.ConfigurationManager
                         .AppSettings["AdditionalStartupUris"];
        StartupApplication(AllUris(uris));
    }

    public void StartupApplication(IEnumerable<Uri> uris)
    {
        new System.Threading.Thread(o =>
        {
            System.Threading.Thread.Sleep(500);
            foreach (var uri in (IEnumerable<Uri>)o) {
                var client = new System.Net.WebClient();
                client.DownloadStringAsync(uris.First());
            }
        }).Start(uris);
    }

    public IEnumerable<Uri> AllUris(string userConfiguration)
    {
        if (userConfiguration == null)
            return GuessedUris();
        return AllUris(userConfiguration.Split(' ')).Union(GuessedUris());
    }

    private IEnumerable<Uri> GuessedUris()
    {
        string path = System.Web.HttpRuntime.AppDomainAppVirtualPath;
        if (path != null)
            yield return new Uri("http://localhost" + path);
    }

    private IEnumerable<Uri> AllUris(params string[] configurationParts)
    {
        return configurationParts
            .Select(p => ParseConfiguration(p))
            .Where(p => p.Item1)
            .Select(p => ToUri(p.Item2))
            .Where(u => u != null);
    }

    private Uri ToUri(string value)
    {
        try {
            return new Uri(value);
        }
        catch (UriFormatException) {
            return null;
        }
    }

    private Tuple<bool, string> ParseConfiguration(string part)
    {
        return new Tuple<bool, string>(IsRelevant(part), ParsePart(part));
    }

    private string ParsePart(string part)
    {
        // We expect IPv4 or MachineName followed by |
        var portions = part.Split('|');
        return portions.Last();
    }

    private bool IsRelevant(string part)
    {
        var portions = part.Split('|');
        return
            portions.Count() == 1 ||
            portions[0] == System.Environment.MachineName ||
            HostIpAddresses().Any(a => a == portions[0]);
    }

    private IEnumerable<string> HostIpAddresses()
    {
        var adaptors = System.Net.NetworkInformation
                             .NetworkInterface.GetAllNetworkInterfaces();
        return adaptors
                .Where(a => a.OperationalStatus == 
                            System.Net.NetworkInformation.OperationalStatus.Up)
                .SelectMany(a => a.GetIPProperties().UnicastAddresses)
                .Where(a => a.Address.AddressFamily == 
                            System.Net.Sockets.AddressFamily.InterNetwork)
                .Select(a => a.Address.ToString());
    }
}

或者您可以簡單地修改Global.asax中的“Application_Start”方法以確保Quortz正在運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM