使用log4net RemotingAppender端口耗尽

时间:2016-10-19 19:47:47

标签: c# .net windows log4net

我在压力测试下有一个企业服务器应用程序,许多客户端连接,请求一些响应并在完成时断开连接。过了一会儿(可能是几天或几小时),他们无法连接错误:

  

无法执行套接字上的操作,因为系统缺少足够的缓冲区空间或者队列已满;

我们使用log4net并在将log4net级别增加到“Trace”之后,错误开始发生得更快,这指向了有罪的一方:)

由于我们使用的RemotingAppender并且没有活动服务来接收日志,因此我们有一个端口耗尽。通过查看“资源监视器”中的服务器的“网络活动”(许多非活动的localhost:7070连接)来计算出一个。

这是一个重现问题的小测试程序(根据PC可能需要运行一段时间):

private static void Main(string[] args)
    {
        log4net.Config.XmlConfigurator.Configure();

        bool exit = false;
        Task.Factory.StartNew(() =>
        {
            Console.ReadKey();
            exit = true;
        });

        ILog log = LogManager.GetLogger(typeof (Program));

        long count = 0;
        while (!exit)
        {
            log.Info($"Loop counter = {count++}.");
            using (TcpClient client = new TcpClient())
            {
                try
                {
                    log.Info("Connecting to server...");
                    client.Connect("google.com", 80);
                    log.Info("Connected to server.");
                    log.Debug($"End points: {client.Client.LocalEndPoint} => {client.Client.RemoteEndPoint}");
                    for (int i = 0; i < 20; i++) log.Debug("Dummy log line.");
                    client.Close();
                    log.Info("Disconnected from the server.");
                    Thread.Sleep(10);
                    log.Warn("Woke up after 10ms.");
                }
                catch (Exception e)
                {
                    log.Error(e);
                    Console.ReadKey();
                    exit = true;
                }
            }
            log.Error("Fake error.");
            log.Warn("Press any key to stop the test :)");
        }
    }

示例log4net配置在这里:

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  <log4net>
    <appender name="Console" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %-5level: %message%newline" />
      </layout>
    </appender>
    <appender name="RemotingAppender" type="log4net.Appender.RemotingAppender" >
      <sink value="tcp://localhost:7070/LoggingSink" />
      <lossy value="false" />
      <bufferSize value="0" />
    </appender>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="Console" />
      <appender-ref ref="RemotingAppender" />
    </root>
  </log4net>

目前的解决方法是从配置中的“root”部分注释掉RemotingAppender。我想知道是否有更好的方法来配置RemotingAppender以避免这种情况(将尝试使用bufferSize值)?

1 个答案:

答案 0 :(得分:0)

避免端口耗尽的方法是在“RemoteAppender”的log4net配置中使用/增加缓冲区大小值。像这样:

 <appender name="RemotingAppender" type="log4net.Appender.RemotingAppender" >
  <sink value="tcp://localhost:7070/LoggingSink" />
  <lossy value="false" />
  <bufferSize value="100" />
</appender>

值越大,日志消息在发送之前就会进入缓冲区(并使用新的套接字连接)。请注意,如果您在端口7070上运行类似Log2Console的侦听器,则不会出现问题,因为重用了相同的TCP连接。 增加缓冲区值的唯一缺点是您可能无法立即获取每条日志消息(因为它已发布),因此如果您关联多个日志源或您的应用程序突然崩溃,请注意这一点。