我最近将.NET Core Web API从2.1升级到了2.2。 Microsoft声称新的InProcess托管模型应比OutOfProcess托管模型up to 4x faster多。
但是,当我在.csproj中将IIS托管模型设置为InProcess <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
时,平均API响应比我设置<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
时高50-100ms。
知道为什么它会减慢API响应时间(提高ping)吗?
我的Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
IoCContainer.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)
{
//Add proper cookie request to follow GDPR
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
//Add SendGrid email sender
services.AddSendGridEmailSender();
//Add general email template sender
services.AddEmailTemplateSender();
//Add ExcelFileDownloadService
services.AddTransient<IExcelFileDownloadService, ExcelFileDownloadService>();
//Add ExcelFileUploadService
services.AddTransient<IExcelFileUploadService, ExcelFileUploadService>();
//Add FileUploadService
services.AddTransient<IUploadFileService, UploadFileService>();
//CORS
services.AddCors();
//Add ApplicationDbContext to DI using MSSQL
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(IoCContainer.Configuration.GetConnectionString("AspifyConnection")));
//Store keys to File System
string path = Directory.GetCurrentDirectory() + @"\keys\";
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(path));
//Add RepositoryWrapper to DI
services.AddScoped<IRepositoryWrapper, RepositoryWrapper>();
//Adds cookie based authentication
//Adds classes like UserManager, SignInManager, PasswordHashers etc.
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddUserManager<UserManager<ApplicationUser>>()
//Adds UserStore and RoleStore from this context
.AddEntityFrameworkStores<ApplicationDbContext>()
//Adds a provider that generates unique keys and hashes
.AddDefaultTokenProviders();
//Add JWT authentication for API clients
var key = Encoding.ASCII.GetBytes(IoCContainer.Configuration["JwtSecretKey"]);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdministratorRole", policy => policy.RequireRole("Administrator"));
});
//Change Identity Framework password policy
services.Configure<IdentityOptions>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequiredLength = 5;
options.Password.RequireLowercase = true;
options.Password.RequireUppercase = false;
options.Password.RequireNonAlphanumeric = false;
});
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
services.AddMvc(options =>
{
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
//Setup identity
app.UseAuthentication();
UpdateDatabase(app);
//Allow all CORS
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseDeveloperExceptionPage();
//Force non-essential cookies to only store if the user has consented
app.UseCookiePolicy();
//Enable static files in wwwroot folder
app.UseStaticFiles();
//set HTTP routes
app.UseMvc(routes =>
{
//Api route
routes.MapRoute(
name: "api",
template: "api/{controller}/{action}/{moreInfo?}");
//Default route to React
routes.MapRoute(
name: "default",
template: "{*path}",
defaults: new { controller = "Home", action = "Index" });
});
}
private static void UpdateDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices
.GetRequiredService<IServiceScopeFactory>()
.CreateScope())
{
using (var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>())
{
context.Database.EnsureCreated();
}
}
}
}
.csproj:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<RuntimeFrameworkVersion>2.2.0</RuntimeFrameworkVersion>
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Migrations\20181110121254_rentalInfoLeasingTypeSetNull.cs" />
<Compile Remove="Migrations\20181110121254_rentalInfoLeasingTypeSetNull.Designer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="EPPlus.Core" Version="1.5.4" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="2.2.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" />
<PackageReference Include="Sendgrid" Version="9.10.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\Examples\" />
<Folder Include="wwwroot\Uploads\" />
<Folder Include="wwwroot\EmailTemplates\" />
<Folder Include="wwwroot\React" />
<Folder Include="wwwroot\React\media" />
</ItemGroup>
<ItemGroup>
<None Include="Views\Home\Index.cshtml" />
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JSONSchema="" /></VisualStudio></ProjectExtensions>
</Project>
CompaniesController.cs:
/// <summary>
/// Get list of all companies without their domains
/// </summary>
/// <returns>List of companies</returns>
[Authorize(Roles = "Admin")]
[HttpGet]
public async Task<IActionResult> Get()
{
List<Company> companies = await _repoWrapper.Companies.GetAllAsync();
List<CompanyListItemResponse> response = new List<CompanyListItemResponse>();
foreach (Company company in companies)
{
response.Add(new CompanyListItemResponse { Id = company.Id, Name = company.Name });
}
response = response.OrderBy(x => x.Name).ToList();
return Ok(response);
}