使用 NLOG 在 IIS 中托管的 WCF 应用程序中的静态变量
Static Variables in WCF application hosted in IIS using NLOG
最近我的 WCF IIS 应用程序的行为发生了变化,这让我感到困惑。一周前,我能够向我的服务发出一个简单的 "Health" 函数请求,该函数使用 Interlocked.Increment 和 return 增加了一个静态变量。现在,我总是得到“1”作为 return 值。
该特定路径中的代码没有改变:
[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 神秘地确定我的 class 需要重新编译().我什至创建了一个单身人士并在单身人士中完成了所有这些事情,并且行为是相同的。一旦我使用记录器,静态变量就会被破坏。
任何人都可以帮助我了解如何避免这种行为吗?
如果您使用的是 iis 8 或更高版本,请设置您的 Idle Time-out=0
以防止应用程序池回收。但如果您使用的是 iis 7,请看一下 post:IIS 7.5 - Change Application Pool Start Mode to Always Running
我找到了答案。我让 NLOG 将日志文件写入程序集目录:
var logdir = SystemUtils.AssemblyDirectory(typeof(Api));
一旦我将其更改为不同的目录,问题就解决了。因此,显然,IIS 的工作方式是确定如果写入应用程序目录,则需要重新编译应用程序域中的类型。
可能有一种方法可以将 IIS 配置为忽略日志目录,但我对将其移动到其他位置感到满意。
最近我的 WCF IIS 应用程序的行为发生了变化,这让我感到困惑。一周前,我能够向我的服务发出一个简单的 "Health" 函数请求,该函数使用 Interlocked.Increment 和 return 增加了一个静态变量。现在,我总是得到“1”作为 return 值。
该特定路径中的代码没有改变:
[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 神秘地确定我的 class 需要重新编译().我什至创建了一个单身人士并在单身人士中完成了所有这些事情,并且行为是相同的。一旦我使用记录器,静态变量就会被破坏。
任何人都可以帮助我了解如何避免这种行为吗?
如果您使用的是 iis 8 或更高版本,请设置您的 Idle Time-out=0
以防止应用程序池回收。但如果您使用的是 iis 7,请看一下 post:IIS 7.5 - Change Application Pool Start Mode to Always Running
我找到了答案。我让 NLOG 将日志文件写入程序集目录:
var logdir = SystemUtils.AssemblyDirectory(typeof(Api));
一旦我将其更改为不同的目录,问题就解决了。因此,显然,IIS 的工作方式是确定如果写入应用程序目录,则需要重新编译应用程序域中的类型。
可能有一种方法可以将 IIS 配置为忽略日志目录,但我对将其移动到其他位置感到满意。