zoukankan      html  css  js  c++  java
  • Aspnet Zero中使用Windows service (Topshelf)来承载Quartz.net任务

    Aspnet Zero使用Windows service (Topshelf)来承载Quartz.net任务

    网上有很多关于如何使用Topshelf创建ABP的Quartz windows服务,但很少(没有)有介绍如何配合Aspnet Zero使用的文章,本文记录集成过程,以供参考。

    1. 在官方Aspnet Zero模板解决方案中建立Console类型的项目,并安装以下nuget package:

      Topshelf

      Abp.Quartz

      Abp.Castle.Log4Net

    2. 添加引用MyCompanyName.AbpZeroTemplate.CoreMyCompanyName.AbpZeroTemplate.EntityFrameworkCore项目

    3. 最终引用如图:

    4. 创建Module文件,

      • 添加相关DependsOn属性;
      • abpZeroTemplateEntityFrameworkCoreModule.SkipDbSeed = true; 这里我们需要禁用数据库初始化动作,因为所有的初始化动作都在Host端完成;
      • 设置数据库连接字符串Configuration.DefaultNameOrConnectionString = _appConfiguration.GetConnectionString( AbpZeroTemplateConsts.ConnectionStringName );

      最终文件如下:

      namespace MyCompanyName.AbpZeroTemplate.WinService
      {
          [DependsOn(typeof(AbpZeroTemplateCoreModule),
              typeof(AbpZeroTemplateEntityFrameworkCoreModule),
              typeof(AbpQuartzModule)
              )]
          public class AbpZeroWinServiceModule : AbpModule
          {
              private readonly IConfigurationRoot _appConfiguration;
      
              public AbpZeroWinServiceModule(AbpZeroTemplateEntityFrameworkCoreModule abpZeroTemplateEntityFrameworkCoreModule)
              {
                  abpZeroTemplateEntityFrameworkCoreModule.SkipDbSeed = true;
      
                  _appConfiguration = AppConfigurations.Get(
                      typeof(AbpZeroWinServiceModule).GetAssembly().GetDirectoryPathOrNull(),
                      addUserSecrets: true
                  );
              }
      
              public override void PreInitialize()
              {
                  //Set default connection string
                  Configuration.DefaultNameOrConnectionString = _appConfiguration.GetConnectionString(
                      AbpZeroTemplateConsts.ConnectionStringName
                  );
              }
      
              public override void Initialize()
              {
                  this.IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
      
              }
          }
      }
      
    5. 修改Program.cs文件

      • 设置工作目录 Directory.SetCurrentDirectory(currentDirectory);, 目的是为了保证工作在windows service时log文件存放目录正确,如果不设置, 工作在windows service时log文件将会存放在system32目录中
      • 注册IdentityRegistrar以及添加abp依赖,这一步是必须的,否则会出现依赖错误:
        Castle.MicroKernel.Handlers.HandlerException: 'Can't create component 'Portal.Authorization.Users.UserManager' as it has dependencies to be satisfied.
        添加abp依赖的同时我们同时添加log4net和插件支持.(注意路径)
        var services = new ServiceCollection();
        IdentityRegistrar.Register(services);
        
        var abpBootstrapper = AbpBootstrapper.Create<AbpZeroWinServiceModule>(options =>
        {
            options.IocManager.IocContainer.AddFacility<LoggingFacility>(
                                f => f.UseAbpLog4Net().WithConfig(Path.Combine(currentDirectory, $"log4net.config"))
                            );
            options.PlugInSources.AddFolder(Path.Combine(currentDirectory, "Plugins"), SearchOption.AllDirectories);
        });
        
        services.AddSingleton(abpBootstrapper);
        abpBootstrapper.IocManager.IocContainer.AddServices(services);
        

      完整Program.cs代码如下:

      class Program
      {
          static void Main(string[] args)
          {
              var currentDirectory = typeof(Program).GetAssembly().GetDirectoryPathOrNull();
              // 设置工作目录. 保证工作在windows service时log文件存放目录正确
              // 如果不设置, 工作在windows service时log文件将会存放在system32目录中
              Directory.SetCurrentDirectory(currentDirectory);
      
              var services = new ServiceCollection();
              IdentityRegistrar.Register(services);
                          
              var abpBootstrapper = AbpBootstrapper.Create<AbpZeroWinServiceModule>(options =>
              {
                  options.IocManager.IocContainer.AddFacility<LoggingFacility>(
                                      f => f.UseAbpLog4Net().WithConfig(Path.Combine(currentDirectory, $"log4net.config"))
                                  );
                  options.PlugInSources.AddFolder(Path.Combine(currentDirectory, "Plugins"), SearchOption.AllDirectories);
              });
      
              services.AddSingleton(abpBootstrapper);
              abpBootstrapper.IocManager.IocContainer.AddServices(services);
      
              HostFactory.Run(x =>
              {
                  x.Service<AbpZeroWinService>(s =>
                  {
                      s.ConstructUsing(name => new AbpZeroWinService());
                      s.WhenStarted((tc, hostControl) => tc.Start(hostControl));
                      s.WhenStopped((tc, hostControl) => tc.Stop(hostControl));
                  });
      
                  x.RunAsLocalSystem();
                  x.StartAutomatically();
      
                  x.SetDescription("ABP服务测试");
                  x.SetDisplayName("ABPTestService");
                  x.SetServiceName("ABPTestService");
              });
          }
      }
      
    6. 启动ABP. Windows service启动时会调用s.ConstructUsing(name => new AbpZeroWinService());, 因此我们在AbpZeroWinService中启动ABP.

      • 创建AbpZeroWinService类继承自ServiceControl, 在Start中初始化AbpBootstrapper, 同时在停止Stop中销毁AbpBootstrapper. 代码如下:
      public class AbpZeroWinService : ServiceControl
      {
          private AbpBootstrapper _bootstrapper;
          public bool Start(HostControl hostControl)
          {
              _bootstrapper = IocManager.Instance.Resolve<AbpBootstrapper>();
              _bootstrapper.Initialize();
              return true;
          }
      
          public bool Stop(HostControl hostControl)
          {
              _bootstrapper.Dispose();
              return true;
          }
      }
      
    7. quartz.net的配置quartz.config中必须使用AdoJobStore类型,并且使用和Host一样的Quartz数据库连接,这样才能实现在host上添加任务,最终由windows service来执行任务。
      (请在HostModule的PreInitialize方法中禁用Job执行Configuration.BackgroundJobs.IsJobExecutionEnabled = false;)

    8. 运行前确保Quartz.net数据库已建立,如何建立请参考Quartz.net官方文档

    以上如有错误的地方请大家指正! 如果更好的实现方式,也请分享一下。
    最后给出WindowService项目的源码,Aspnet Zero的项目自行解决。
    source code

  • 相关阅读:
    nginx.conf配置
    分组查询最近时间的记录
    jQuery中$(function(){})与(function($){})(jQuery)、$(document).ready(function(){})等的区别详细讲解
    form表单的onsubmit()问题 集合
    vs代码快捷键
    localStorage存储方法
    display和visibility的区别
    Javascript Math ceil()、floor()、round()三个函数的区别
    sqlservere小计合计总计
    CentOS 7.1 图形化安装
  • 原文地址:https://www.cnblogs.com/FocusNet/p/13474785.html
Copyright © 2011-2022 走看看