【问题标题】:Memory consumption issue in Quartz.net coreQuartz.net 核心中的内存消耗问题
【发布时间】:2019-05-28 13:16:28
【问题描述】:

我在我的应用程序中使用 Quartz.NET 3.0.7 来处理一些计划任务,但是当我启动计划程序时,它会在计划程序运行时增加内存。我还检查了打印一些列表的简单计划任务控制台上的字符串也发生了同样的问题。我不明白什么是实际问题。我的观察是 IJob 对象在工作完成后被释放。除此之外我不知道。

我通过传递 JobType 来动态创建工作

 private IJobDetail GetJobDetailForType<TInput>(string jobKey, string jobGroup) where TInput : IJob
    {
      IJobDetail jobDetail = JobBuilder.Create<TInput>()
                                       .WithIdentity(jobKey, jobGroup)
                                       .Build();
      return jobDetail;
    }

并在此函数中初始化调度作业

  private void InitializeSchedulerJob(ScheduleJob scheduleJob)
    {

        IJobDetail jobDetail;
        ITrigger trigger = this.GetTrigger(scheduleJob.Code.ToString(), tenantCode, scheduleJob.CornSchedule);

        if (scheduleJob.Code == (int)EnumHelper.Scheduler.Job.EmailJob)
        {
          this.logger.LogDebug($"EmailJob");
          jobDetail = this.GetJobDetailForType<EmailJob>(scheduleJob.Code.ToString(), tenantCode);
        }

        this.scheduler.ScheduleJob(jobDetail, trigger);
    }

电子邮件工作代码

 public class EmailJob : IJob 
  {
    private IServiceProvider serviceProvider;

    public EmailJob(IServiceProvider serviceProvider)
    {
      this.serviceProvider = serviceProvider;
    }

    public async Task Execute(IJobExecutionContext context)
    {
      if (this.serviceProvider != null)
      {
          JobKey jobKey = context.JobDetail.Key;
          IEmailScheduleSendService emailScheduleSendServiceNew = this.serviceProvider.GetRequiredService<IEmailScheduleSendService>();
          ILogger<EmailJob> logger = this.serviceProvider.GetRequiredService<ILogger<EmailJob>>();
          logger.LogDebug($"FROM EXECUTE METHOD | {jobKey.Name} | {jobKey.Group} | START");
          await emailScheduleSendServiceNew.EmailScheduleSendAsync(context);
          logger.LogDebug($"FROM EXECUTE METHOD | {jobKey.Name} | {jobKey.Group} | END");
        }
      }
    }

【问题讨论】:

  • 您是否尝试过使用内存配置文件来找出导致内存消耗的原因?
  • 你使用一些 DI 或 ServiceLocator 吗?
  • 是的。我正在使用 .net core 内置 DI
  • 请展示代码如何创建作业以及如何注入它们的依赖项。我没记错,Quartz 想在作业运行后释放它们,但 .Net Core DI 不支持。

标签: c# quartz-scheduler quartz.net


【解决方案1】:

您可能希望开始运行一些性能计数器来监控 CPU 使用率和内存统计信息并找出发生了什么。

如果这不能让您得到任何明显的答案,那么是时候开始分析了。

【讨论】:

  • 我尝试使用 dotTrace 但我不明白如何检测问题。
【解决方案2】:

我猜你的服务定位器请求的服务在使用后没有释放。您可以通过在您请求的服务之一中实现IDisposable 接口来检查这一点,并验证是否调用了Dispose()。我猜它不是。

要解决此问题,您可以将服务注册为作用域并手动打开作用域。这将确保所有服务在使用后被丢弃。

public async Task Execute(IJobExecutionContext context)
{
    // this check is superfluous and can be omitted. 
    // if you want to ensure that the service locator is there, check this in the constructor.
    // with a good DI framework, it can't be null.
    if (this.serviceProvider != null)
    {
        // open the scope and dispose it after use.
        using (var serviceScope = host.Services.CreateScope())
        {
            // get the service locator from the scope.
            var services = serviceScope.ServiceProvider;

            try
            {                   
                JobKey jobKey = context.JobDetail.Key;
                IEmailScheduleSendService emailScheduleSendServiceNew = services.GetRequiredService<IEmailScheduleSendService>();
                ILogger<EmailJob> logger = services.GetRequiredService<ILogger<EmailJob>>();
                logger.LogDebug($"FROM EXECUTE METHOD | {jobKey.Name} | {jobKey.Group} | START");
                await emailScheduleSendServiceNew.EmailScheduleSendAsync(context);
                logger.LogDebug($"FROM EXECUTE METHOD | {jobKey.Name} | {jobKey.Group} | END");
            }
            catch (Exception ex)
            {
                logger.LogDebug($"SOMETHING WENT WRONG!");
            }
        }
    }        
}

【讨论】:

  • 也许将服务注册为临时服务会更好。
  • @keuleJ 我认为瞬态不会起作用,因为.Net Core DI 无法跟踪它们的生命周期。但值得一试。
  • 作用域服务确实需要一个可以被垃圾回收的作用域。瞬态服务不需要垃圾收集范围。
  • @keuleJ 这里的问题是 .Net Core DI 无法跟踪瞬态服务的生命周期。解决后它们将永远存在,并且内存泄漏仍然存在。如果您知道更好的方法,请随时添加答案。但这个问题似乎被放弃了。
猜你喜欢
  • 1970-01-01
  • 2013-08-21
  • 2015-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 2012-02-12
相关资源
最近更新 更多