Мой запрос на предпечатную проверку Cors кажется медленным - PullRequest
2 голосов
/ 28 мая 2019

Я заметил, что проверка "cors" занимает больше времени, чем я ожидал. Это происходило на разных скоростях от localhost, qa и production.

Я использую axios (^ 0.18.0), который использует mobx / MST / reactjs и asp.net core api 2.2

У меня могут быть опции предполетной проверки, которые варьируются от 20 миллисекунд до 10 секунд, и они будут случайным образом меняться.

Например, у меня есть

https://localhost:44391/api/Countries

Это запрос на получение, и он может занимать 20 миллисекунд 9 раз подряд (например, Ctrl + F5), но в 10-й раз он решает занять секунды (на самом деле я не получаю секунды на локальном хосте, но иногда на секунду) .

enter image description here

Итак, этот тест, 204 (запрос cors), занимает 215 мс, тогда как фактический запрос, который возвращает данные, занимает половину времени. Это кажется задом наперед.

enter image description here

enter image description here

Это мой запрос AJAX

 const axiosInstance = axios.create({
      baseURL: 'https://localhost:44391/api/Countries',
      timeout: 120000,
      headers: {
        contentType: 'application/json',
      }})

      axiosInstance.get();

Вот мой стартап. Я сделал все открытые сердечники и хотел уточнить его после того, как решил эту проблему.

public class Startup
    {
        public IHostingEnvironment HostingEnvironment { get; }
        private readonly ILogger<Startup> logger;
        public Startup(IConfiguration configuration, IHostingEnvironment env, ILogger<Startup> logger)
        {
            Configuration = configuration;
            HostingEnvironment = env;
            this.logger = logger;
        }

        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.AddCors();

            services.AddDbContext<ApplicationDbContext>(options =>
            {
                options.UseLazyLoadingProxies();
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));

            });

            services.AddIdentity<Employee, IdentityRole>(opts =>
            {
                opts.Password.RequireDigit = false;
                opts.Password.RequireLowercase = false;
                opts.Password.RequireUppercase = false;
                opts.Password.RequireNonAlphanumeric = false;
                opts.Password.RequiredLength = 4;
                opts.User.RequireUniqueEmail = true;

            }).AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();

            services.AddAuthentication(opts =>
            {
                opts.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(cfg =>
            {
                cfg.RequireHttpsMetadata = false;
                cfg.SaveToken = true;
                cfg.TokenValidationParameters = new TokenValidationParameters()
                {
                    // standard configuration
                    ValidIssuer = Configuration["Auth:Jwt:Issuer"],
                    ValidAudience = Configuration["Auth:Jwt:Audience"],
                    IssuerSigningKey = new SymmetricSecurityKey(
                    Encoding.UTF8.GetBytes(Configuration["Auth:Jwt:Key"])),
                    ClockSkew = TimeSpan.Zero,

                    // security switches
                    RequireExpirationTime = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = true,
                    ValidateAudience = true
                };
            });

            services.AddAuthorization(options =>
            {
                options.AddPolicy("CanManageCompany", policyBuilder =>
                {
                    policyBuilder.RequireRole(DbSeeder.CompanyAdminRole, DbSeeder.SlAdminRole);
                });

                options.AddPolicy("CanViewInventory", policyBuilder =>
                {
                    policyBuilder.RequireRole(DbSeeder.CompanyAdminRole, DbSeeder.SlAdminRole, DbSeeder.GeneralUserRole);
                });

                options.AddPolicy("AdminArea", policyBuilder =>
                {
                    policyBuilder.RequireRole(DbSeeder.SlAdminRole);
                });
            });


            // do di injection about 30 of these here
            services.AddTransient<IService, MyService>();


            services.AddSingleton(HostingEnvironment);

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);


            services.AddTransient<IValidator<CompanyDto>, CompanyDtoValidator> ();
            services.AddTransient<IValidator<BranchDto>, BranchDtoValidator>();
            services.AddTransient<IValidator<RegistrationDto>, RegistrationDtoValidator>();

            JsonConvert.DefaultSettings = () => {
                return new JsonSerializerSettings()
                {
                    NullValueHandling = NullValueHandling.Ignore,
                    MissingMemberHandling = MissingMemberHandling.Ignore,
                    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)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            //TODO: Change this.
            app.UseCors(builder => builder
                .AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());


            app.UseHttpsRedirection();
            app.UseAuthentication();
            app.UseMvc();

        }
    }

Я не знаю, является ли это действительным тестом, но он подражает тому, что я вижу в qa / production в случайные моменты времени.

Я изменил запрос axios на ...

 const axiosInstance = axios.create({
      baseURL: 'https://localhost:44391/api/Countries/get',
      timeout: 120000,
      headers: {
        contentType: 'application/json',
      }})

      axiosInstance.get();

в основном я ставлю / получаю, что вызывает 404

enter image description here

enter image description here

enter image description here

Тем не менее, когда я обновляю свою страницу с точно таким же сценарием, она снова завершается за миллисекунды (хотя все еще медленнее, чем 404)

Редактировать

Я сделал размещенный сайт почти идентичным моему реальному сайту. Единственное отличие состоит в том, что используется только http, а не https.

http://52.183.76.195:82/

Это не так медленно, как мой реальный сайт, но предварительная проверка сейчас может занять 40 мс, в то время как реальный запрос занимает 50 мс.

Я тестирую его в последней версии Chrome, и вам придется загрузить вкладку сети и загрузить / нажать кнопку (визуальный вывод не отображается).

enter image description here

1 Ответ

2 голосов
/ 05 июня 2019

Я не уверен, используете ли вы балансировщик нагрузки или какой-либо другой прокси-сервис, но одним из быстрых решений было бы переместить заголовки ответов CORS на уровень балансировщика нагрузки.Это минимизирует накладные расходы, которые ваше приложение может добавить в любой момент времени.Как настроить nginx в качестве прокси-службы cors, можно найти в Как включить CORS в прокси-сервере Nginx?

...