Browse Source

集成Ocelot网关,Consul 服务注册和发现

pull/8/head
王军 4 years ago
parent
commit
d1a547e6cc
  1. 3
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/CompanyName.ProjectName.WebGateway.csproj
  2. 3
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Program.cs
  3. 21
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Properties/launchSettings.json
  4. 35
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Startup.cs
  5. 98
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/WebGatewayModule.cs
  6. 48
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Consul.json
  7. 45
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Development.json
  8. 52
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Production.json
  9. 10
      aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.json
  10. 1
      aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/CompanyName.ProjectName.HttpApi.Host.csproj
  11. 73
      aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/DefaultHttpExceptionStatusCodeFinder.cs
  12. 24
      aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/EnumSchemaFilter.cs
  13. 56
      aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs
  14. 36
      aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/SwaggerTagsFilter.cs
  15. 220
      aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs
  16. 6
      aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json
  17. 2
      aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/CompanyName.ProjectName.Shared.Hosting.Gateways.csproj
  18. 4
      aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/SharedHostingGatewayModule.cs
  19. 1
      aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/Microsoft/AspNetCore/Builder/ApplicationBuilderExtensions.cs
  20. 26
      aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/SharedHostingMicroserviceModule.cs

3
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/CompanyName.ProjectName.WebGateway.csproj

@ -4,8 +4,9 @@
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3"/>
<ProjectReference Include="..\..\shared\CompanyName.ProjectName.Shared.Hosting.Gateways\CompanyName.ProjectName.Shared.Hosting.Gateways.csproj" />
</ItemGroup>
</Project>

3
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Program.cs

@ -18,6 +18,7 @@ namespace CompanyName.ProjectName.WebGateway
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); })
.UseAutofac();
}
}

21
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Properties/launchSettings.json

@ -1,30 +1,13 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:2409",
"sslPort": 44302
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"CompanyName.ProjectName.WebGateway": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"applicationUrl": "http://localhost:44314",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
"ASPNETCORE_ENVIRONMENT": "Consul"
}
}
}

35
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/Startup.cs

@ -16,43 +16,14 @@ namespace CompanyName.ProjectName.WebGateway
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1",
new OpenApiInfo
{ Title = "CompanyName.ProjectName.WebGateway", Version = "v1" });
});
services.AddApplication<WebGatewayModule>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
public void Configure(IApplicationBuilder app)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
"CompanyName.ProjectName.WebGateway v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
app.InitializeApplication();
}
}
}

98
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/WebGatewayModule.cs

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CompanyName.ProjectName.Shared.Hosting.Gateways;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Ocelot.Middleware;
using Swashbuckle.AspNetCore.SwaggerUI;
using Volo.Abp;
using Volo.Abp.Modularity;
namespace CompanyName.ProjectName.WebGateway
{
[DependsOn(
typeof(SharedHostingGatewayModule))]
public class WebGatewayModule : AbpModule
{
private const string DefaultCorsPolicyName = "Default";
public override void ConfigureServices(ServiceConfigurationContext context)
{
ConfigureCors(context);
ConfigureSwaggerServices(context);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
app.UseCorrelationId();
app.UseCors(DefaultCorsPolicyName);
app.UseRouting();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/ProjectName/swagger.json", "ProjectNameAPI");
options.DefaultModelsExpandDepth(-1);
options.DocExpansion(DocExpansion.None);
});
app.UseConfiguredEndpoints();
app.UseOcelot().Wait();
}
/// <summary>
/// 配置跨域
/// </summary>
/// <param name="context"></param>
private void ConfigureCors(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
context.Services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context)
{
context.Services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo {Title = "WebGateway API", Version = "v1"});
options.DocInclusionPredicate((docName, description) => true);
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme, Id = "Bearer"
}
},
new List<string>()
}
});
});
}
}
}

48
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Consul.json

@ -0,0 +1,48 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"App": {
"SelfUrl": "http://localhost:44314",
"CorsOrigins": "http://localhost:4200"
},
"GlobalConfiguration": {
},
"Routes": [
{
"DownstreamPathTemplate": "/swagger/ProjectName/swagger.json",
"DownstreamScheme": "http",
"ServiceName": "Project-Service",
"LoadBalancerOptions": {
"Type": "LeastConnection"
},
"UpstreamPathTemplate": "/ProjectName/swagger.json",
"UpstreamHttpMethod": [
"Get",
"Post",
"Put",
"Delete"
]
},
{
"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",
"ServiceName": "Project-Service",
"LoadBalancerOptions": {
"Type": "LeastConnection"
},
"UpstreamPathTemplate": "/{url}",
"UpstreamHttpMethod": [
"Get",
"Post",
"Put",
"Delete"
]
}
]
}

45
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Development.json

@ -5,5 +5,48 @@
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
},
"AllowedHosts": "*",
"App": {
"SelfUrl": "http://localhost:44314",
"CorsOrigins": "http://localhost:4200"
},
"GlobalConfiguration": {
},
"Routes": [
{
"DownstreamPathTemplate": "/swagger/ProjectName/swagger.json",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44315
}
],
"UpstreamPathTemplate": "/ProjectName/swagger.json",
"UpstreamHttpMethod": [
"Get",
"Post",
"Put",
"Delete"
]
},
{
"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44315
}
],
"UpstreamPathTemplate": "/{url}",
"UpstreamHttpMethod": [
"Get",
"Post",
"Put",
"Delete"
]
}
]
}

52
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.Production.json

@ -0,0 +1,52 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"App": {
"SelfUrl": "http://localhost:44314",
"CorsOrigins": "http://localhost:4200"
},
"GlobalConfiguration": {
},
"Routes": [
{
"DownstreamPathTemplate": "/swagger/ProjectName/swagger.json",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44315
}
],
"UpstreamPathTemplate": "/ProjectName/swagger.json",
"UpstreamHttpMethod": [
"Get",
"Post",
"Put",
"Delete"
]
},
{
"DownstreamPathTemplate": "/{url}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44315
}
],
"UpstreamPathTemplate": "/{url}",
"UpstreamHttpMethod": [
"Get",
"Post",
"Put",
"Delete"
]
}
]
}

10
aspnet-core/gateways/CompanyName.ProjectName.WebGateway/appsettings.json

@ -1,10 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

1
aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/CompanyName.ProjectName.HttpApi.Host.csproj

@ -38,6 +38,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\frameworks\CAP\src\Lion.Abp.Cap\Lion.Abp.Cap.csproj" />
<ProjectReference Include="..\..\..\shared\CompanyName.ProjectName.Shared.Hosting.Microservices\CompanyName.ProjectName.Shared.Hosting.Microservices.csproj" />
<ProjectReference Include="..\..\src\CompanyName.ProjectName.Application\CompanyName.ProjectName.Application.csproj" />
<ProjectReference Include="..\..\src\CompanyName.ProjectName.EntityFrameworkCore\CompanyName.ProjectName.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\src\CompanyName.ProjectName.HttpApi\CompanyName.ProjectName.HttpApi.csproj" />

73
aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/DefaultHttpExceptionStatusCodeFinder.cs

@ -1,73 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using Volo.Abp;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Validation;
namespace CompanyName.ProjectName.Extensions.Filters
{
[Dependency(ReplaceServices = true)]
public class DefaultHttpExceptionStatusCodeFinder : IHttpExceptionStatusCodeFinder, ITransientDependency
{
protected AbpExceptionHttpStatusCodeOptions Options { get; }
public DefaultHttpExceptionStatusCodeFinder(
IOptions<AbpExceptionHttpStatusCodeOptions> options)
{
Options = options.Value;
}
public HttpStatusCode GetStatusCode(HttpContext httpContext, Exception exception)
{
if (exception is IHasHttpStatusCode exceptionWithHttpStatusCode &&
exceptionWithHttpStatusCode.HttpStatusCode > 0)
{
return (HttpStatusCode)exceptionWithHttpStatusCode.HttpStatusCode;
}
if (exception is IHasErrorCode exceptionWithErrorCode &&
!exceptionWithErrorCode.Code.IsNullOrWhiteSpace())
{
if (Options.ErrorCodeToHttpStatusCodeMappings.TryGetValue(exceptionWithErrorCode.Code, out var status))
{
return status;
}
}
if (exception is AbpAuthorizationException)
{
return HttpStatusCode.Forbidden;
}
//TODO: Handle SecurityException..?
if (exception is AbpValidationException)
{
return HttpStatusCode.BadRequest;
}
if (exception is EntityNotFoundException)
{
return HttpStatusCode.NotFound;
}
if (exception is NotImplementedException)
{
return HttpStatusCode.NotImplemented;
}
if (exception is IBusinessException)
{
return HttpStatusCode.InternalServerError;
}
return HttpStatusCode.InternalServerError;
}
}
}

24
aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/EnumSchemaFilter.cs

@ -1,24 +0,0 @@
using System;
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace CompanyName.ProjectName.Extensions.Filters
{
public class EnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
var array = new OpenApiArray();
array.AddRange(Enum.GetNames(context.Type).Select(n => new OpenApiString(n)));
// NSwag
schema.Extensions.Add("x-enumNames", array);
// Openapi-generator
schema.Extensions.Add("x-enum-varnames", array);
}
}
}
}

56
aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs

@ -1,56 +0,0 @@
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace CompanyName.ProjectName.Extensions.Filters
{
/// <summary>
/// 在使用nswag的时候,原生默认的api导致生产的代理类存在问题
/// 所有隐藏原生的api,重写路由
/// </summary>
public class HiddenAbpDefaultApiFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
foreach (ApiDescription apiDescription in context.ApiDescriptions)
{
if (apiDescription.TryGetMethodInfo(out MethodInfo method))
{
string key = "/" + apiDescription.RelativePath;
var reuslt = IsHidden(key);
if(reuslt) swaggerDoc.Paths.Remove(key);
}
}
}
private bool IsHidden(string key)
{
var list = GetHiddenAbpDefaultApiList();
foreach (var item in list)
{
if (key.Contains(item)) return true;
}
return false;
}
private List<string> GetHiddenAbpDefaultApiList()
{
return new List<string>() {
"/api/abp/multi-tenancy/tenants",
"/api/account",
"/api/feature-management/features",
"/api/permission-management/permissions",
"/api/identity/my-profile",
"/api/identity",
"/api/multi-tenancy/tenants",
"/api/setting-management/emailing"
};
}
}
}

36
aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/SwaggerTagsFilter.cs

@ -1,36 +0,0 @@
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CompanyNameProjectName.Extensions.Filters
{
/// <summary>
/// 把abp vnext 提供的api 归档
/// </summary>
public class SwaggerTagsFilter : IOperationFilter
{
public const string DefaultTagName = "ABP Vnext 默认 Api";
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var tag = GetChineseTag(context.ApiDescription.ActionDescriptor as ControllerActionDescriptor);
if (null != tag)
operation.Tags = new List<OpenApiTag> { tag };
}
private static OpenApiTag GetChineseTag(ControllerActionDescriptor description)
{
if (null != description?.ControllerTypeInfo?.Namespace)
{
if (description.ControllerTypeInfo.Namespace.StartsWith("Volo.Abp") || description.ControllerTypeInfo.Namespace.StartsWith("Pages.Abp.MultiTenancy"))
return new OpenApiTag { Name = DefaultTagName };
return null;
}
return null;
}
}
}

220
aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs

@ -1,18 +1,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using CompanyName.ProjectName.ConfigurationOptions;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using CompanyName.ProjectName.EntityFrameworkCore;
using CompanyName.ProjectName.Extensions.Filters;
using CompanyNameProjectName.Extensions.Filters;
using Hangfire;
using Hangfire.MySql;
@ -29,18 +26,17 @@ using Volo.Abp.Autofac;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.BackgroundJobs.Hangfire;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.VirtualFileSystem;
using System.Threading.Tasks;
using CompanyName.ProjectName.Extensions;
using CompanyName.ProjectName.MultiTenancy;
using DefaultNamespace;
using DefaultNamespace.Swaggers;
using Lion.Abp.Cap;
using Savorboard.CAP.InMemoryMessageQueue;
using Serilog;
using Swashbuckle.AspNetCore.SwaggerUI;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.Caching;
@ -59,13 +55,15 @@ namespace CompanyName.ProjectName
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpBackgroundJobsHangfireModule),
typeof(LionAbpCapModule),
typeof(AbpAspNetCoreMultiTenancyModule)
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(SharedHostingMicroserviceModule)
)]
public class ProjectNameHttpApiHostModule : AbpModule
{
private const string DefaultCorsPolicyName = "Default";
public override void OnPostApplicationInitialization(ApplicationInitializationContext context)
public override void OnPostApplicationInitialization(
ApplicationInitializationContext context)
{
// context.CreateRecurringJob();
base.OnPostApplicationInitialization(context);
@ -74,77 +72,73 @@ namespace CompanyName.ProjectName
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var hostingEnvironment = context.Services.GetHostingEnvironment();
//ConfigureConventionalControllers();
//ConfigureAuthentication(context, configuration);
ConfigureLocalization();
ConfigureCache(context);
ConfigureVirtualFileSystem(context);
ConfigureCors(context, configuration);
ConfigureSwaggerServices(context, configuration);
ConfigureOptions(context);
ConfigureHealthChecks(context);
ConfigureJwtAuthentication(context, configuration);
ConfigureHangfireMysql(context);
ConfigurationCap(context);
ConfigurationStsHttpClient(context);
ConfigureAbpExceptions(context);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var configuration = context.GetConfiguration();
app.UseAbpRequestLocalization();
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");
options.SwaggerEndpoint("/swagger/ProjectName/swagger.json", "ProjectName API");
options.DocExpansion(DocExpansion.None);
options.DefaultModelsExpandDepth(-1);
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseSerilogRequestLogging(opts => { opts.EnrichDiagnosticContext = SerilogToEsExtensions.EnrichFromRequest; });
app.UseSerilogRequestLogging(opts =>
{
opts.EnrichDiagnosticContext = SerilogToEsExtensions.EnrichFromRequest;
});
app.UseUnitOfWork();
app.UseConfiguredEndpoints();
app.UseEndpoints(endpoints => { endpoints.MapHealthChecks("/health"); });
app.UseHangfireDashboard("/hangfire", new DashboardOptions()
{
Authorization = new[] {new CustomHangfireAuthorizeFilter()},
Authorization = new[] { new CustomHangfireAuthorizeFilter() },
IgnoreAntiforgeryToken = true
});
}
/// <summary>
/// 异常处理
/// </summary>
/// <param name="context"></param>
private void ConfigureAbpExceptions(ServiceConfigurationContext context)
{
context.Services.Configure<AbpExceptionHandlingOptions>(options => { options.SendExceptionsDetailsToClients = true; });
if (configuration.GetValue<bool>("Consul:Enabled", false))
{
app.UseConsul();
}
}
public void ConfigureHangfireMysql(ServiceConfigurationContext context)
private void ConfigureHangfireMysql(ServiceConfigurationContext context)
{
Configure<AbpBackgroundJobOptions>(options => { options.IsJobExecutionEnabled = true; });
Configure<AbpBackgroundJobOptions>(options =>
{
options.IsJobExecutionEnabled = true;
});
context.Services.AddHangfire(config =>
{
config.UseStorage(new MySqlStorage(context.Services.GetConfiguration().GetConnectionString("Default"),
config.UseStorage(new MySqlStorage(
context.Services.GetConfiguration().GetConnectionString("Default"),
new MySqlStorageOptions()
{
//CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
@ -162,7 +156,8 @@ namespace CompanyName.ProjectName
/// </summary>
/// <param name="context"></param>
/// <param name="configuration"></param>
private void ConfigureJwtAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
private void ConfigureJwtAuthentication(ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddAuthentication(options =>
{
@ -171,19 +166,21 @@ namespace CompanyName.ProjectName
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
// 是否开启签名认证
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
//ClockSkew = TimeSpan.Zero,
ValidIssuer = configuration["Jwt:Issuer"],
ValidAudience = configuration["Jwt:Audience"],
IssuerSigningKey =
new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"]))
};
options.TokenValidationParameters =
new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
// 是否开启签名认证
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
//ClockSkew = TimeSpan.Zero,
ValidIssuer = configuration["Jwt:Issuer"],
ValidAudience = configuration["Jwt:Audience"],
IssuerSigningKey =
new SymmetricSecurityKey(
Encoding.ASCII.GetBytes(configuration["Jwt:SecurityKey"]))
};
options.Events = new JwtBearerEvents
{
@ -198,9 +195,11 @@ namespace CompanyName.ProjectName
}
// 如果请求来自hangfire 或者cap
if (path.ToString().StartsWith("/hangfire") || path.ToString().StartsWith("/cap"))
if (path.ToString().StartsWith("/hangfire") ||
path.ToString().StartsWith("/cap"))
{
currentContext.HttpContext.Response.Headers.Remove("X-Frame-Options");
currentContext.HttpContext.Response.Headers.Remove(
"X-Frame-Options");
if (!string.IsNullOrEmpty(accessToken))
{
currentContext.Token = accessToken;
@ -229,7 +228,8 @@ namespace CompanyName.ProjectName
/// <param name="context"></param>
private void ConfigureOptions(ServiceConfigurationContext context)
{
context.Services.Configure<JwtOptions>(context.Services.GetConfiguration().GetSection("Jwt"));
context.Services.Configure<JwtOptions>(context.Services.GetConfiguration()
.GetSection("Jwt"));
}
/// <summary>
@ -237,7 +237,8 @@ namespace CompanyName.ProjectName
/// </summary>
private void ConfigureCache(ServiceConfigurationContext context)
{
Configure<AbpDistributedCacheOptions>(options => { options.KeyPrefix = "ProjectName:"; });
Configure<AbpDistributedCacheOptions>(
options => { options.KeyPrefix = "ProjectName:"; });
var configuration = context.Services.GetConfiguration();
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
context.Services
@ -245,31 +246,6 @@ namespace CompanyName.ProjectName
.PersistKeysToStackExchangeRedis(redis, "ProjectName-Protection-Keys");
}
private void ConfigureVirtualFileSystem(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options => { options.FileSets.AddEmbedded<ProjectNameHttpApiHostModule>(); });
// var hostingEnvironment = context.Services.GetHostingEnvironment();
//
// if (hostingEnvironment.IsDevelopment())
// {
// Configure<AbpVirtualFileSystemOptions>(options =>
// {
// options.FileSets.ReplaceEmbeddedByPhysical<ProjectNameDomainSharedModule>(
// Path.Combine(hostingEnvironment.ContentRootPath,
// $"..{Path.DirectorySeparatorChar}CompanyName.ProjectName.Domain.Shared"));
// options.FileSets.ReplaceEmbeddedByPhysical<ProjectNameDomainModule>(
// Path.Combine(hostingEnvironment.ContentRootPath,
// $"..{Path.DirectorySeparatorChar}CompanyName.ProjectName.Domain"));
// options.FileSets.ReplaceEmbeddedByPhysical<ProjectNameApplicationContractsModule>(
// Path.Combine(hostingEnvironment.ContentRootPath,
// $"..{Path.DirectorySeparatorChar}CompanyName.ProjectName.Application.Contracts"));
// options.FileSets.ReplaceEmbeddedByPhysical<ProjectNameApplicationModule>(
// Path.Combine(hostingEnvironment.ContentRootPath,
// $"..{Path.DirectorySeparatorChar}CompanyName.ProjectName.Application"));
// });
// }
}
private void ConfigurationStsHttpClient(ServiceConfigurationContext context)
{
@ -277,7 +253,8 @@ namespace CompanyName.ProjectName
options =>
{
options.BaseAddress =
new Uri(context.Services.GetConfiguration().GetSection("HttpClient:Sts:Url").Value);
new Uri(context.Services.GetConfiguration().GetSection("HttpClient:Sts:Url")
.Value);
});
}
@ -285,31 +262,19 @@ namespace CompanyName.ProjectName
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(ProjectNameApplicationModule).Assembly);
options.ConventionalControllers.Create(typeof(ProjectNameApplicationModule)
.Assembly);
});
}
/// <summary>
/// 健康检查
/// </summary>
/// <param name="context"></param>
private void ConfigureHealthChecks(ServiceConfigurationContext context)
{
var redisConnectionString =
context.Services.GetConfiguration().GetValue<string>("Cache:Redis:ConnectionString");
var redisDatabaseId = context.Services.GetConfiguration().GetValue<int>("Cache:Redis:DatabaseId");
var password = context.Services.GetConfiguration().GetValue<string>("Cache:Redis:Password");
var connectString = $"{redisConnectionString},password={password},defaultdatabase={redisDatabaseId}";
context.Services.AddHealthChecks().AddRedis(redisConnectionString).AddMySql(connectString);
}
private static void ConfigureSwaggerServices(ServiceConfigurationContext context, IConfiguration configuration)
private static void ConfigureSwaggerServices(ServiceConfigurationContext context,
IConfiguration configuration)
{
context.Services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo {Title = "CompanyNameProjectName API", Version = "v1"});
options.SwaggerDoc("ProjectName",
new OpenApiInfo { Title = "CompanyNameProjectName API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.EnableAnnotations(); // 启用注解
options.DocumentFilter<HiddenAbpDefaultApiFilter>();
@ -321,15 +286,17 @@ namespace CompanyName.ProjectName
options.IncludeXmlComments(xml, true);
}
options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme()
{
Description = "Please enter into field the word 'Bearer' followed by a space and the JWT value",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme,
BearerFormat = "JWT"
});
options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme,
new OpenApiSecurityScheme()
{
Description =
"Please enter into field the word 'Bearer' followed by a space and the JWT value",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme,
BearerFormat = "JWT"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
@ -357,7 +324,8 @@ namespace CompanyName.ProjectName
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme, Id = "ApiKey"}
Reference = new OpenApiReference
{ Type = ReferenceType.SecurityScheme, Id = "ApiKey" }
},
new string[] { }
}
@ -365,48 +333,6 @@ namespace CompanyName.ProjectName
});
}
private void ConfigureLocalization()
{
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("ar", "ar", "العربية"));
options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
options.Languages.Add(new LanguageInfo("es", "es", "Español", "es"));
});
}
private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAntiforgery(o => o.SuppressXFrameOptionsHeader = true);
context.Services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
}
private void ConfigurationCap(ServiceConfigurationContext context)
{

6
aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/appsettings.Development.json

@ -12,6 +12,7 @@
}
},
"App": {
"SelfUrl": "http://localhost:44315",
"CorsOrigins": "https://*.ProjectName.com,http://localhost:4200,http://localhost:3100"
},
"ConnectionStrings": {
@ -51,5 +52,10 @@
"Sts": {
"Url": "http://localhost:44354"
}
},
"Consul": {
"Enabled": true,
"Host": "http://localhost:8500",
"Service": "Project-Service"
}
}

2
aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/CompanyName.ProjectName.Shared.Hosting.Gateways.csproj

@ -5,6 +5,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ocelot" Version="17.0.0" />
<PackageReference Include="Ocelot.Provider.Consul" Version="17.0.0" />
<PackageReference Include="Ocelot.Provider.Polly" Version="17.0.0" />
<PackageReference Include="Volo.Abp" Version="$(AbpPackageVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore" Version="$(AbpPackageVersion)" />
<PackageReference Include="Volo.Abp.Autofac" Version="$(AbpPackageVersion)" />

4
aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Gateways/SharedHostingGatewayModule.cs

@ -1,5 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Provider.Consul;
using Ocelot.Provider.Polly;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
@ -23,7 +25,7 @@ namespace CompanyName.ProjectName.Shared.Hosting.Gateways
private static void ConfigureOcelot(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
context.Services.AddOcelot(configuration);
context.Services.AddOcelot(configuration).AddConsul().AddPolly();
}
}

1
aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/Microsoft/AspNetCore/Builder/ApplicationBuilderExtensions.cs

@ -36,7 +36,6 @@ namespace Microsoft.AspNetCore.Builder
Port = appUrl.Port,
Check = new AgentServiceCheck
{
Status = HealthStatus.Passing,
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务停止多久后注销
Interval = TimeSpan.FromSeconds(3),//健康检查时间间隔,或者称为心跳 间隔
HTTP = $"http://{appUrl.Host}:{appUrl.Port}/health",//健康检查地址

26
aspnet-core/shared/CompanyName.ProjectName.Shared.Hosting.Microservices/SharedHostingMicroserviceModule.cs

@ -3,6 +3,7 @@ using System.Linq;
using Microsoft.AspNetCore.Cors;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.Autofac;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
@ -26,7 +27,29 @@ namespace DefaultNamespace
ConfigureLocalization();
ConfigureCors(context);
ConfigureUrls(configuration);
ConfigureAbpExceptions(context);
ConfigureConsul(context, configuration);
}
private void ConfigureConsul(ServiceConfigurationContext context,
IConfiguration configuration)
{
if (configuration.GetValue<bool>("Consul:Enabled", false))
{
context.Services.AddConsulConfig(configuration);
}
}
/// <summary>
/// 异常处理
/// </summary>
/// <param name="context"></param>
private void ConfigureAbpExceptions(ServiceConfigurationContext context)
{
context.Services.Configure<AbpExceptionHandlingOptions>(options =>
{
options.SendExceptionsDetailsToClients = true;
});
}
/// <summary>
@ -98,6 +121,7 @@ namespace DefaultNamespace
private void ConfigureHealthChecks(ServiceConfigurationContext context)
{
// TODO 检查数据库和redis是否正常 AspNetCore.HealthChecks.Redis AspNetCore.HealthChecks.MySql
// context.Services.AddHealthChecks().AddRedis(redisConnectionString).AddMySql(connectString);
context.Services.AddHealthChecks();
}
}

Loading…
Cancel
Save