Commit c21b1c42 by lcx

Merge branch 'feature/限流' into develop

parents 103b61d0 40791839
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Performance.DtoModels.AppSettings;
using Performance.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Performance.Api.Configurations
{
public static class AppSettingConfig
{
public static void AddAppSettingConfiguration(this IServiceCollection services, IConfiguration configuration)
{
if (services == null) throw new ArgumentNullException(nameof(services));
services
.Configure<AppConnection>(configuration.GetSection("AppConnection"))
.Configure<Application>(configuration.GetSection("Application"))
.Configure<HuyiSmsConfig>(configuration.GetSection("HuyiSmsConfig"))
.Configure<EmailOptions>(configuration.GetSection("EmailOptions"))
.Configure<WebapiUrl>(configuration.GetSection("WebapiUrl"));
}
}
}
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;
using Performance.DtoModels.AutoMapper;
using System;
namespace Performance.Api.Configurations
{
public static class AutoMapperConfig
{
public static void AddAutoMapperConfiguration(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
Mapper.Initialize(cfg => cfg.AddProfile<AutoMapperConfigs>());
services.AddAutoMapper();
}
}
}
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using System;
namespace Performance.Api.Configurations
{
public static class DatabaseConfig
{
public static void AddDatabaseConfiguration(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
var connection = services.BuildServiceProvider().GetService<IOptions<AppConnection>>();
services.AddDbContext<PerformanceDbContext>(options =>
{
options.UseMySQL(connection.Value.PerformanceConnectionString);
});
}
}
}
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Performance.Infrastructure;
using Performance.Services;
using Performance.Services.Queues;
using System;
namespace Performance.Api.Configurations
{
public static class DependencyInjectionConfig
{
public static void AddDependencyInjectionConfiguration(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
#region custom util
//huyi短信发送注入
services.AddScoped<HuyiSmsNotify>();
//用户身份信息服务
services.AddScoped<ClaimService>();
#endregion custom util
#region email
//阿里邮箱配置
var emailOption = services.BuildServiceProvider().GetService<IOptions<EmailOptions>>();
//邮件发送
services.AddEmailUtil(options =>
{
options.Account = emailOption.Value.Account;
options.Password = emailOption.Value.Password;
options.SmtpServer = emailOption.Value.SmtpServer;
});
#endregion email
#region redis
//var csredis = new CSRedis.CSRedisClient(connection.Value.RedisConnectionString);
//RedisHelper.Initialization(csredis);
#endregion redis
services.AddHostedService<QueuedHostedService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
services.AddSingleton<IHubNotificationQueue, HubNotificationQueue>();
services
.AddPerformanceService()
.AddPerformanceRepoitory();
}
}
#region hangfire 权限
public class HangfireAuthorizationFilter : Hangfire.Dashboard.IDashboardAuthorizationFilter
{
//这里需要配置权限规则
public bool Authorize(Hangfire.Dashboard.DashboardContext context)
{
return true;
}
}
#endregion hangfire 权限
}
using AspNetCoreRateLimit;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace Performance.Api.Configurations
{
public static class RateLimitConfig
{
public static void AddRateLimitConfiguration(this IServiceCollection services, IConfiguration configuration)
{
if (services == null) throw new ArgumentNullException(nameof(services));
//加载配置
services.AddOptions();
//从appsettings.json获取相应配置
services.Configure<IpRateLimitOptions>(configuration.GetSection("IpRateLimiting"));
//注入计数器和规则存储
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//配置(计数器密钥生成器)
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
}
public static void UseRateLimitSetup(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
app.UseIpRateLimiting();
}
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Swagger;
using System;
using System.Collections.Generic;
using System.IO;
namespace Performance.Api.Configurations
{
public static class SwaggerConfig
{
public static void AddSwaggerConfiguration(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Version = "v1.0", Title = "绩效API接口" });
//var xmlPath = new string[]
//{
// Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "Performance.Api.xml"),
// Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "Performance.DtoModels.xml"),
// Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "Performance.EntityModels.xml"),
//};
//foreach (var item in xmlPath)
//{
// c.IncludeXmlComments(item, true);
//}
var xmlPathsss = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "Performance.Api.xml");
c.IncludeXmlComments(xmlPathsss, true);
// Token绑定到ConfigureServices
var security = new Dictionary<string, IEnumerable<string>> { { "Performance API", new string[] { } }, };
c.AddSecurityRequirement(security);
c.AddSecurityDefinition("Performance API", new ApiKeyScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)",
Name = "Authorization",
In = "HEADER"
});
});
}
public static void UseSwaggerSetup(this IApplicationBuilder app, IConfiguration configuration)
{
if (app == null) throw new ArgumentNullException(nameof(app));
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint(configuration["Application:SwaggerEndpoint"], "v1.0");
c.RoutePrefix = string.Empty;
});
}
}
}
using GraphQL;
using GraphQL.Types;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Performance.Api
{
......
......@@ -36,6 +36,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AspNetCoreRateLimit" Version="3.0.3" />
<PackageReference Include="AutoMapper" Version="8.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="6.0.0" />
<PackageReference Include="CSRedisCore" Version="3.0.45" />
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLog.Web;
using System;
namespace Performance.Api
{
......@@ -23,6 +19,7 @@ public static void Main(string[] args)
catch (Exception ex)
{
logger.Error(ex, "Stopped program because of exception");
throw;
}
finally
{
......@@ -37,15 +34,16 @@ public static void Main(string[] args)
var env = context.HostingEnvironment;
config.AddJsonFile("appsettings.json", true, true);
config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true);
config.AddJsonFile($"RateLimitConfig.json", true, true);
})
.UseUrls("http://*:5001")
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog()
.UseStartup<Startup>();
.UseNLog();
}
}
{
"IpRateLimiting": {
//false则全局将应用限制,并且仅应用具有作为端点的规则* true则限制将应用于每个端点,如{HTTP_Verb}{PATH}
"EnableEndpointRateLimiting": true,
//false则拒绝的API调用不会添加到调用次数计数器上
"StackBlockedRequests": false,
//注意这个配置,表示获取用户端的真实IP,我们的线上经过负载后是 X-Forwarded-For,而测试服务器没有,所以是X-Real-IP
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"HttpStatusCode": 200,
"QuotaExceededResponse": {
"Content": "{{\"state\":429,\"message\":\"访问过于频繁,请稍后重试\",\"data\":null}}",
"ContentType": "application/json",
"StatusCode": 200
},
//IP白名单,本地调试或者UAT环境,可以加入相应的IP,略过策略的限制
"IpWhitelist": [],
//端点白名单,如果全局配置了访问策略,设置端点白名单相当于IP白名单一样,略过策略的限制
"EndpointWhitelist": [],
"ClientWhitelist": [],
"GeneralRules": [
{
"Endpoint": "*",
"Period": "1s",
"Limit": 1
}
]
}
}
using AutoMapper;
using FluentValidation;
using FluentValidation;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog.Extensions.Logging;
using Performance.DtoModels.AppSettings;
using Performance.DtoModels.AutoMapper;
using Performance.EntityModels;
using Performance.Api.Configurations;
using Performance.Infrastructure;
using Performance.Services;
using Performance.Services.Queues;
using Swashbuckle.AspNetCore.Swagger;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
......@@ -38,51 +26,35 @@ public Startup(IConfiguration configuration)
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//LogHelper.Initialize(Configuration.GetSection("AppConnection:RedisConnectionString").Value, "MTEzMTAyMzEzNDYzMzY5MzE4NA");
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
#region appsetting注入
// appsettings.json
services.AddAppSettingConfiguration(Configuration);
services
.Configure<AppConnection>(Configuration.GetSection("AppConnection"))
.Configure<Application>(Configuration.GetSection("Application"))
.Configure<HuyiSmsConfig>(Configuration.GetSection("HuyiSmsConfig"))
.Configure<EmailOptions>(Configuration.GetSection("EmailOptions"))
.Configure<WebapiUrl>(Configuration.GetSection("WebapiUrl"));
#endregion appsetting注入
// memory cache
services.AddMemoryCache();
var connection = services.BuildServiceProvider().GetService<IOptions<AppConnection>>();
// ratelimit
services.AddRateLimitConfiguration(Configuration);
// graphql
services.AddGraphQLSchemaAndTypes();
#region json & fluentvalidation & filter
services
//筛选器配置
.AddMvc(option =>
{
//筛选器配置
option.Filters.Add<AuthenticationFilter>();
option.Filters.Add<ActionsFilter>();
option.Filters.Add<ExceptionsFilter>();
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
//json格式配置
.AddJsonOptions(json =>
{
json.SerializerSettings.Converters.Add(new IsoDateTimeConverterContent() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
json.SerializerSettings.ContractResolver = new LowercaseContractResolver();
json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Include;
json.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
json.SerializerSettings.Culture = new CultureInfo("zh-CN");
json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
})
//model验证
.AddJsonOptions(JsonOptions) //json格式配置
.AddFluentValidation(fv =>
{
//禁用其他以使FluentValidation是唯一执行的验证库
// model验证,禁用其他以使FluentValidation是唯一执行的验证库
fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
var assembly = Assembly.Load("Performance.DtoModels");
......@@ -95,68 +67,22 @@ public void ConfigureServices(IServiceCollection services)
#endregion json & fluentvalidation & filter
#region automapper
Mapper.Initialize(cfg => cfg.AddProfile<AutoMapperConfigs>());
services.AddAutoMapper();
#endregion automapper
#region service注入 repoitory注入
services
.AddPerformanceService()
.AddPerformanceRepoitory();
#endregion service注入 repoitory注入
#region custom util
//huyi短信发送注入
services.AddScoped<HuyiSmsNotify>();
//用户身份信息服务
services.AddScoped<ClaimService>();
#endregion custom util
#region email
// dbcontext
services.AddDatabaseConfiguration();
//阿里邮箱配置
var emailOption = services.BuildServiceProvider().GetService<IOptions<EmailOptions>>();
//邮件发送
services.AddEmailUtil(options =>
{
options.Account = emailOption.Value.Account;
options.Password = emailOption.Value.Password;
options.SmtpServer = emailOption.Value.SmtpServer;
});
#endregion email
#region redis
//var csredis = new CSRedis.CSRedisClient(connection.Value.RedisConnectionString);
//RedisHelper.Initialization(csredis);
#endregion redis
services.AddMemoryCache();
// automapper
services.AddAutoMapperConfiguration();
services.AddHostedService<QueuedHostedService>();
services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
services.AddSingleton<IHubNotificationQueue, HubNotificationQueue>();
// swagger
services.AddSwaggerConfiguration();
//#region hangfire
//services.AddHangfire(config =>
//{
// config.UseFilter(new AutomaticRetryAttribute { Attempts = 0 });
// config.UseStorage(new MySqlStorage(connection.Value.HangfireConnectionString));
//});
//#endregion hangfire
// service repository
services.AddDependencyInjectionConfiguration();
// signalr
services.AddSignalR();
// cors
services.AddCors(options =>
{
options.AddPolicy("SignalrCore", policy =>
......@@ -164,54 +90,6 @@ public void ConfigureServices(IServiceCollection services)
policy.SetIsOriginAllowed(origin => true).AllowAnyHeader().AllowAnyMethod().AllowCredentials();
});
});
#region //ef配置
services.AddDbContext<PerformanceDbContext>(options =>
{
options.UseMySQL(connection.Value.PerformanceConnectionString);
});
#endregion //ef配置
#region swagger
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Version = "v1.0", Title = "绩效API接口" });
var xmlPath = new string[]
{
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "Performance.Api.xml"),
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "Performance.DtoModels.xml"),
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "Performance.EntityModels.xml"),
};
var xmlPathsss = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot", "Performance.Api.xml");
c.IncludeXmlComments(xmlPathsss, true);
//foreach (var item in xmlPath)
//{
// c.IncludeXmlComments(item, true);
//}
#region Token绑定到ConfigureServices
var security = new Dictionary<string, IEnumerable<string>> { { "Performance API", new string[] { } }, };
c.AddSecurityRequirement(security);
c.AddSecurityDefinition("Performance API", new ApiKeyScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)",
Name = "Authorization",
In = "HEADER"
});
#endregion Token绑定到ConfigureServices
});
#endregion swagger
ServiceLocator.Instance = services.BuildServiceProvider();
FluentScheduler.JobManager.Initialize(new JobRegistry());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
......@@ -226,41 +104,27 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env)
app.UseStatusCodePagesWithReExecute("/error/{0}");
}
#region Swagger
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint(Configuration["Application:SwaggerEndpoint"], "v1.0");
//c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1.0");
c.RoutePrefix = "";
});
#endregion Swagger
//#region hangfire
app.UseCors("SignalrCore");
//app.UseHangfireServer();
//app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new[] { new HangfireAuthorizationFilter() } });
app.UseSignalR(routes => routes.MapHub<AllotLogHub>("/performance/allotLogHub"));
//#endregion hangfire
app.UseRateLimitSetup();
app.UseCors("SignalrCore");
app.UseSignalR(routes => routes.MapHub<AllotLogHub>("/performance/allotLogHub"));
app.UseMvc();
}
}
#region hangfire 权限
app.UseSwaggerSetup(Configuration);
}
public class HangfireAuthorizationFilter : Hangfire.Dashboard.IDashboardAuthorizationFilter
{
//这里需要配置权限规则
public bool Authorize(Hangfire.Dashboard.DashboardContext context)
private void JsonOptions(MvcJsonOptions json)
{
return true;
json.SerializerSettings.Converters.Add(new IsoDateTimeConverterContent() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
json.SerializerSettings.ContractResolver = new LowercaseContractResolver();
json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Include;
json.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
json.SerializerSettings.Culture = new CultureInfo("zh-CN");
json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
}
}
#endregion hangfire 权限
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment