使用NLOG在IIS中托管的WCF应用程序中的静态变量

时间:2017-06-03 01:36:42

标签: c# wcf iis nlog

我对最近WCF IIS应用程序行为的变化感到困惑。一个星期前,我能够向我的服务请求一个简单的"健康"使用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 个答案:

答案 0 :(得分:1)

如果您使用的是iis 8或更高版本,请设置Idle Time-out=0以防止应用池回收。但如果您使用的是iis 7,请查看以下帖子:IIS 7.5 - Change Application Pool Start Mode to Always Running

答案 1 :(得分:0)

我发现了答案。我让NLOG将日志文件写入Assembly目录:

with tf.Session(server.target) as sess:
    print sess.run(some_variable)

一旦我将其更改为其他目录,问题就解决了。因此,显然,IIS的工作方式是确定在写入应用程序目录时是否需要重新编译应用程序域中的类型。

可能有一种方法可以将IIS配置为忽略日志目录,但我对将其移动到其他位置感到满意。