Ala*_*ark 11 docker .net-core asp.net-core
我们的应用程序是部署在Linux Docker容器中并在Kubernetes中运行的ASP.NET Core 2.0 WebAPI.
在负载测试期间,我们发现CPU使用率出现间歇性峰值,而我们的应用程序永远无法从中恢复.
我们使用perfcollect从容器中收集痕迹,以便我们可以将成功的测试和测试与CPU峰值进行比较.我们发现,失败测试中大约75%的CPU时间花费在JIT_MonRelaibleEnter_Protable锁定操作的接口上.打电话的是System.Diagnostics.TraceSource.dll.
我们的应用程序是从.NET Framework移植而来的,包含很多调用System.Diagnostics.Trace.WriteLine().当我们删除所有这些时,我们的CPU /内存使用量减少了50%以上,我们不再看到CPU峰值了.
我想了解这个问题的原因.
在corefx repo中,我可以看到在TraceInternal.cs中设置了一个默认的跟踪侦听器:
public static TraceListenerCollection Listeners
{
get
{
InitializeSettings();
if (s_listeners == null)
{
lock (critSec)
{
if (s_listeners == null)
{
// In the absence of config support, the listeners by default add
// DefaultTraceListener to the listener collection.
s_listeners = new TraceListenerCollection();
TraceListener defaultListener = new DefaultTraceListener();
defaultListener.IndentLevel = t_indentLevel;
defaultListener.IndentSize = s_indentSize;
s_listeners.Add(defaultListener);
}
}
}
return s_listeners;
}
}
Run Code Online (Sandbox Code Playgroud)
我可以看到DefaultTraceListener.cs调用Debug.Write():
private void Write(string message, bool useLogFile)
{
if (NeedIndent)
WriteIndent();
// really huge messages mess up both VS and dbmon, so we chop it up into
// reasonable chunks if it's too big
if (message == null || message.Length <= InternalWriteSize)
{
Debug.Write(message);
}
else
{
int offset;
for (offset = 0; offset < message.Length - InternalWriteSize; offset += InternalWriteSize)
{
Debug.Write(message.Substring(offset, InternalWriteSize));
}
Debug.Write(message.Substring(offset));
}
if (useLogFile && !string.IsNullOrEmpty(LogFileName))
WriteToLogFile(message);
}
Run Code Online (Sandbox Code Playgroud)
在Debug.Unix.cs中,我可以看到有一个对SysLog的调用:
private static void WriteToDebugger(string message)
{
if (Debugger.IsLogging())
{
Debugger.Log(0, null, message);
}
else
{
Interop.Sys.SysLog(Interop.Sys.SysLogPriority.LOG_USER | Interop.Sys.SysLogPriority.LOG_DEBUG, "%s", message);
}
}
Run Code Online (Sandbox Code Playgroud)
我没有很多使用Linux的经验,但我相信我可以通过在容器中运行以下命令来模拟对SysLog的调用:
logger --socket-errors=on 'SysLog test'
Run Code Online (Sandbox Code Playgroud)
当我运行该命令时,我得到以下响应:
socket/dev/log:没有这样的文件或目录
所以看起来我无法从容器中成功调用SysLog.如果这确实是我打电话时发生的事情Trace.WriteLine(),为什么它会在我的应用程序中导致锁定问题?
据我所知,EnvVar_DebugWriteToStdErr未在我的容器中设置,所以它不应该尝试写入StdErr.
| 归档时间: |
|
| 查看次数: |
418 次 |
| 最近记录: |