我正在IIS 7.5上运行一个Web应用程序,它需要偶尔进行回收(否则内存使用会无法处理,我正在调查!)。
当它回收时,它实际上没有运行,直到另一个请求进入,石英不会运行。
有没有办法让IIS在回收应用程序池后立即自动启动1个工作流程,以确保石英始终在线?
答案 0 :(得分:14)
是!
编辑C:\ Windows \ System32 \ inetsrv \ config \ applicationHost.config以包含:
<applicationPools>
<add name="MyAppWorkerProcess" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" />
</applicationPools>
声明应该作为您网站的“热身”运行的内容
<sites>
<site name="MySite" id="1">
<application path="/" serviceAutoStartEnabled="true" serviceAutoStartProvider="PreWarmMyCache" />
</site>
</sites>
<serviceAutoStartProviders>
<add name="PreWarmMyCache" type="PreWarmCache, MyAssembly" />
</serviceAutoStartProviders>
使用您想要的任何“预热”逻辑配置您的应用程序:
public class PreWarmCache : System.Web.Hosting.IProcessHostPreloadClient {
public void Preload(string[] parameters) {
// Perform initialization and cache loading logic here...
}
}
注意:如果您需要的只是w3wp.exe进程存在,我相信只需要第1步。如果你还需要其他项目(比如某些东西要加载到内存中),那么也会使用第2步和第3步。
答案 1 :(得分:1)
从IIS 8.0开始,可以选择模拟对根页面的请求,从而实现完整的应用程序初始化:应用程序池高级设置 - &gt; Preload enabled = true。
当然,startMode应该是AlwaysRunning。
有关如何启用此功能的更多详细信息,请参见here。
答案 2 :(得分:0)
我抓住了这个问题。虽然Stephen's answer将使应用程序保持运行,但在Spring.Net环境中,框架不会启动,Quartz也不会运行。我整理了一个IProcessHostPreloadClient实现,它将启动对应用程序的实际请求,以便运行所有机器。这也是on my blog发布的:
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());
}
}
答案 3 :(得分:-3)
或者你可以简单地修改Global.asax中的“Application_Start”方法,以确保Quortz正在运行。