Browse Source

集成 hangfire

pull/6/head
WangJunZzz 5 years ago
parent
commit
862be11bfe
  1. 14
      aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Jobs/IRecurringJob.cs
  2. 14
      aspnet-core/services/src/CompanyName.ProjectName.Application/Jobs/TestJob.cs
  3. 2
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/CompanyName.ProjectName.HttpApi.Host.csproj
  4. 32
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/CustomHangfireAuthorizeFilter.cs
  5. 81
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Jobs/CronType.cs
  6. 17
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Jobs/RecurringJobsExtensions.cs
  7. 1683
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Logs/logs.txt
  8. 152
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs
  9. 3
      aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/appsettings.json

14
aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Jobs/IRecurringJob.cs

@ -0,0 +1,14 @@
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace CompanyName.ProjectName.Jobs
{
public interface IRecurringJob : ITransientDependency
{
/// <summary>
/// 执行任务
/// </summary>
/// <returns></returns>
Task ExecuteAsync();
}
}

14
aspnet-core/services/src/CompanyName.ProjectName.Application/Jobs/TestJob.cs

@ -0,0 +1,14 @@
using System;
using System.Threading.Tasks;
namespace CompanyName.ProjectName.Jobs
{
public class TestJob : IRecurringJob
{
public Task ExecuteAsync()
{
Console.WriteLine($"job 测试- {DateTime.Now}");
return Task.CompletedTask;
}
}
}

2
aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/CompanyName.ProjectName.HttpApi.Host.csproj

@ -9,6 +9,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Hangfire.MySqlStorage" Version="2.0.3" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.*" />
@ -16,6 +17,7 @@
<PackageReference Include="Volo.Abp.Account.Web" Version="$(AbpPackageVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy" Version="$(AbpPackageVersion)" />
<PackageReference Include="Volo.Abp.Autofac" Version="$(AbpPackageVersion)" />
<PackageReference Include="Volo.Abp.BackgroundJobs.HangFire" Version="4.3.3" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="$(AbpPackageVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="$(AbpPackageVersion)" />
<PackageReference Include="Volo.Abp.Swashbuckle" Version="$(AbpPackageVersion)" />

32
aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/CustomHangfireAuthorizeFilter.cs

@ -1,16 +1,16 @@
// using Hangfire.Dashboard;
// using Microsoft.Extensions.DependencyInjection;
// using Volo.Abp.Users;
//
// namespace CompanyNameProjectName.Extensions.Filters
// {
// public class CustomHangfireAuthorizeFilter : IDashboardAuthorizationFilter
// {
// public bool Authorize(DashboardContext context)
// {
// //var currentUser = context.GetHttpContext().RequestServices.GetRequiredService<ICurrentUser>();
// //return currentUser.IsAuthenticated;
// return true;
// }
// }
// }
using Hangfire.Dashboard;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Users;
namespace CompanyNameProjectName.Extensions.Filters
{
public class CustomHangfireAuthorizeFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
//var currentUser = context.GetHttpContext().RequestServices.GetRequiredService<ICurrentUser>();
//return currentUser.IsAuthenticated;
return true;
}
}
}

81
aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Jobs/CronType.cs

@ -0,0 +1,81 @@
using System;
using Hangfire;
namespace CompanyName.ProjectName.Jobs
{
/// <summary>
/// Cron类型
/// </summary>
public static class CronType
{
/// <summary>
/// 周期性为分钟的任务
/// </summary>
/// <param name="interval">执行周期的间隔,默认为每分钟一次</param>
/// <returns></returns>
public static string Minute(int interval = 1)
{
return "1 0/" + interval.ToString() + " * * * ? ";
}
/// <summary>
/// 周期性为小时的任务
/// </summary>
/// <param name="minute">第几分钟开始,默认为第一分钟</param>
/// <param name="interval">执行周期的间隔,默认为每小时一次</param>
/// <returns></returns>
public static string Hour(int minute = 1, int interval = 1)
{
return "1 " + minute + " 0/" + interval.ToString() + " * * ? ";
}
/// <summary>
/// 周期性为天的任务
/// </summary>
/// <param name="hour">第几小时开始,默认从1点开始</param>
/// <param name="minute">第几分钟开始,默认从第1分钟开始</param>
/// <param name="interval">执行周期的间隔,默认为每天一次</param>
/// <returns></returns>
public static string Day(int hour = 1, int minute = 1, int interval = 1)
{
return "1 " + minute.ToString() + " " + hour.ToString() + " 1/" + interval.ToString() + " * ? ";
}
/// <summary>
/// 周期性为周的任务
/// </summary>
/// <param name="dayOfWeek">星期几开始,默认从星期一点开始</param>
/// <param name="hour">第几小时开始,默认从1点开始</param>
/// <param name="minute">第几分钟开始,默认从第1分钟开始</param>
/// <returns></returns>
public static string Week(DayOfWeek dayOfWeek = DayOfWeek.Monday, int hour = 1, int minute = 1)
{
return Cron.Weekly(dayOfWeek, hour, minute);
}
/// <summary>
/// 周期性为月的任务
/// </summary>
/// <param name="day">几号开始,默认从一号开始</param>
/// <param name="hour">第几小时开始,默认从1点开始</param>
/// <param name="minute">第几分钟开始,默认从第1分钟开始</param>
/// <returns></returns>
public static string Month(int day = 1, int hour = 1, int minute = 1)
{
return Cron.Monthly(day, hour, minute);
}
/// <summary>
/// 周期性为年的任务
/// </summary>
/// <param name="month">几月开始,默认从一月开始</param>
/// <param name="day">几号开始,默认从一号开始</param>
/// <param name="hour">第几小时开始,默认从1点开始</param>
/// <param name="minute">第几分钟开始,默认从第1分钟开始</param>
/// <returns></returns>
public static string Year(int month = 1, int day = 1, int hour = 1, int minute = 1)
{
return Cron.Yearly(month, day, hour, minute);
}
}
}

17
aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Jobs/RecurringJobsExtensions.cs

@ -0,0 +1,17 @@
using Hangfire;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
namespace CompanyName.ProjectName.Jobs
{
public static class RecurringJobsExtensions
{
public static void CreateRecurringJob(this ApplicationInitializationContext context)
{
using var scope = context.ServiceProvider.CreateScope();
var testJob =
scope.ServiceProvider.GetService<TestJob>();
RecurringJob.AddOrUpdate("测试Job", () => testJob.ExecuteAsync(), CronType.Minute(1));
}
}
}

1683
aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/Logs/logs.txt

File diff suppressed because it is too large

152
aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs

@ -15,7 +15,11 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using CompanyName.ProjectName.EntityFrameworkCore;
using CompanyName.ProjectName.Extensions.Filters;
using CompanyName.ProjectName.Jobs;
using CompanyName.ProjectName.MultiTenancy;
using CompanyNameProjectName.Extensions.Filters;
using Hangfire;
using Hangfire.MySql;
using Microsoft.IdentityModel.Tokens;
using StackExchange.Redis;
using Microsoft.OpenApi.Models;
@ -27,6 +31,8 @@ using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.BackgroundJobs.Hangfire;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Identity.AspNetCore;
@ -47,13 +53,19 @@ namespace CompanyName.ProjectName
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpSwashbuckleModule),
typeof(AbpAccountWebModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule)
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpBackgroundJobsHangfireModule)
)]
public class ProjectNameHttpApiHostModule : AbpModule
{
private const string DefaultCorsPolicyName = "Default";
public override void OnPostApplicationInitialization(ApplicationInitializationContext context)
{
context.CreateRecurringJob();
base.OnPostApplicationInitialization(context);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
@ -70,9 +82,78 @@ namespace CompanyName.ProjectName
ConfigureOptions(context);
ConfigureHealthChecks(context);
ConfigureJwtAuthentication(context, configuration);
ConfigureHangfireMysql(context);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
if (!env.IsDevelopment())
{
app.UseErrorPage();
}
app.UseCorrelationId();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName);
app.UseAuthentication();
if (MultiTenancyConsts.IsEnabled)
{
app.UseMultiTenancy();
}
app.UseAuthorization();
app.UseSwagger();
app.UseAbpSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "ProjectName API");
var configuration = context.GetConfiguration();
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
options.OAuthScopes("ProjectName");
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseUnitOfWork();
app.UseConfiguredEndpoints();
app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); });
app.UseHangfireDashboard("/hangfire", new DashboardOptions()
{
Authorization = new[] {new CustomHangfireAuthorizeFilter()}
});
}
public void ConfigureHangfireMysql(ServiceConfigurationContext context)
{
Configure<AbpBackgroundJobOptions>(options => { options.IsJobExecutionEnabled = true; });
context.Services.AddHangfire(config =>
{
config.UseStorage(new MySqlStorage(context.Services.GetConfiguration().GetConnectionString("Hangfire"),
new MySqlStorageOptions()
{
//CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
//SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
//QueuePollInterval = TimeSpan.Zero,
//UseRecommendedIsolationLevel = true,
//DisableGlobalLocks = true
}));
});
}
/// <summary>
/// 配置JWT
/// </summary>
@ -97,10 +178,12 @@ namespace CompanyName.ProjectName
//ClockSkew = TimeSpan.Zero,
ValidIssuer = configuration["Jwt:Issuer"],
ValidAudience = configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"]))
IssuerSigningKey =
new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"]))
};
});
}
/// <summary>
/// 配置options
/// </summary>
@ -147,7 +230,6 @@ namespace CompanyName.ProjectName
});
}
/// <summary>
/// 健康检查
@ -155,10 +237,9 @@ namespace CompanyName.ProjectName
/// <param name="context"></param>
private void ConfigureHealthChecks(ServiceConfigurationContext context)
{
var redisConnectionString =
var redisConnectionString =
context.Services.GetConfiguration().GetValue<string>("Redis:Configuration")
+",defaultdatabase="
+ ",defaultdatabase="
+ context.Services.GetConfiguration().GetValue<int>("Redis:DatabaseId", 1);
var mysqlConnectionString = context.Services.GetConfiguration().GetConnectionString("Default");
context.Services.AddHealthChecks().AddRedis(redisConnectionString).AddMySql(mysqlConnectionString);
@ -246,9 +327,9 @@ namespace CompanyName.ProjectName
{
if (!hostingEnvironment.IsDevelopment())
{
var redisConnectionString =
var redisConnectionString =
context.Services.GetConfiguration().GetValue<string>("Redis:Configuration")
+",defaultdatabase="
+ ",defaultdatabase="
+ context.Services.GetConfiguration().GetValue<int>("Redis:DatabaseId", 1);
var redis = ConnectionMultiplexer.Connect(redisConnectionString);
context.Services
@ -278,56 +359,5 @@ namespace CompanyName.ProjectName
});
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
if (!env.IsDevelopment())
{
app.UseErrorPage();
}
app.UseCorrelationId();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName);
app.UseAuthentication();
if (MultiTenancyConsts.IsEnabled)
{
app.UseMultiTenancy();
}
app.UseAuthorization();
app.UseSwagger();
app.UseAbpSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "ProjectName API");
var configuration = context.GetConfiguration();
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
options.OAuthScopes("ProjectName");
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseUnitOfWork();
app.UseConfiguredEndpoints();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
}
}
}

3
aspnet-core/services/src/CompanyName.ProjectName.HttpApi.Host/appsettings.json

@ -4,7 +4,8 @@
},
"ConnectionStrings": {
"Default": "Data Source=localhost;Database=CompanyNameProjectNameDB;uid=root;pwd=mypassword;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true",
"DataDictionaryManagement": "Data Source=localhost;Database=DataDictionaryManagement;uid=root;pwd=mypassword;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true"
"DataDictionaryManagement": "Data Source=localhost;Database=DataDictionaryManagement;uid=root;pwd=mypassword;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true",
"Hangfire": "Data Source=localhost;Database=CompanyNameProjectNameHangfireDB;uid=root;pwd=mypassword;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true"
},
"Redis": {
"Configuration": "localhost,password=mypassword",

Loading…
Cancel
Save