服务架构上带有CORS的Asp.net核心API 100%CPU瓶颈

时间:2016-11-29 00:11:19

标签: asp.net-core azure-service-fabric asp.net-core-webapi asp.net-core-middleware

我在Service Fabric上托管 .Net Framework 4.5.2 的ASP.net核心为 STATELESS 服务。

API是一个vanilla API,为空

 [Route("Test")]
public class TestController : Controller
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok("Done");
    }
}

这是我的启动代码

  public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }
    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
        });

        services.AddResponseCompression();

        services.AddMvc().AddJsonOptions(opts =>
        {
            // Force Camel Case to JSON
            opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        });

    }


    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseCors("CorsPolicy");
        app.UseResponseCompression();
        app.UseMvc();
    }
}

这是OpenAsync方法:

  Task<string> ICommunicationListener.OpenAsync(CancellationToken cancellationToken)
        {
            var endpoint = FabricRuntime.GetActivationContext().GetEndpoint(_endpointName);
            string serverUrl = $"{endpoint.Protocol}://{FabricRuntime.GetNodeContext().IPAddressOrFQDN}:{endpoint.Port}";

            //.UseWebListener()
            _webHost = new WebHostBuilder().UseKestrel()
                                           .UseContentRoot(Directory.GetCurrentDirectory())
                                           .UseStartup<Startup>()
                                           .UseUrls(serverUrl)
                                           .Build();

            _webHost.Start();

            return Task.FromResult(serverUrl);
        }

一切都简单明了,没有自定义。 CORS呼叫有效,一切都很完美。 我使用带有 15K用户加载的Visual Studio Team Services进行了测试,这一切都像魅力一样,具有14K RPS。 我认为VS的负载测试不会使用CORS中间件。

现在的问题是,当我将这个空API 置于生产环境中时,接收来自 100个并发用户的呼叫时,CPU会在3分钟内跳至100% 。在CPU达到100%之前应答呼叫,然后开始发送错误。 似乎15000用户和NO CORS一切都工作,并且有100个用户+ CORS不工作,CPU达到100%并保持直到我重新启动VM Scale设置。

CPU

如果我停止发送呼叫,5节点的CPU保持稳定在99%而不接收任何一个呼叫。

这怎么可能? 我尝试了一切,项目简单明了,VS负载测试工作,只有当我把它放在来自不同站点和不同IP地址的真实CORS调用时才会发生这种情况。

我在向其发送流量之前在服务器中执行了性能跟踪,再次使用Visual Studio的负载测试,使用完全正确的CORS标头,一切都非常快。

通过真实世界调用,这就是我在探查器中看到的内容:

Trace

除了CORS中间件和通常的Kestrel进程之外,它没有任何内容。 无状态服务占用了99%的CPU,即使我停止流量也会保留它。

这是另一个30秒的跟踪,没有流量,但CPU为90%

enter image description here

我不知道还能做什么,CORS有问题,我确信它,即使它有效,也不会出现问题。

这是一个正确服务的CORS电话。

cors call

Asp.net Core CORS中间件是否存在错误?

更新

我尝试了很多组合来解决问题:

  1. 新群集,相同的Asp.net Core vanilla服务=&gt;还有问题

  2. 同一群集新项目相同Asp.net Core vanilla service =&gt;还有问题

  3. 相同的群集WebAPI OWIN服务,相同的代码=&gt; 问题被推翻!

  4. 使用带有超过50个并发请求的CORS,Service Fabric上的Asp.Net Core出现问题。

    这是使用Visual Studio模板,OWIN和CORS的Asp.Net无状态服务的CPU(0.85%),大约有100个并发连接和上面相同的空Web API

    OWIN

    此时我需要Microsoft官方来源的帮助才能解决问题。 我几乎可以肯定这是一个 Asp.net核心CORS错误,当你将它作为无状态服务托管在Service Fabric上并发送一些最小流量(不只是几次刷新)时会发生这种情况在浏览器中。)

0 个答案:

没有答案