コード例 #1
0
        public async Task Invoke_NoThrottle_DispatchesDirectly()
        {
            bool            nextInvoked = false;
            RequestDelegate next        = (ctxt) =>
            {
                nextInvoked = true;
                ctxt.Response.StatusCode = (int)HttpStatusCode.Accepted;
                return(Task.CompletedTask);
            };
            var options    = new HttpOptions();
            var middleware = new HttpThrottleMiddleware(next, _loggerFactory, TimeSpan.FromSeconds(1));

            var httpContext = new DefaultHttpContext();
            await middleware.Invoke(httpContext, new OptionsWrapper <HttpOptions>(_httpOptions), _requestQueue, _performanceManager.Object, _metricsLogger.Object);

            Assert.True(nextInvoked);
            Assert.Equal(HttpStatusCode.Accepted, (HttpStatusCode)httpContext.Response.StatusCode);
        }
コード例 #2
0
        public async Task Invoke_MaxParallelism_RequestsAreThrottled()
        {
            int maxParallelism = 3;

            _httpOptions = new HttpOptions
            {
                MaxConcurrentRequests = maxParallelism
            };
            _requestQueue = new HttpRequestQueue(new OptionsWrapper <HttpOptions>(_httpOptions));

            int             count = 0;
            RequestDelegate next  = async(ctxt) =>
            {
                if (Interlocked.Increment(ref count) > maxParallelism)
                {
                    throw new Exception($"Max parallelism of {maxParallelism} exceeded. Current parallelism: {count}");
                }

                await Task.Delay(100);

                Interlocked.Decrement(ref count);
                ctxt.Response.StatusCode = (int)HttpStatusCode.Accepted;
            };

            var middleware = new HttpThrottleMiddleware(next, _loggerFactory, TimeSpan.FromSeconds(1));

            // expect all requests to succeed
            var tasks        = new List <Task>();
            var httpContexts = new List <HttpContext>();

            for (int i = 0; i < 20; i++)
            {
                var httpContext = new DefaultHttpContext();
                httpContexts.Add(httpContext);
                tasks.Add(middleware.Invoke(httpContext, new OptionsWrapper <HttpOptions>(_httpOptions), _requestQueue, _performanceManager.Object, _metricsLogger.Object));
            }
            await Task.WhenAll(tasks);

            Assert.True(httpContexts.All(p => (HttpStatusCode)p.Response.StatusCode == HttpStatusCode.Accepted));
        }
コード例 #3
0
        public async Task Invoke_HostIsOverloaded_RequestsAreRejected()
        {
            _httpOptions = new HttpOptions
            {
                DynamicThrottlesEnabled = true
            };
            _requestQueue = new HttpRequestQueue(new OptionsWrapper <HttpOptions>(_httpOptions));

            bool isOverloaded = false;

            _performanceManager.Setup(p => p.PerformanceCountersExceeded(It.IsAny <Collection <string> >(), It.IsAny <ILogger>())).Returns(() => isOverloaded);

            RequestDelegate next = async(ctxt) =>
            {
                await Task.Delay(100);

                ctxt.Response.StatusCode = (int)HttpStatusCode.Accepted;
            };
            var middleware = new HttpThrottleMiddleware(next, _loggerFactory, TimeSpan.FromMilliseconds(50));

            var tasks        = new List <Task>();
            var httpContexts = new List <HttpContext>();

            for (int i = 0; i < 10; i++)
            {
                if (i == 7)
                {
                    isOverloaded = true;
                }
                var httpContext = new DefaultHttpContext();
                httpContexts.Add(httpContext);
                await middleware.Invoke(httpContext, new OptionsWrapper <HttpOptions>(_httpOptions), _requestQueue, _performanceManager.Object, _metricsLogger.Object);
            }
            await Task.WhenAll(tasks);

            Assert.Equal(7, httpContexts.Count(p => (HttpStatusCode)p.Response.StatusCode == HttpStatusCode.Accepted));
            Assert.Equal(3, httpContexts.Count(p => (HttpStatusCode)p.Response.StatusCode == HttpStatusCode.TooManyRequests));
        }
コード例 #4
0
        public async Task Invoke_UnderLoad_RequestsAreRejected()
        {
            _httpOptions.DynamicThrottlesEnabled = true;

            bool highLoad           = false;
            int  highLoadQueryCount = 0;

            _performanceManager.Setup(p => p.PerformanceCountersExceeded(It.IsAny <Collection <string> >(), It.IsAny <ILogger>()))
            .Callback <Collection <string>, ILogger>((exceededCounters, tw) =>
            {
                if (highLoad)
                {
                    exceededCounters.Add("Threads");
                    exceededCounters.Add("Processes");
                }
            }).Returns(() =>
            {
                highLoadQueryCount++;
                return(highLoad);
            });

            // issue some requests while not under high load
            for (int i = 0; i < 3; i++)
            {
                var httpContext = new DefaultHttpContext();
                await _middleware.Invoke(httpContext, new OptionsWrapper <HttpOptions>(_httpOptions), _requestQueue, _performanceManager.Object, _metricsLogger.Object);

                Assert.Equal(HttpStatusCode.Accepted, (HttpStatusCode)httpContext.Response.StatusCode);
                await Task.Delay(100);
            }
            Assert.Equal(1, highLoadQueryCount);
            Assert.Equal(0, _throttleMetricCount);

            // signal high load and verify requests are rejected
            await Task.Delay(1000);

            highLoad = true;
            for (int i = 0; i < 3; i++)
            {
                var httpContext = new DefaultHttpContext();
                await _middleware.Invoke(httpContext, new OptionsWrapper <HttpOptions>(_httpOptions), _requestQueue, _performanceManager.Object, _metricsLogger.Object);

                httpContext.Response.Headers.TryGetValue(ScriptConstants.AntaresScaleOutHeaderName, out StringValues values);
                string scaleOutHeader = values.Single();
                Assert.Equal("1", scaleOutHeader);
                Assert.Equal(HttpStatusCode.TooManyRequests, (HttpStatusCode)httpContext.Response.StatusCode);
                await Task.Delay(100);
            }
            Assert.Equal(2, highLoadQueryCount);
            Assert.Equal(3, _throttleMetricCount);
            var log = _loggerProvider.GetAllLogMessages().Last();

            Assert.Equal("Thresholds for the following counters have been exceeded: [Threads, Processes]", log.FormattedMessage);

            await Task.Delay(1000);

            highLoad = false;
            for (int i = 0; i < 3; i++)
            {
                var httpContext = new DefaultHttpContext();
                await _middleware.Invoke(httpContext, new OptionsWrapper <HttpOptions>(_httpOptions), _requestQueue, _performanceManager.Object, _metricsLogger.Object);

                Assert.Equal(HttpStatusCode.Accepted, (HttpStatusCode)httpContext.Response.StatusCode);
                await Task.Delay(100);
            }
            Assert.Equal(3, highLoadQueryCount);
            Assert.Equal(3, _throttleMetricCount);
        }