0

我们已经创建了一个带有 SQL 背板的服务器。最近,我们发现这个问题导致 w3wp.exe 使用大量线程。在浏览了整个代码库之后,我们能够缩小原因与 NLog 相关。

我们通过 web config 文件中的配置来配置 NLog。

<configuration>
  <configSections>
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
  </configSections>
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd">
    <targets async="true">

      <target name="file" xsi:type="File" fileName="${basedir}/Logs/${shortdate}_printcloud.log" archiveFileName="${basedir}/Logs/ArchiveAuto/{#}_printcloud.log" archiveDateFormat="yyyy-MM-dd" archiveAboveSize="50000000" archiveEvery="Day" archiveNumbering="DateAndSequence" maxArchiveFiles="14" archiveOldFileOnStartup="false" createDirs="true" layout="${longdate} ${uppercase:${level}}  ${logger} ${message} (${callsite:includSourcePath=true}) ${exception:format=tostring}" />

    </targets>
    <rules>
     <logger name="PrintCloud.*" minlevel="Trace" maxlevel="Error" writeTo="file" />-->

    </rules>
  </nlog>
<configuration>

在集线器内部,我们使用了如下所示的记录器。

public class ConnectorHub : Hub
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    public void Connect(string message)
    {
        logger.Debug("Connection Recieved");
        (new SignalRHubHelper()).SendConnectRecieved(Context.ConnectionId);
    }
}

当我们在启用这些配置的情况下运行背板时,当客户端尝试重新连接时,我们面临着大量线程使用的问题。但是如果我们从 web 配置文件中注释掉 NLog 配置代码,那么背板就可以正常工作了。有没有人在使用背板时遇到过类似的行为?这种行为的原因可能是什么?

SignalR 版本 - 2.2.2 NLog 版本 - 4.4.9

编辑 1

当我们从 webconfig 禁用信号器跟踪日志记录时,问题似乎没有发生。我们习惯于NLog.NLogTraceListener记录信号器跟踪。

  <system.diagnostics>
    <sources>
      <source name="SignalR.SqlMessageBus">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.ServiceBusMessageBus">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.RedisMessageBus">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.ScaleoutMessageBus">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.Transports.WebSocketTransport">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.Transports.ServerSentEventsTransport">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.Transports.ForeverFrameTransport">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.Transports.LongPollingTransport">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.Transports.TransportHeartBeat">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
      <source name="SignalR.ReflectedHubDescriptorProvider">
        <listeners>
          <add name="traces" />
        </listeners>
      </source>
    </sources>
     <!--Sets the trace verbosity level--> 
    <switches>
      <add name="SignalRSwitch" value="Verbose" />
    </switches>
    <sharedListeners>

     <add name="traces" type="NLog.NLogTraceListener, NLog" />
    </sharedListeners>
    <trace autoflush="true" />
  </system.diagnostics>

而不是 usingNLog.NLogTraceListener和 using System.Diagnostics.TextWriterTraceListenerinstead 似乎也没有给出任何问题。

4

1 回答 1

3

认为问题是这样的:

autoflush=true

这会导致 NLogTraceListener 发狂并为每个跟踪事件执行刷新。通过使用线程池线程刷新所有已注册的 NLog 目标。

如果您需要,则考虑通过向侦听器添加属性来autoflush=true禁用线程池刷新:disableFlush

<add name="traces" type="NLog.NLogTraceListener, NLog" disableFlush="true" />

好奇为什么 NLog Wiki 建议启用autoflush=true,而不添加这个重要属性:

https://github.com/NLog/NLog/wiki/NLog-Trace-Listener-for-System-Diagnostics-Trace

更新NLog 4.5 现在disableFlush=true默认使用。另请参阅https://github.com/NLog/NLog/pull/2407

于 2017-05-27T22:37:29.137 回答