在 CORS 预检时阻止 ASP 核心并发请求



我有一个脚本,可以向包含JSON的端点发出多个POST。目前,脚本可能会同时从本地主机制作 100+ 个 POST。在请求所有 POST 之前,不会调用该路由的方法;在此之前,仅发送 HTTP 选项(CORS 预检(作为响应。一旦脚本停止发出 POST 请求,服务器才会开始调用路由方法。

当然,让脚本同时发出 100+ POST 请求会发生变化,但我担心这将如何影响许多用户的生产使用。

在我的调试中,我发现在该批次中的所有 POST 请求都发出之前,我的过滤器/代码都不会运行。

我不知道如何解决这个问题。CPU 和内存甚至还没有接近达到其极限,更改筛选器顺序没有任何影响,优化路由方法也没有效果,因为在发出所有请求之前不会调用它。

我正在IIS Express 10上使用Visual Studio的开发机器上对此进行测试。我正在使用 ASP.NET Core 2.0。

应用配置:

public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddJsonOptions(opt =>
{
opt.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
})
.AddMvcOptions(opt =>
{
opt.Filters.Add(new IPLoggingInterceptionAttribute());
});
services.AddCors(options =>
{
options.AddPolicy("AllOrigins", builder =>
{
builder.AllowAnyHeader();
builder.AllowAnyMethod();
builder.AllowAnyOrigin();
});
});
services
.AddScoped<RequireAuthAttribute>();
String connectionString = Configuration.GetConnectionString("Vault");
services.AddDbContext<VaultContext>(options => options.UseNpgsql(connectionString));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("AllOrigins");
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.All,
RequireHeaderSymmetry = false
});
app.UseMvc();
}

路由响应方法(如果相关(:

[HttpPost("{villageId}/army/current")]
public async Task<IActionResult> PostCurrentArmy(long villageId, [FromBody]JSON.ArmySet currentArmySetJson)
{
if (!ModelState.IsValid)
return ValidationProblem(ModelState);
//  [Note that 'CurrentWorldId' is a blocking property on first read]
//  Get or make CurrentVillage
Scaffold.CurrentVillage currentVillage =
await context.CurrentVillage
.FromWorld(CurrentWorldId)
.Where(v => v.VillageId == villageId)
.FirstOrDefaultAsync();
currentVillage = currentVillage ?? (await context.AddAsync(new Scaffold.CurrentVillage())).Entity;
currentVillage.WorldId = CurrentWorldId;
if (currentVillage.PlayerId == null)
{
var modelVillage = await (
from village in context.Village.FromWorld(CurrentWorldId)
where village.VillageId == villageId
select village
).FirstOrDefaultAsync();
if (modelVillage != null)
{
currentVillage.VillageId = modelVillage.VillageId;
currentVillage.PlayerId = modelVillage.PlayerId;
currentVillage.Points = modelVillage.Points;
currentVillage.VillageName = modelVillage.VillageName;
currentVillage.X = modelVillage.X.Value;
currentVillage.Y = modelVillage.Y.Value;
}
}
if (!Configuration.Security.AllowUploadArmyForNonOwner
&& currentVillage.PlayerId != CurrentUser.PlayerId)
{
await context.InvalidDataRecord.AddAsync(MakeInvalidDataRecord(
JsonConvert.SerializeObject(currentArmySetJson),
$"Attempted to upload current army to village {villageId} but that village is not owned by the requestor"
));
await context.SaveChangesAsync();
return Unauthorized();
}
var fullArmy = currentArmySetJson.Stationed + currentArmySetJson.Traveling + currentArmySetJson.Supporting;
currentVillage.ArmyOwned     = ArmyConvert.JsonToArmy(fullArmy, currentVillage.ArmyOwned, context);
currentVillage.ArmyStationed = ArmyConvert.JsonToArmy(currentArmySetJson.Stationed, currentVillage.ArmyStationed, context);
currentVillage.ArmyTraveling = ArmyConvert.JsonToArmy(currentArmySetJson.Traveling, currentVillage.ArmyTraveling, context);

await context.SaveChangesAsync();
return Ok();
}

正如@Tseng指出的那样,在IIS服务器(非开发(上尝试一下。在继续这样做之前,您应该能够快速完成以下几件事,以排除您的应用程序不是引起关注的原因。

  1. 您是否 100% 确定请求不会到达您的 netcore 应用程序?你能吗 检查 IIS 日志并关联时间戳?更好的是有小提琴手 在重试之前安装,以确保请求 实际上立即点击您的应用程序,而不是排队等候一个 大爆炸?

  2. 也尝试使用其他浏览器。使用所有优化浏览器 这些天用客户端代码做,我有一些怪癖或 您发出请求的方式,使其以您的方式运行 如上所述(排队请求以立即执行(。

如果上述两种情况不是这样,并且您可以立即确认所有请求都命中应用程序,那么我怀疑某种类型的阻止和/或资源锁定阻止了所有请求排队。

让我们知道您的发现。祝你好运。

>@Tseng是正确的 - 问题是浏览器,它似乎在脚本完成之前持有 POST 请求,但没有持有 OPTIONS 请求。

最新更新