我对WCF IIS应用程序行为的最新变化感到困惑 . 一周前,我能够向我的服务请求一个简单的“ Health ”函数,该函数使用Interlocked.Increment增加一个静态变量并返回它 . 现在,我总是得到'1'作为回报值 .
该特定途径中的代码没有改变:
[ServiceContract]
public interface IApi {
[WebInvoke(
Method = "GET",
UriTemplate = "health",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
int GetHealth();
}
static int HealthCount = 0;
public int GetHealth()
{
return Interlocked.Increment(ref HealthCount);
}
可能相关的web.config设置:
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"
</appSettings>
...
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
...
<modules runAllManagedModulesForAllRequests="true" />
在IIS中,我已经将AppPool配置为具有AlwaysRunning的StartMode . 但是在我发现这个问题之后我做到了这一点并没有什么区别 .
我已将问题隔离到NLog . 我有一个静态构造函数:
static Api()
{
Logger = LogManager.GetCurrentClassLogger();
Logger.Log(LogLevel.Debug, "API Initialized.");
}
使用上面的静态构造函数会发生退化的新行为,但不会出现以下代码:
static Api()
{
Logger = LogManager.GetCurrentClassLogger();
}
简而言之,如果我使用NLog Logger记录任何内容,就好像我的AppDomain会在每个请求上回收,或者.NET神秘地确定我的类需要重新编译(https://stackoverflow.com/a/8919336/148051) . 我甚至创建了一个Singleton并在单例中完成了所有这些工作并且行为是相同的 . 一旦我使用Logger,静态变量就会被破坏 .
任何人都可以帮助我了解如何避免这种行为?
2 回答
如果您使用的是iis 8或更高版本,请设置
Idle Time-out=0
以防止应用程序池回收 . 但如果你使用的是iis 7,请看看这篇文章:IIS 7.5 - Change Application Pool Start Mode to Always Running我发现了答案 . 我让NLOG将日志文件写入Assembly目录:
一旦我将其更改为其他目录,问题就解决了 . 因此,显然,IIS的工作原理是确定在编写应用程序目录时需要重新编译应用程序域中的类型 .
可能有一种方法可以将IIS配置为忽略日志目录,但我对将其移动到其他位置感到满意 .