ASP.NET Core MVC application background tasks

Original: ASP.NET MVC application Core background tasks

  Cache common data (such as Find) can significantly improve your MVC Web application performance and response time in the memory of the application. Of course, these data must be refreshed periodically.

  Of course, you can use any method to update the data, such as Redis provides a set of cached objects life time, then for the practice of this updated single object I think it is not consistent with my programming habits, we can use QuartZ. NET framework for task scheduling, we unified cache update in the mission plan, we met our goal.

  Quartz well-supported, cross-platform library that can be used in an application internal scheduling task. Because middleware supports ASP.NET Core architecture and out of the box, use it in .NET Core MVC Web application a little different. In this article, I will try to use the ASP.NET core application in Quartz to explain Simple Plan backstage workers scheduled task.

  I use a simple ASP.NET Core WebApi project template as the basis for the sample project. Since we do not focus on the actual response endpoint, but attention Startup.cs dependency injection part and middleware, the default project template WebApi enough.

  As a first step we should refer to the Quartz framework, I will use Nuget manager, I now use the tool is Visual Studio 2019 trial version.

Install-Package Quartz -Version 3.0.7

  If you are developing on Linux or Mac Os, then please install the .net core sdk .net using scaffolding to be introduced.

dotnet add package Quartz --version 3.0.7

  由于ASP.NET Core具有开箱即用的依赖注入支持,我们需要在启动时设置我们的解析器,但在我们这样做之前,我们需要编写我们将用于设置调度的一些Quartz接口的实现我们项目中的任务。

  我们首先需要编写我们的任务,即将按特定时间表执行的代码单元。为此,我们需要在我们的作业类中实现  Quartz.IJob接口。

复制代码
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Threading.Tasks;

namespace Schedule.WebApiCore.Sample.Schedule
{
    public class ScheduledJob : IJob
    {
        private readonly IConfiguration configuration;
        private readonly ILogger<ScheduledJob> logger;


        public ScheduledJob(IConfiguration configuration, ILogger<ScheduledJob> logger)
        {
            this.logger = logger;
            this.configuration = configuration;
        }

        public async Task Execute(IJobExecutionContext context)
        {

            this.logger.LogWarning($"Hello from scheduled task {DateTime.Now.ToLongTimeString()}");

            await Task.CompletedTask;
            
        }
    }
}
复制代码

由于它只是一个示例应用程序,因此每次作业执行时,我只会在输出中写入当前时间的消息。将从Startup.cs类方法注入Microsoft.Extensions.Configuration.IConfiguration和Microsoft.Extensions.Logging.ILogger接口实现的实例

我们需要实现的下一个接口是Quartz.Spi.IjobFactory

复制代码
using Quartz;
using Quartz.Spi;
using System;

namespace Schedule.WebApiCore.Sample.Schedule
{
    public class ScheduledJobFactory : IJobFactory
    {
        private readonly IServiceProvider serviceProvider;

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

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            return serviceProvider.GetService(typeof(IJob)) as IJob;
        }

        public void ReturnJob(IJob job) {
            var disposable = job as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        }
        
    }
}
复制代码

   我们将IJobFactory接口实现的实例分配给我们的IScheduler实例,该实例将用于在每个调度触发器上实例化作业实例。现在在我们的Startup.cs中设置依赖注入解析器。

配置#

复制代码
using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using Schedule.WebApiCore.Sample.Schedule;


namespace Schedule.WebApiCore.Sample
{
    public class Startup
    {

        public IConfiguration Configuration { get; }
        public IHostingEnvironment HostingEnvironment { get; }

        public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
        {
            this.HostingEnvironment = hostingEnvironment;
            this.Configuration = configuration;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddLogging();

            services.AddSingleton<IConfiguration>(new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{this.HostingEnvironment.EnvironmentName.ToLower()}.json")
                .Build());

            #region Configure Quartz DI

            services.Add(new ServiceDescriptor(typeof(IJob), typeof(ScheduledJob), ServiceLifetime.Transient));
            services.AddSingleton<IJobFactory, ScheduledJobFactory>();
            services.AddSingleton<IJobDetail>(provider =>
            {
                return JobBuilder.Create<ScheduledJob>()
                  .WithIdentity("Sample.job", "group1")
                  .Build();
            });

            services.AddSingleton<ITrigger>(provider =>
            {
                return TriggerBuilder.Create()
                .WithIdentity($"Sample.trigger", "group1")
                .StartNow()
                .WithSimpleSchedule
                 (s =>
                    s.WithInterval(TimeSpan.FromSeconds(5))
                    .RepeatForever()
                 )
                 .Build();
            });

            services.AddSingleton<IScheduler>(provider =>
            {
                var schedulerFactory = new StdSchedulerFactory();
                var scheduler = schedulerFactory.GetScheduler().Result;
                scheduler.JobFactory = provider.GetService<IJobFactory>();
                scheduler.Start();
                return scheduler;
            });

            #endregion


            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IScheduler scheduler)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            scheduler.ScheduleJob(app.ApplicationServices.GetService<IJobDetail>(), app.ApplicationServices.GetService<ITrigger>());

            app.UseMvc();
        }
    }
}
复制代码

修改Startup.cs#

  启动项目没有什么问题~但当你将所有部件放在Startup.cs中的一个地方时,这样更容易解释整个DI设置,在那里你可以看到所有的依赖关系和接口是如何解决的,但是从长远来看,这个Startup.cs应该是凌乱的它最终将成为维持的噩梦。出于这个原因,我将整个DI包装到扩展方法中。

  综上所述,我们的.Net Core为我们提供了解决方案,那么把Quartz的代码全部放到一个静态类中,它将使用Quartz的Microsoft依赖注入语句和管道的Microsoft.AspNetCore.Builder.IApplicationBuilder扩展  Microsoft.Extensions.DependencyInjection.IServiceCollection 。

  就我个人而言,我喜欢在项目中创建一个Extensions文件夹,然后在其中写入类,再去Startup.cs中进行配置!QuartzExtensions定义如下:

复制代码
    public static class QuartzExtensions
    {
        public static void AddQuartz(this IServiceCollection services, Type jobType)
        {
            services.Add(new ServiceDescriptor(typeof(IJob), jobType, ServiceLifetime.Transient));
            services.AddSingleton<IJobFactory, ScheduledJobFactory>();
            services.AddSingleton<IJobDetail>(provider =>
            {
                return JobBuilder.Create<ScheduledJob>()
                  .WithIdentity("Sample.job", "group1")
                  .Build();
            });

            services.AddSingleton<ITrigger>(provider =>
            {
                return TriggerBuilder.Create()
                .WithIdentity($"Sample.trigger", "group1")
                .StartNow()
                .WithSimpleSchedule
                 (s =>
                    s.WithInterval(TimeSpan.FromSeconds(5))
                    .RepeatForever()
                 )
                 .Build();
            });

            services.AddSingleton<IScheduler>(provider =>
            {
                var schedulerFactory = new StdSchedulerFactory();
                var scheduler = schedulerFactory.GetScheduler().Result;
                scheduler.JobFactory = provider.GetService<IJobFactory>();
                scheduler.Start();
                return scheduler;
            });

        }

        public static void UseQuartz(this IApplicationBuilder app)
        {
            app.ApplicationServices.GetService<IScheduler>()
                .ScheduleJob(app.ApplicationServices.GetService<IJobDetail>(),
                app.ApplicationServices.GetService<ITrigger>()
                );
        }
    }
复制代码

现在我们的Startup.cs更清洁,更容易维护和扩展!

复制代码
    public class Startup
    {
        public IConfiguration Configuration { get; }
        public IHostingEnvironment HostingEnvironment { get; }

        public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
        {
            this.HostingEnvironment = hostingEnvironment;
            this.Configuration = configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddLogging();

            services.AddSingleton<IConfiguration>(new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{this.HostingEnvironment.EnvironmentName.ToLower()}.json")
                .Build());

            services.AddQuartz(typeof(ScheduledJob));

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseQuartz();

            app.UseMvc();
        }
    }
复制代码

再次启动项目,ok 通过~

 祝.Net Core 越来越好!

Guess you like

Origin www.cnblogs.com/lonelyxmas/p/12050806.html