如何判断.NET Core WebAPI是否空闲?有没有状态监控NuGet包?
判断.NET Core Minimal API的空闲状态及监控方案
一、自定义实现空闲状态判断
最直接的方式是通过中间件+全局状态追踪实现,核心思路是监控请求的开始与结束,统计活跃请求数并记录最后请求时间:
1. 实现请求追踪中间件
创建中间件维护请求计数和最后请求时间:
public class RequestTrackingMiddleware { private readonly RequestDelegate _next; private static int _activeRequests; private static DateTime _lastRequestTime; public RequestTrackingMiddleware(RequestDelegate next) { _next = next; _lastRequestTime = DateTime.UtcNow; } public async Task InvokeAsync(HttpContext context) { Interlocked.Increment(ref _activeRequests); try { _lastRequestTime = DateTime.UtcNow; await _next(context); } finally { Interlocked.Decrement(ref _activeRequests); } } // 暴露静态方法供外部判断空闲状态 public static bool IsIdle(TimeSpan idleThreshold) { return _activeRequests == 0 && DateTime.UtcNow - _lastRequestTime >= idleThreshold; } } // 扩展方法注册中间件 public static class RequestTrackingMiddlewareExtensions { public static IApplicationBuilder UseRequestTracking(this IApplicationBuilder builder) { return builder.UseMiddleware<RequestTrackingMiddleware>(); } }
2. 在Minimal API中注册中间件
在Program.cs中添加中间件(需放在路由映射之前):
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); // 注册请求追踪中间件 app.UseRequestTracking(); // 你的API路由 app.MapGet("/", () => "Hello World!"); app.MapPost("/data", (MyData data) => Results.Ok(data)); app.Run();
3. 检查空闲状态
可在Hosted Service或其他服务中定时调用RequestTrackingMiddleware.IsIdle(TimeSpan.FromSeconds(30))判断应用是否空闲。
二、状态监控与订阅钩子的实现
没有专门针对“空闲状态订阅”的官方NuGet包,但可通过以下方式实现:
1. 自定义可订阅的状态监控服务
基于IObservable实现服务,允许其他组件订阅空闲状态变更:
public class IdleMonitorService : IObservable<bool>, IDisposable { private readonly List<IObserver<bool>> _observers = new(); private readonly IHostApplicationLifetime _appLifetime; private Timer? _checkTimer; private bool _isIdle; private readonly TimeSpan _idleThreshold; public IdleMonitorService(IHostApplicationLifetime appLifetime, IOptions<IdleMonitorSettings> settings) { _appLifetime = appLifetime; _idleThreshold = settings.Value.IdleThreshold; // 应用启动后开始定时检查 _appLifetime.ApplicationStarted.Register(StartMonitoring); _appLifetime.ApplicationStopping.Register(StopMonitoring); } private void StartMonitoring() { _checkTimer = new Timer(CheckIdleState, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); } private void StopMonitoring() { _checkTimer?.Dispose(); } private void CheckIdleState(object? state) { var newIdleState = RequestTrackingMiddleware.IsIdle(_idleThreshold); if (newIdleState != _isIdle) { _isIdle = newIdleState; foreach (var observer in _observers) { observer.OnNext(_isIdle); } } } public IDisposable Subscribe(IObserver<bool> observer) { if (!_observers.Contains(observer)) _observers.Add(observer); return new Unsubscriber(_observers, observer); } public void Dispose() { StopMonitoring(); foreach (var observer in _observers) { observer.OnCompleted(); } _observers.Clear(); } private class Unsubscriber : IDisposable { private readonly List<IObserver<bool>> _observers; private readonly IObserver<bool> _observer; public Unsubscriber(List<IObserver<bool>> observers, IObserver<bool> observer) { _observers = observers; _observer = observer; } public void Dispose() { if (_observers.Contains(_observer)) _observers.Remove(_observer); } } } // 配置类 public class IdleMonitorSettings { public TimeSpan IdleThreshold { get; set; } = TimeSpan.FromSeconds(30); } // 注册服务 public static class IdleMonitorServiceExtensions { public static IServiceCollection AddIdleMonitor(this IServiceCollection services, Action<IdleMonitorSettings> configure) { services.Configure(configure); services.AddSingleton<IdleMonitorService>(); return services; } }
2. 使用现有监控库扩展
- Microsoft.Extensions.Diagnostics.HealthChecks:可自定义健康检查,将空闲状态纳入健康状态判断,需自行实现状态变更的订阅逻辑。
- App.Metrics:可收集请求吞吐量、活跃请求数等指标,基于指标判断空闲状态,并通过其事件系统订阅指标变化触发状态通知。
使用示例
在Hosted Service中订阅空闲状态变更:
public class IdleNotificationService : BackgroundService { private readonly IdleMonitorService _idleMonitor; private IDisposable? _subscription; public IdleNotificationService(IdleMonitorService idleMonitor) { _idleMonitor = idleMonitor; } protected override Task ExecuteAsync(CancellationToken stoppingToken) { _subscription = _idleMonitor.Subscribe(new IdleObserver()); return Task.CompletedTask; } public override void Dispose() { _subscription?.Dispose(); base.Dispose(); } private class IdleObserver : IObserver<bool> { public void OnNext(bool isIdle) { Console.WriteLine(isIdle ? "应用进入空闲状态" : "应用退出空闲状态"); } public void OnError(Exception error) { // 处理错误 } public void OnCompleted() { // 处理完成 } } }
内容的提问来源于stack exchange,提问作者davincikuo
相关产品推荐
相关产品推荐

