Quartz.Examples.AspNetCore

​ .NetCore的Web系统,后台主要执行多个触发器任务,前台展示所有触发器信息和正在执行的作业的相关信息,还可以通过访问health-UI来查看目前系统健康状态

  • launchSettings.json

    {
    "profiles": {
    "Quartz.Examples.AspNetCore": {
    "commandName": "Project",
    // 自动打开浏览器
    "launchBrowser": true,
    // 默认的链接地址
    "applicationUrl": "http://localhost:5000",
    "environmentVariables": {
    // 开发模式
    "ASPNETCORE_ENVIRONMENT": "Development"
    }
    }
    }
    }
  • appsettings.json

    Loggin配置,cron设置,路由设置

  • quartz_jobs.config

    触发器和作业的xml配置

  • Startup

    1. 创建Serilog日志

      public Startup(IConfiguration configuration)
      {
      Log.Logger = new LoggerConfiguration()
      // 从默认的日志组件中填充事件信息(使用默认配置)
      .Enrich.FromLogContext()
      // 写入到控制器中
      .WriteTo.Console()
      // 创建日志
      .CreateLogger();
      // 赋值
      Configuration = configuration;
      }
      public IConfiguration Configuration { get; }
      // 向容器中添加日志
      services.AddLogging(loggingBuilder =>
      {
      loggingBuilder.ClearProviders();
      loggingBuilder.AddSerilog(dispose: true);
      });
    2. OpenTelemetry

      通过标准化不同的应用程序和框架如何收集和发出可观察性遥测数据,用于管理观测类的数据。

      • 可观察性遥测(分布式跟踪、指标等)的供应商中立规范
      • 实现用于检测的公共接口的API
      • 应用程序使用SDK为插件作者配置工具和接口以编写导出器
      • 使你能够将数据发送到你选择的遥测后端的导出器

      OpenTelemetry搭配Zipkin来追踪ASP.NET Core服务之间的WebAPI和gRPC请求,Zipkin官网地址

      OpenTelemetry搭配Uber的分布式跟踪系统Jaeger来监视系统

      // 添加观测数据工具
      services.AddOpenTelemetryTracing(builder =>
      {
      builder
      // 启用Quartz.NET作业自动数据收集功能
      .AddQuartzInstrumentation()
      // 使用Zipkin来追踪数据请求
      .AddZipkinExporter(o =>
      {
      o.Endpoint = new Uri("http://localhost:9411/api/v2/spans");
      })
      // 添加Jaeger监听
      .AddJaegerExporter(o =>
      {
      // these are the defaults
      o.AgentHost = "localhost";
      o.AgentPort = 6831;
      });
      });
    3. services.AddRazorPages()

      1. Razor Pages 功能:cshtml视图模板
      2. 身分验证服务
      3. Data Annotation - 支持 Attribute 资料检核及 IValidateObject
      4. Cache Tag Helper
      5. AddMvcCore()核心服务
    4. Quartz.NET相关代码

      // 配置
      services.Configure<QuartzOptions>(options =>
      {
      // 忽略重复项,默认为false
      options.Scheduling.IgnoreDuplicates = true;
      // 替换现有配置信息和数据信息,默认为true
      options.Scheduling.OverWriteExistingData = true;
      });
      // 添加调度配置
      services.AddQuartz(q =>
      {
      // 唯一表示
      q.SchedulerId = "Scheduler-Core";
      // 程序关闭时中断作业
      q.InterruptJobsOnShutdown = true;
      // 程序关闭时等待作业关闭
      q.InterruptJobsOnShutdownWithWait = true;
      // 并发作业数,默认是1
      q.MaxBatchSize = 5;
      // -- 一下是默认方法
      // 默认使用Microsoft的依赖注入
      q.UseMicrosoftDependencyInjectionJobFactory();
      // 使用默认的类型加载器
      q.UseSimpleTypeLoader();
      // 使用默认的内存存储
      q.UseInMemoryStore();
      // 默认的线程池,最大线程数为10
      q.UseDefaultThreadPool(maxConcurrency: 10);
      // 自动中断长时间运行的作业
      q.UseJobAutoInterrupt(options =>
      {
      // 默认最长时间为5分钟
      options.DefaultMaxRunTime = TimeSpan.FromMinutes(5);
      });
      // 使用时间转换器,主要用于不同系统之间的转换
      q.UseTimeZoneConverter(); // 添加监听
      q.AddSchedulerListener<SampleSchedulerListener>();
      q.AddJobListener<SampleJobListener>(GroupMatcher<JobKey>.GroupEquals(jobKey.Group));
      q.AddTriggerListener<SampleTriggerListener>();
      }
      // 每次都创建一个不同的ExampleJob实例 (AddTransient)
      services.AddTransient<ExampleJob>(); // 添加SecondSampleJobListener监听(AddSingleton:单例模式)
      services.AddSingleton<IJobListener, SecondSampleJobListener>();
      services.AddSingleton<ITriggerListener>(serviceProvider =>
      {
      // 添加SecondSampleTriggerListener触发器
      var logger = serviceProvider.GetRequiredService<ILogger<SecondSampleTriggerListener>>();
      return new SecondSampleTriggerListener(logger, "Example value");
      });
      // 将appsettings.json的配置信息映射到SampleOptions的实例中
      services.Configure<SampleOptions>(Configuration.GetSection("Sample"));
      // 增加Quzrtz.NET的配置项
      services.AddOptions<QuartzOptions>()
      .Configure<IOptions<SampleOptions>>((options, dep) =>
      {
      if (!string.IsNullOrWhiteSpace(dep.Value.CronSchedule))
      {
      var jobKey = new JobKey("options-custom-job", "custom");
      options.AddJob<ExampleJob>(j => j.WithIdentity(jobKey));
      options.AddTrigger(trigger => trigger
      .WithIdentity("options-custom-trigger", "custom")
      .ForJob(jobKey)
      .WithCronSchedule(dep.Value.CronSchedule));
      }
      });
      // 添加Quartz.NET的服务
      services.AddQuartzServer(options =>
      {
      // 当程序关闭时需要等待作业完成
      options.WaitForJobsToComplete = true;
      });
    5. AddHealthChecksUI

      添加健康检查的页面

      • 精简方式,访问/health判断健康状态

        /*
        健康等级
        Healthy 健康
        Unhealthy 不良
        Degraded 降级
        */
        public void ConfigureServices(IServiceCollection services){
        service.AddHealthchecks();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
        //可以通过访问/health链接来查看健康等级
        app.MapHealthChecks("/health");
        }
      • UI页面-Quartz.NET方式

        // appsettings.json中
        // 健康检测的配置信息
        "HealthChecksUI": {
        // 可以同时监控多个健康检查API
        "HealthChecks": [
        {
        "Name": "localhost",
        "Uri": "/healthz"
        }
        ],
        // 当API的健康状态改变时,向指定Uri发送告警数据
        "Webhooks": []
        } public void ConfigureServices(IServiceCollection services){
        // 添加健康检测页面,并将数据存放到内存中
        services
        .AddHealthChecksUI()
        .AddInMemoryStorage();
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
        app.UseEndpoints(endpoints =>
        {
        // 配置路由
        endpoints.MapRazorPages();
        // 健康检测的url链接
        endpoints.MapHealthChecks("healthz", new HealthCheckOptions
        {
        Predicate = _ => true,
        // 返回json格式健康检查数据
        ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
        });
        // 添加健康检测页面到路由中,默认为healthchecks-ui
        endpoints.MapHealthChecksUI();
        });
        }
    6. Configure(IApplicationBuilder app, IWebHostEnvironment env)

      配置Http request的管道

      • app.UseHsts() 将 HTTP 严格传输安全协议 (HSTS) 标头发送到客户端
      • app.UseStaticFiles(); 使用静态资源
      • app.UseRouting() 使用路由
  • SampleJobListener

    监听中添加logger

    // 初始化请参见:Startup->1.创建Serilog日志
    // 实现JobListenerSupport而非IJobListener
    public class SampleJobListener : JobListenerSupport
    {
    //声明一个logger
    private readonly ILogger<SampleJobListener> logger; public SampleJobListener(ILogger<SampleJobListener> logger)
    {
    //赋值
    this.logger = logger;
    }
    public override string Name => "Sample Job Listener";
    public override Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default)
    {
    // 使用
    logger.LogInformation("The job is about to be executed, prepare yourself!");
    return Task.CompletedTask;
    }
    } // 程序中使用logger的监听
    services.AddQuartz(q =>
    // 调用监听类-只给jobkey.Group这个群组的创建此监听
    q.AddJobListener<SampleJobListener>(GroupMatcher<JobKey>.GroupEquals(jobKey.Group));
    );
  • wwwroot

    静态资源文件

    通过后台UseStaticFiles()方法引入静态变量

  • Pages部分---Razor页面

    1. 自动生成部分

      // View  加上@符就代表是c#相关代码
      @page
      @model Quartz.Examples.AspNetCore.Pages.Index1Model
      @{
      } // ViewModel
      namespace Quartz.Examples.AspNetCore.Pages
      {
      public class Index1Model : PageModel
      {
      // 页面加载时调用
      public void OnGet()
      {
      }
      }
      }

      2.Quartz.NET中的Razor

      • View

        @page
        @model IndexModel
        @{
        // Html中的title标签值
        ViewData["Title"] = "Home page";
        }
        <div class="text-center">
        <h1 class="display-4">Scheduled Triggers</h1>
        // 调用Control中的Model的Triggers变量
        @foreach (var trigger in Model.Triggers)
        {
        // 将触发器的群组和名称放到span标签中
        <span>@trigger.Group / @trigger.Name</span>
        <br/>
        }
        <br />
        <h1 class="display-4">Currently Executing Jobs</h1>
        @foreach (var job in Model.CurrentlyExecutingJobs)
        {
        <span>@job.JobDetail.Key.Group / @job.JobDetail.Key.Name - triggered by @job.Trigger.Key.Group / @job.Trigger.Key.Name</span>
        <br/>
        }
        <br />
        <h1 class="display-4">Health Status</h1>
        <a href="/healthchecks-ui">Open health checks UI</a>
        </div>
      • ViewModel

        public class IndexModel : PageModel
        {
        // 引入Logging
        private readonly ILogger<IndexModel> _logger;
        // 声明一个调度工厂类
        private readonly ISchedulerFactory schedulerFactory; // 在服务启动前需要将需要的类进行配置,配置完成后系统会通过接口类获得单例的相关实现类,如java的spring
        public IndexModel(
        ILogger<IndexModel> logger,
        ISchedulerFactory schedulerFactory)
        {
        _logger = logger;
        this.schedulerFactory = schedulerFactory;
        }
        // 只读的集合,赋值为空集合
        public IReadOnlyCollection<TriggerKey> Triggers { get; set; } = Array.Empty<TriggerKey>();
        public IReadOnlyCollection<IJobExecutionContext> CurrentlyExecutingJobs { get; set; } = Array.Empty<IJobExecutionContext>(); public async Task OnGet()
        {
        // 等待获取调取实例
        var scheduler = await schedulerFactory.GetScheduler();
        //获得所有的触发器
        Triggers = await scheduler.GetTriggerKeys(GroupMatcher<TriggerKey>.AnyGroup());
        // 获得所有在执行的调度作业上下文
        CurrentlyExecutingJobs = await scheduler.GetCurrentlyExecutingJobs();
        }
        }

Quartz.Net源码Example之Quartz.Examples.AspNetCore的更多相关文章

  1. Pytorch学习之源码理解:pytorch/examples/mnists

    Pytorch学习之源码理解:pytorch/examples/mnists from __future__ import print_function import argparse import ...

  2. cache2go源码最后一讲 - examples

    先看一下我们讲到哪里了: cache2go的源码前面我们已经讲完了cacheitem和cachetable的实现,今天cahce和examples会一起讲完~ 1.cache.go源码 ​      ...

  3. ASP.NET Core 源码阅读笔记(5) ---Microsoft.AspNetCore.Routing路由

    这篇随笔讲讲路由功能,主要内容在项目Microsoft.AspNetCore.Routing中,可以在GitHub上找到,Routing项目地址. 路由功能是大家都很熟悉的功能,使用起来也十分简单,从 ...

  4. ASP.NET Core 源码阅读笔记(3) ---Microsoft.AspNetCore.Hosting

    有关Hosting的基础知识 Hosting是一个非常重要,但又很难翻译成中文的概念.翻译成:寄宿,大概能勉强地传达它的意思.我们知道,有一些病毒离开了活体之后就会死亡,我们把那些活体称为病毒的宿主. ...

  5. java ssm 后台框架平台 项目源码 websocket IM quartz springmvc

    A代码编辑器,在线模版编辑,仿开发工具编辑器,pdf在线预览,文件转换编码B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器freemaker模版技术 ,0个 ...

  6. quartz(7)-源码分析

    定时器启动 上图通过spring加载quartz <bean id="scheduler" class="org.springframework.schedulin ...

  7. Quartz.Net系列(三):解读Quartz.Net源码领略设计模式在其中的应用

    1.Builder(建造者)模式 JobBuilder  DateBuilder  其他的Builder(TriggerBuilder.SchedulerBuilder等) 2.抽象工厂模式 ISch ...

  8. quartz集群调度机制调研及源码分析---转载

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  9. 定时组件quartz系列<三>quartz调度机制调研及源码分析

    quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...

  10. anki_vector SDK源码解析(教程)

    一:最近anki vector robot开放了Python SDK,我听到的第一时间就赶快上网查了查,先抛几个官网重要链接吧: Python编程API手册及环境搭建等: https://sdk-re ...

随机推荐

  1. iptables综合实验: 两个私有网络的互相通迅

    环境准备: 主机A IP:192.168.0.6/24 网关改为192.168.0.8 firewallA IP:eth1 192.168.0.8/24 eth0 10.0.0.8/24 删除默认路由 ...

  2. 实例解读丨关于GaussDB ETCD服务异常

    摘要:本文通过对ETCD服务异常问题分析,代码展示解决方案. 本文分享自华为云社区<[实例状态]GaussDB ETCD服务异常>,作者:酷哥. 首先确认是否是虚拟机.网络故障 虚拟机故障 ...

  3. 华为开发者大会2022:HMS Core 3D建模服务再升级,万物皆可驱动

    11月4日,HDC2022华为开发者大会在东莞松山湖举办.在本次大会的HMS Core创新图形能力分论坛中,HMS Core重点介绍了其在3D技术领域的创新应用方向,其中3D建模服务展示了创新的自动骨 ...

  4. 成熟企业级开源监控解决方案Zabbix6.2关键功能实战-上

    @ 目录 概述 定义 监控作用 使用理解 监控对象和指标 架构组成 常用监控软件分析 版本选型 俗语 安装 部署方式 部署 zabbix-agent 概述 定义 Zabbix 官网地址 https:/ ...

  5. <一>类,对象,this指针

    C++ 类:实体的抽象类型 实体(属性,行为) ->ADT(abstract data type) 类(属性->成员变量,行为->成员方法) OOP语言4大特征 抽象 封装/隐藏(通 ...

  6. CSS动画-transition/animation

    HTML系列: 人人都懂的HTML基础知识-HTML教程(1) HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CS ...

  7. CSP-J/S 2021 游记

    \(\large\texttt{Day -1}\) 晚上好累啊,去集训了,回来之后发现十一点了还码了一会儿,只能祈求上帝明天不会打瞌睡. \(\large\texttt{Day 0}\) 意料中的事情 ...

  8. Go语言核心36讲43-----io包中接口的好处与优势

    上一篇文章中,我主要讲到了io.Reader的扩展接口和实现类型.当然,io代码包中的核心接口不止io.Reader一个. 我们基于它引出的一条主线,只是io包类型体系中的一部分.我们很有必要再从另一 ...

  9. 基于python的数学建模---非线性规划

    凸函数的非线性规划 minimize 求解的是局部最优解 简单的函数,无所谓 复杂的函数 初始值的设定很重要 scipy.optimize.minimize(fun,x0,args=(),method ...

  10. 【DL论文精读笔记】VGGNet

    VGGNet(Very Deep Convolutional Networks) 1.introduction ● 采用3x3的小卷积核应用在比较深的网络里 ● 结果不错,赢得了2014 Imagen ...