门户网站建设实施方案,wap门户,建设银行的网站你打不开,网页免费游戏prometheus-net.DotNetRuntime 介绍Intro前面集成 Prometheus 的文章中简单提到过#xff0c;prometheus-net.DotNetRuntime 可以获取到一些 CLR 的数据#xff0c;比如说 GC, ThreadPool, Contention, JIT 等指标#xff0c;而这些指标可以很大程度上帮助我们解决很多问题prometheus-net.DotNetRuntime 可以获取到一些 CLR 的数据比如说 GC, ThreadPool, Contention, JIT 等指标而这些指标可以很大程度上帮助我们解决很多问题比如应用执行过程中是否经常发生 GCGC 等待时间时间是否过长是否有发生死锁或竞争锁时间过长是否有发生线程池饿死等等一系列问题有了这些指标我们就可以清晰的在运行时了解到这些信息。来看一下官方介绍A plugin for the prometheus-net package, exposing .NET core runtime metrics including:Garbage collection collection frequencies and timings by generation/ type, pause timings and GC CPU consumption ratioHeap size by generationBytes allocated by small/ large object heapJIT compilations and JIT CPU consumption ratioThread pool size, scheduling delays and reasons for growing/ shrinkingLock contentionExceptions thrown, broken down by typeThese metrics are essential for understanding the peformance of any non-trivial application. Even if your application is well instrumented, youre only getting half the story- what the runtime is doing completes the picture.支持的指标Contention Events只要运行时使用的 System.Threading.Monitor 锁或 Native锁出现争用情况就会引发争用事件。一个线程等待的锁被另一线程占有时将发生争用。NameDescriptionTypedotnet_contention_seconds_total发生锁争用的耗时(秒)总计Counterdotnet_contention_total锁争用获得锁的数量总计CounterThread Pool EventsWorker thread 线程池和 IO thread 线程池信息NameDescriptionTypedotnet_threadpool_num_threads线程池中活跃的线程数量Gaugedotnet_threadpool_io_num_threadsIO 线程池中活跃线程数量(WindowsOnly)Gaugedotnet_threadpool_adjustments_total线程池中线程调整总计CounterGarbage Collection EventsCaptures information pertaining to garbage collection, to help in diagnostics and debugging.NameDescriptionTypedotnet_gc_collection_seconds执行 GC 回收过程耗费的时间秒Histogramdotnet_gc_pause_secondsGC 回收造成的 Pause 耗费的时间秒Histogramdotnet_gc_collection_reasons_total触发 GC 垃圾回收的原因统计Counterdotnet_gc_cpu_ratio运行垃圾收集所花费的进程CPU时间的百分比Gaugedotnet_gc_pause_ratio进程暂停进行垃圾收集所花费的时间百分比Gaugedotnet_gc_heap_size_bytes当前各个 GC 堆的大小 (发生垃圾回收之后才会更新)Gaugedotnet_gc_allocated_bytes_total大小对象堆上已分配的字节总数每100 KB分配更新Counterdotnet_gc_pinned_objectspinned 对象的数量Gaugedotnet_gc_finalization_queue_length等待 finalize 的对象数GaugeJIT EventsNameDescriptionTypedotnet_jit_method_totalJIT编译器编译的方法总数Counterdotnet_jit_method_seconds_totalJIT编译器中花费的总时间秒Counterdotnet_jit_cpu_ratioJIT 花费的 CPU 时间Gauge集成方式上面的列出来的指标是我觉得比较重要的指标还有一些 ThreadPool Scheduling 的指标和 CLR Exception 的指标我觉得意义不是特别大有需要的可以去源码里看一看集成的方式有两种一种是作者提供了一个默认的 Collector 会去收集所有支持的 CLR 指标信息另外一种则是可以自己自定义的要收集的 CLR 指标类型来看示例使用默认的 Collector 收集 CLR 指标DotNetRuntimeStatsBuilder.Default().StartCollecting();
使用自定义的 Collector 收集 CLR 指标DotNetRuntimeStatsBuilder.Customize().WithContentionStats() // Contention event.WithGcStats() // GC 指标.WithThreadPoolStats() // ThreadPool 指标// .WithCustomCollector(null) // 你可以自己实现一个自定义的 Collector.StartCollecting();
上面提到过默认的 Collector 会收集支持的所有的 CLR 指标且看源码怎么做的构建了一个 Builder 通过建造者模式来构建复杂配置的收集器类似于 .net core 里的 HostBuilder/LoggingBuilder ...像极了 Host.CreateDefaultBuilder做了一些变形源码地址https://github.com/djluck/prometheus-net.DotNetRuntime/blob/master/src/prometheus-net.DotNetRuntime/DotNetRuntimeStatsBuilder.cs实现原理那它是如何工作的呢如何实现捕获 CLR 的指标的呢下面我们就来解密一下在项目 README 里已经有了简单的介绍是基于 CLR 的 ETW Events 来实现的具体的 CLR 支持的 ETW Events 可以参考文档https://docs.microsoft.com/en-us/dotnet/framework/performance/clr-etw-events而 ETW Events 是通过 EventSource 的方式使得我们可以在进程外获取到进程的一些运行信息这也是我们可以通过 PerfMonitor/PerfView 等方式进程外获取进程 CLR 信息的重要实现方式同样的微软的新的诊断工具 dotnet diagnostic tools 的实现方式 EventPipe 也是基于 EventSOurce 的而 EventSource 的事件不仅仅可以通过进程外的这些工具来消费我们也可以在应用程序中实现 EventListener 来实现进程内的 EventSource 事件消费而这就是 prometheus-net.DotNetRuntime 这个库的实现本质方法可以参考源码https://github.com/djluck/prometheus-net.DotNetRuntime/blob/master/src/prometheus-net.DotNetRuntime/DotNetEventListener.cs具体的事件处理是在对应的 Collector 中https://github.com/djluck/prometheus-net.DotNetRuntime/tree/master/src/prometheus-net.DotNetRuntime/StatsCollectorsMetrics Samples为了比较直观的看到这些指标可以带来的效果分享一下我的应用中用到的一些 dashboard 截图Lock ContentionGC从上面的图可以清晰的看到这个时间点发生了一次垃圾回收此时 GC Heap 的大小和 GC 垃圾回收的CPU 占用率和耗时都可以大概看的出来对于我们运行时诊断应用程序问题会很有帮助ThreadThread 的信息还可以拿到一些 threadpool 线程调度的数量以及延迟这里没有展示出来目前我主要关注的是线程池中线程的数量和线程池线程调整的原因线程池线程调整的原因中有一个是 starvation这个指标尤其需要关注一下应避免出现 threadpool starvation 的情况出现这个的原因通常是因为有一些不当的用法如Task.Wait、Task.Result、await Task.Run() 来把一个同步方法变成异步等不好的用法导致的DiagnosticSource除了 EventSource 之外还有一个 DiagnosticSource 可以帮助我们诊断应用程序的性能问题目前微软也是推荐类库中使用 DiagnosticSource 的方式来让应用诊断类库中的一些性能问题这也是目前大多数 APM 实现的机制Skywalking、ElasticAPM、OpenTelemetry 等都使用了 DiagnosticSource 的方式来实现应用程序的性能诊断如果是进程外应用程序的性能诊断推荐首选 EventSource如果是进程内推荐首选 DiagnosticSource通常我们都应该使用 DiagnosticSource即使想进程外捕获也是可以做到的关于这二者的使用可以看一下这个 Comment https://github.com/dotnet/aspnetcore/issues/2312#issuecomment-359514074More除了上面列出来的那些指标还有一些指标比如 exceptionthreadpool scheduling还有当前 dotnet 的环境系统版本GC 类型Runtime 版本程序 TargetFrameworkCPU 数量等有兴趣的可以用一下试一下exception 指标使用下来感觉帮助不大有一些即使是已经处理的或者忽略的 Exception 也会被统计这些 Exception 大多并不会影响应用程序的运行如果参考这个的话可能会带来很多的困扰所以我觉得还是需要应用程序来统计 exception 指标更为合适一些prometheus-net.DotNetRuntime 作为 prometheus-net 的一个插件依赖于 prometheus-net 去写 metrics 信息也就是说 metrics 的信息可以通过 prometheus-net 来获取集成 asp.net core 的时候和之前集成 prometheus-net 是一样的metrics path 是同一个可以参考我这个项目: https://github.com/OpenReservation/ReservationServer/tree/dev/OpenReservation注意作者推荐 .netcore3.0 以上使用.netcore 2.x 会有一些 BUG可以在 Issue 里看到Referencehttps://github.com/djluck/prometheus-net.DotNetRuntimehttps://docs.microsoft.com/en-us/dotnet/framework/performance/clr-etw-eventshttps://github.com/dotnet/aspnetcore/issues/2312#issuecomment-359514074https://github.com/OpenReservation/ReservationServer