使用 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 配置为忽略日志目录,但我对将其移动到其他位置感到满意。