我在压力测试下有一个企业服务器应用程序,许多客户端连接,请求一些响应并在完成时断开连接。过了一会儿(可能是几天或几小时),他们无法连接错误:
无法执行套接字上的操作,因为系统缺少足够的缓冲区空间或者队列已满;
我们使用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值)?
答案 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连接。 增加缓冲区值的唯一缺点是您可能无法立即获取每条日志消息(因为它已发布),因此如果您关联多个日志源或您的应用程序突然崩溃,请注意这一点。