public WebRpcHandler(string baseUrl, Dictionary <string, object> environment, HttpRequestQueue queue, IRpcHandlerAppCounters rpcAppCounters = null, HttpRequestQueueOptions httpRequestQueueOptions = null) { this.rpcAppCounters = rpcAppCounters ?? nullAppCounters; this.baseUrl = baseUrl; this.environment = environment; if (httpRequestQueueOptions == null) { httpRequestQueueOptions = new HttpRequestQueueOptions(); } this.httpRequestQueue = queue; this.httpRequestQueue.SetCounters(this); this.httpRequestQueue.MaxErrorRequests = httpRequestQueueOptions.HttpQueueMaxTimeouts; this.httpRequestQueue.MaxTimedOutRequests = httpRequestQueueOptions.HttpQueueMaxErrors; this.httpRequestQueue.ReconnectInterval = TimeSpan.FromMilliseconds(httpRequestQueueOptions.HttpQueueReconnectInterval); this.httpRequestQueue.QueueTimeout = TimeSpan.FromMilliseconds(httpRequestQueueOptions.HttpQueueQueueTimeout); this.httpRequestQueue.MaxQueuedRequests = httpRequestQueueOptions.HttpQueueMaxQueuedRequests; this.httpRequestQueue.MaxBackoffInMilliseconds = httpRequestQueueOptions.HttpQueueMaxBackoffTime; this.httpRequestQueue.MaxConcurrentRequests = httpRequestQueueOptions.HttpQueueMaxConcurrentRequests; this.httpRequestTimeout = httpRequestQueueOptions.HttpQueueRequestTimeout; }
public WebRpcHandler(string baseUrl, Dictionary<string, object> environment, HttpRequestQueue queue, IRpcHandlerAppCounters rpcAppCounters = null, HttpRequestQueueOptions httpRequestQueueOptions = null) { this.rpcAppCounters = rpcAppCounters ?? nullAppCounters; this.baseUrl = baseUrl; this.environment = environment; if (httpRequestQueueOptions == null) { httpRequestQueueOptions = new HttpRequestQueueOptions(); } this.httpRequestQueue = queue; this.httpRequestQueue.SetCounters(this); this.httpRequestQueue.MaxErrorRequests = httpRequestQueueOptions.HttpQueueMaxTimeouts; this.httpRequestQueue.MaxTimedOutRequests = httpRequestQueueOptions.HttpQueueMaxErrors; this.httpRequestQueue.ReconnectInterval = TimeSpan.FromMilliseconds(httpRequestQueueOptions.HttpQueueReconnectInterval); this.httpRequestQueue.QueueTimeout = TimeSpan.FromMilliseconds(httpRequestQueueOptions.HttpQueueQueueTimeout); this.httpRequestQueue.MaxQueuedRequests = httpRequestQueueOptions.HttpQueueMaxQueuedRequests; this.httpRequestQueue.MaxBackoffInMilliseconds = httpRequestQueueOptions.HttpQueueMaxBackoffTime; this.httpRequestQueue.MaxConcurrentRequests = httpRequestQueueOptions.HttpQueueMaxConcurrentRequests; this.httpRequestTimeout = httpRequestQueueOptions.HttpQueueRequestTimeout; }
public void SingleRequest() { var queue = new HttpRequestQueue(); queue.Enqueue("http://localhost:8080/", this.ResponseCallBack, null); Assert.IsTrue(this.resetEvent.WaitOne(TimeOutMilliseconds)); }
public HttpThrottleMiddlewareTests() { _functionDescriptor = new FunctionDescriptor("Test", null, null, new Collection <ParameterDescriptor>(), null, null, null); _scriptHost = new Mock <IScriptJobHost>(MockBehavior.Strict); _metricsLogger = new Mock <IMetricsLogger>(MockBehavior.Strict); _metricsLogger.Setup(p => p.LogEvent(MetricEventNames.FunctionInvokeThrottled, null, null)).Callback(() => { Interlocked.Increment(ref _throttleMetricCount); }); var environment = SystemEnvironment.Instance; var mockServiceProvider = new Mock <IServiceProvider>(MockBehavior.Strict); var healthMonitorOptions = new HostHealthMonitorOptions(); _performanceManager = new Mock <HostPerformanceManager>(MockBehavior.Strict, environment, new OptionsWrapper <HostHealthMonitorOptions>(healthMonitorOptions), mockServiceProvider.Object); _httpOptions = new HttpOptions(); _loggerFactory = new LoggerFactory(); _loggerProvider = new TestLoggerProvider(); _loggerFactory.AddProvider(_loggerProvider); RequestDelegate next = (ctxt) => { ctxt.Response.StatusCode = (int)HttpStatusCode.Accepted; return(Task.CompletedTask); }; _middleware = new HttpThrottleMiddleware(next, _loggerFactory, TimeSpan.FromSeconds(1)); _requestQueue = new HttpRequestQueue(new OptionsWrapper <HttpOptions>(_httpOptions)); }
public async Task Invoke_MaxOutstandingRequestsExceeded_RequestsAreRejected() { int maxParallelism = 1; int maxQueueLength = 10; _httpOptions = new HttpOptions { MaxOutstandingRequests = maxQueueLength, MaxConcurrentRequests = maxParallelism }; _requestQueue = new HttpRequestQueue(new OptionsWrapper <HttpOptions>(_httpOptions)); RequestDelegate next = async(ctxt) => { await Task.Delay(100); ctxt.Response.StatusCode = (int)HttpStatusCode.Accepted; }; var middleware = new HttpThrottleMiddleware(next, _loggerFactory, TimeSpan.FromSeconds(1)); // expect requests past the threshold to be rejected var tasks = new List <Task>(); var httpContexts = new List <HttpContext>(); for (int i = 0; i < 25; 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); int countSuccess = httpContexts.Count(p => (HttpStatusCode)p.Response.StatusCode == HttpStatusCode.Accepted); Assert.Equal(maxQueueLength, countSuccess); int rejectCount = 25 - countSuccess; Assert.Equal(rejectCount, httpContexts.Count(p => p.Response.StatusCode == 429)); IEnumerable <LogMessage> logMessages = _loggerProvider.GetAllLogMessages(); Assert.Equal(rejectCount, logMessages.Count()); Assert.True(logMessages.All(p => string.Compare("Http request queue limit of 10 has been exceeded.", p.FormattedMessage) == 0)); // send a number of requests not exceeding the limit // expect all to succeed tasks = new List <Task>(); httpContexts = new List <HttpContext>(); for (int i = 0; i < maxQueueLength; 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)); }
public AsyncRequestState(Guid appId, HttpRequestQueue httpQueue, Action <AsyncRequestState> callback, /*bool isBlobStoreQueue,*/ LogCountGuard logGuard) { this.Callback = callback; // this.IsBlobStoreQueue = isBlobStoreQueue; this.LogGuard = logGuard; this.HttpQueue = httpQueue; this.AppId = appId; }
public static bool ShouldEnable(IServiceProvider serviceProvider) { var scriptHostManager = serviceProvider?.GetService <IScriptHostManager>(); if (scriptHostManager != null && Utility.TryGetHostService(scriptHostManager, out IOptions <HttpOptions> options)) { return(HttpRequestQueue.IsEnabled(options.Value) || options.Value.DynamicThrottlesEnabled); } return(false); }
public WebRpcHandler(string baseUrl, Dictionary <string, object> environment, HttpRequestQueue queue, int httpQueueRequestTimeout, IRpcHandlerAppCounters rpcAppCounters = null) { this.rpcAppCounters = rpcAppCounters ?? nullAppCounters; this.baseUrl = baseUrl; this.environment = environment; this.httpRequestQueue = queue; this.httpRequestQueue.SetCounters(this); this.httpRequestTimeout = httpQueueRequestTimeout; }
static RiotApiBase() { using (var dbContext = new DbContext()) { DbRateLimits = dbContext.RateLimits.ToList(); Queue = new HttpRequestQueue(new RateLimitList(DbRateLimits.Select(rl => new RateLimit { Limit = rl.Limit, Time = rl.Time }))); } }
private void TryGetApplicationAccountAsync(HttpRequestQueue httpQueue, Guid appId, string url, string username, string password, Action <AsyncRequestState> onGetAccountInfoCallback, int retriesCount = DefaultRetriesCount) { var logGuard = httpQueue == this.blobHttpQueue ? this.blobHttpQueueLogGuard : this.accountServiceHttpQueueLogGuard; var asyncRequestState = new AsyncRequestState(appId, httpQueue, onGetAccountInfoCallback, httpQueue == this.blobHttpQueue, logGuard); var uri = string.Format(url, appId); var request = this.GetWebRequest(uri, username, password, logGuard); httpQueue.Enqueue(request, HttpRequestQueueCallbackAsync, asyncRequestState, retriesCount); }
public void Offline() { var fiber = new StubFiber(); fiber.ExecutePendingImmediately = false; var queue = new HttpRequestQueue(); queue.MaxConcurrentRequests = 2; queue.ReconnectInterval = TimeSpan.FromMilliseconds(500); var state = new RequestState(); var state2 = new RequestState(); var state3 = new RequestState(); queue.Enqueue("http://localhost:8080?func=Forbidden", this.ResponseCallBack, state); queue.Enqueue("http://localhost:8080?func=Forbidden", this.ResponseCallBack, state2); queue.Enqueue("http://localhost:8080?func=Forbidden", this.ResponseCallBack, state3); Assert.IsTrue(state.ResetEvent.WaitOne(TimeOutMilliseconds)); Assert.AreEqual(HttpRequestQueueResultCode.Error, state.Result); Assert.IsTrue(state2.ResetEvent.WaitOne(TimeOutMilliseconds)); Assert.AreEqual(HttpRequestQueueResultCode.Offline, state2.Result); Assert.IsTrue(state3.ResetEvent.WaitOne(TimeOutMilliseconds)); Assert.AreEqual(HttpRequestQueueResultCode.Offline, state3.Result); Assert.AreEqual(HttpRequestQueueState.Offline, queue.QueueState); state = new RequestState(); queue.Enqueue("http://localhost:8080", this.ResponseCallBack, state); Assert.IsTrue(state.ResetEvent.WaitOne(TimeOutMilliseconds)); Assert.AreEqual(HttpRequestQueueResultCode.Offline, state.Result); Assert.AreEqual(HttpRequestQueueState.Offline, queue.QueueState); Thread.Sleep(750); state = new RequestState(); state2 = new RequestState(); queue.Enqueue("http://localhost:8080", this.ResponseCallBack, state); queue.Enqueue("http://localhost:8080", this.ResponseCallBack, state2); Assert.IsTrue(state.ResetEvent.WaitOne(TimeOutMilliseconds)); Assert.AreEqual(HttpRequestQueueResultCode.Success, state.Result); Assert.IsTrue(state2.ResetEvent.WaitOne(TimeOutMilliseconds)); Assert.AreEqual(HttpRequestQueueResultCode.Offline, state2.Result); Assert.AreEqual(HttpRequestQueueState.Running, queue.QueueState); }
public ClientAuthenticationQueue(string uri, string queryStringParameters, bool rejectIfUnavailable, int requestTimeout) { this.Uri = uri; this.QueryStringParameters = queryStringParameters; if (log.IsDebugEnabled) { log.DebugFormat("Create authentication queue for adress {0}", this.Uri); } this.requestTimeoutMilliseconds = requestTimeout; this.RejectIfUnavailable = rejectIfUnavailable; this.fiber = new PoolFiber(); this.httpRequestQueue = new HttpRequestQueue(this.fiber); }
private void TryGetMonitoringResultAsync(HttpRequestQueue httpQueue, Guid appId, string servernames, string url, /*string username, * string password,*/Action <AsyncRequestState> onGetMonitoringInfoCallback) { var logGuard = /*httpQueue == this.blobHttpQueue ? this.blobHttpQueueLogGuard :*/ this.monitoringServiceHttpQueueLogGuard; var asyncRequestState = new AsyncRequestState(appId, httpQueue, onGetMonitoringInfoCallback, /*httpQueue == this.blobHttpQueue,*/ logGuard); //TODO var uri = string.Format(url, servernames); var request = this.GetWebRequest(uri, /*username, password,*/ logGuard); const int RETRY_COUNT = 3; httpQueue.Enqueue(request, HttpRequestQueueCallbackAsync, asyncRequestState, RETRY_COUNT); }
private static void EnqueuWebRequest(HttpRequestQueue queue, HttpRequest request, int RequestRetryCount, HttpWebRequest webRequest, HttpRequestQueueCallback callback) { switch (webRequest.Method) { case "GET": case "TRACE": case "HEAD": queue.Enqueue(webRequest, callback, request.UserState, RequestRetryCount); return; } if (request.DataStream != null) { queue.Enqueue(webRequest, request.DataStream.ToArray(), callback, request.UserState, RequestRetryCount); } else { queue.Enqueue(webRequest, callback, request.UserState, RequestRetryCount); } }
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)); }
public void MaxConcurrentRequests() { const int requestCount = 10; this.responseCount = 0; var fiber = new StubFiber(); fiber.ExecutePendingImmediately = false; var queue = new HttpRequestQueue(fiber); queue.MaxConcurrentRequests = 2; for (int i = 0; i < requestCount; i++) { queue.Enqueue("http://localhost:8080/", this.ResponseCallBack, null); } fiber.ExecuteAllPending(); Assert.AreEqual(1, queue.RunningRequestsCount); Assert.AreEqual(requestCount - 1, queue.QueuedRequestCount); var startTime = DateTime.UtcNow; var time = TimeSpan.FromMilliseconds(TimeOutMilliseconds * requestCount); while (this.responseCount < 10) { Assert.Less(DateTime.UtcNow.Subtract(startTime), time, "Received not all responses in the expected time"); if (this.responseCount > 0) { Assert.Less(queue.MaxConcurrentRequests, queue.MaxConcurrentRequests + 1); } fiber.ExecuteAllPending(); Thread.Sleep(50); } }
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)); }
public ClientAuthenticationQueue(string uri, string queryStringParameters, bool rejectIfUnavailable, int requestTimeout, bool forwardAsJSON) { this.Uri = uri; this.QueryStringParameters = queryStringParameters; if (!string.IsNullOrEmpty(queryStringParameters)) { this.QueryStringParametersCollection = HttpUtility.ParseQueryString(queryStringParameters); } if (log.IsDebugEnabled) { log.DebugFormat("Create authentication queue for adress {0}", this.Uri); } this.requestTimeoutMilliseconds = requestTimeout; this.RejectIfUnavailable = rejectIfUnavailable; this.fiber = new PoolFiber(); this.httpRequestQueue = new HttpRequestQueue(this.fiber); this.ForwardAsJSON = forwardAsJSON; }
public async Task Invoke(HttpContext httpContext, IOptions <HttpOptions> httpOptions, HttpRequestQueue requestQueue, HostPerformanceManager performanceManager, IMetricsLogger metricsLogger) { if (httpOptions.Value.DynamicThrottlesEnabled && ((DateTime.UtcNow - _lastPerformanceCheck) > _performanceCheckInterval)) { // only check host status periodically Collection <string> exceededCounters = new Collection <string>(); _rejectRequests = await performanceManager.IsUnderHighLoadAsync(exceededCounters); _lastPerformanceCheck = DateTime.UtcNow; if (_rejectRequests) { _logger.LogWarning($"Thresholds for the following counters have been exceeded: [{string.Join(", ", exceededCounters)}]"); } } if (_rejectRequests) { // we're currently in reject mode, so reject the request and // call the next delegate without calling base RejectRequest(httpContext, metricsLogger); return; } if (requestQueue.Enabled) { var success = await requestQueue.Post(httpContext, _next); if (!success) { _logger?.LogInformation($"Http request queue limit of {httpOptions.Value.MaxOutstandingRequests} has been exceeded."); RejectRequest(httpContext, metricsLogger); } } else { // queue is not enabled, so just dispatch the request directly await _next.Invoke(httpContext); } }
public static bool ShouldEnable(HttpOptions options) { return(HttpRequestQueue.IsEnabled(options) || options.DynamicThrottlesEnabled); }
public void MaxTimedOutRequests() { var queue = new HttpRequestQueue(); // get queue into running state var webRequest = this.CreateWebRequest(string.Empty); var requestState = new RequestState(); queue.Enqueue(webRequest, this.ResponseCallBack, requestState); Assert.IsTrue(requestState.WaitOne()); Assert.AreEqual(HttpRequestQueueResultCode.Success, requestState.Result); Assert.AreEqual(HttpRequestQueueState.Running, queue.QueueState); // timeout a request webRequest = this.CreateWebRequest("Timeout"); requestState = new RequestState(); queue.Enqueue(webRequest, this.ResponseCallBack, requestState); Assert.IsTrue(requestState.WaitOne(TimeOutMilliseconds * 2)); Assert.AreEqual(HttpRequestQueueResultCode.RequestTimeout, requestState.Result); // queue should be still in running state because no value for // MaxTimedOutRequests are specified Assert.AreEqual(HttpRequestQueueState.Running, queue.QueueState); Assert.AreEqual(0, queue.TimedOutRequests); queue.MaxTimedOutRequests = 2; webRequest = this.CreateWebRequest("Timeout"); requestState = new RequestState(); queue.Enqueue(webRequest, this.ResponseCallBack, requestState); Assert.IsTrue(requestState.WaitOne(TimeOutMilliseconds * 2)); Assert.AreEqual(HttpRequestQueueResultCode.RequestTimeout, requestState.Result); // queue should be still in running state because the specified MaxTimedOutRequests // value is not reached Assert.AreEqual(HttpRequestQueueState.Running, queue.QueueState); Assert.AreEqual(1, queue.TimedOutRequests); webRequest = this.CreateWebRequest(string.Empty); requestState = new RequestState(); queue.Enqueue(webRequest, this.ResponseCallBack, requestState); Assert.IsTrue(requestState.WaitOne(TimeOutMilliseconds)); Assert.AreEqual(HttpRequestQueueResultCode.Success, requestState.Result); webRequest = this.CreateWebRequest("Timeout"); requestState = new RequestState(); queue.Enqueue(webRequest, this.ResponseCallBack, requestState); Assert.IsTrue(requestState.WaitOne(TimeOutMilliseconds * 2)); Assert.AreEqual(HttpRequestQueueResultCode.RequestTimeout, requestState.Result); // queue should be still in running state because the counter for // timed out requests is reset by the successfull request Assert.AreEqual(HttpRequestQueueState.Running, queue.QueueState); Assert.AreEqual(1, queue.TimedOutRequests); webRequest = this.CreateWebRequest("Timeout"); requestState = new RequestState(); queue.Enqueue(webRequest, this.ResponseCallBack, requestState); Assert.IsTrue(requestState.WaitOne(TimeOutMilliseconds * 2)); Assert.AreEqual(HttpRequestQueueResultCode.RequestTimeout, requestState.Result); // queue should be in offline state because the counter for // timed out requests reached the MaxTimedOutRequests value Assert.AreEqual(2, queue.TimedOutRequests); Assert.AreEqual(HttpRequestQueueState.Offline, queue.QueueState); }
public AccountServiceHealthController(HttpRequestQueue blobHttpQueue, HttpRequestQueue accountServiceHttpQueue) { this.blobHttpQueue = blobHttpQueue; this.accountServiceHttpQueue = accountServiceHttpQueue; }