5

我在 Service Fabric 上作为无状态服务托管的 .Net Framework 4.5.2 上有一个ASP.net Core

API 是香草 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 调用有效,一切都很完美。我使用 Visual Studio Team Services 和15K users load进行了测试,这一切都像一个魅力一样,具有 14K RPS。顺便说一下,我认为 VS 的负载测试不使用 CORS 中间件。

现在的问题是,当我将这个完全空的 API投入生产,同时接收来自大约100 个用户的调用时,CPU 会在 3 分钟内跃升至 100%。呼叫被应答,直到 CPU 达到 100%,然后开始发回错误。似乎有 15000 个用户并且没有 CORS 一切正常,并且有 100 个用户 + CORS 不起作用,CPU 达到 100% 并保持这种状态,直到我重新启动 VM Scale set。

中央处理器

如果我停止发送调用,5 个节点的 CPU 保持稳定在 99%,没有收到任何单个调用。

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

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

对于真实世界的调用,这是我在分析器中看到的:

痕迹

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

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

在此处输入图像描述

我不知道还能做什么,CORS 有问题,我敢肯定,即使它有效,但不知何故出了问题。

这是一个正确服务的 CORS 调用。

科尔斯电话

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

更新:

我尝试了许多组合来隔离问题:

  1. 新集群,相同的 Asp.net Core vanilla 服务=> 问题仍然存在

  2. 相同的集群新项目相同的 Asp.net Core vanilla 服务=> 问题仍然存在

  3. 相同的集群 WebAPI OWIN 服务,相同的代码 =>问题消失了!

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

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

欧文

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

4

0 回答 0