Пример #1
0
        // Executes the asynchronous method with load balancing in case of virtual network
        internal TResult ExecuteAndGetWithVirtualNetworkLoadBalancing <TResult>(Func <string, Task <TResult> > method)
        {
            if (_loadBalancer == null)
            {
                return(method.Invoke(null).Result);
            }
            else
            {
                TResult result = default(TResult);

                int numRetries = _loadBalancer.GetNumAvailableEndpoints();
                LoadBalancingHelper.Execute(() =>
                {
                    var endpoint = _loadBalancer.GetEndpoint();
                    Contract.Assert(endpoint != null, "Load balancer failed to return a worker node endpoint!");

                    Trace.TraceInformation("\tIssuing request to endpoint " + endpoint);
                    try
                    {
                        result = method.Invoke(endpoint.ToString()).Result;
                        _loadBalancer.RecordSuccess(endpoint);
                    }
                    catch (Exception)
                    {
                        _loadBalancer.RecordFailure(endpoint);
                        throw;
                    }
                },
                                            new RetryOnAllExceptionsPolicy(),
                                            new NoOpBackOffScheme(), numRetries: numRetries);

                return(result);
            }
        }
Пример #2
0
        /// <summary>
        /// Issues the web request asynchronous.
        /// </summary>
        /// <param name="endpoint">The endpoint.</param>
        /// <param name="method">The method.</param>
        /// <param name="input">The input.</param>
        /// <param name="options">request options</param>
        /// <returns></returns>
        public async Task <Response> IssueWebRequestAsync(string endpoint, string query, string method, Stream input,
                                                          RequestOptions options)
        {
            options.Validate();
            var watch = Stopwatch.StartNew();

            Trace.CorrelationManager.ActivityId = Guid.NewGuid();
            var balancedEndpoint = _balancer.GetEndpoint();

            // Grab the host. Use the alternative host if one is specified
            var host = options.AlternativeHost != null ? options.AlternativeHost : balancedEndpoint.Host;

            var builder = new UriBuilder(
                balancedEndpoint.Scheme,
                host,
                options.Port,
                options.AlternativeEndpoint + endpoint);

            if (query != null)
            {
                builder.Query = query;
            }

            var target = builder.Uri;

            try
            {
                Debug.WriteLine("Issuing request {0} to endpoint {1}", Trace.CorrelationManager.ActivityId, target);

                var httpWebRequest = WebRequest.CreateHttp(target);
                //httpWebRequest.ServicePoint.ReceiveBufferSize = options.ReceiveBufferSize;
                //httpWebRequest.ServicePoint.UseNagleAlgorithm = options.UseNagle;
                httpWebRequest.Timeout         = options.TimeoutMillis; // This has no influence for calls that are made Async
                httpWebRequest.KeepAlive       = options.KeepAlive;
                httpWebRequest.Credentials     = _credentialCache;
                httpWebRequest.PreAuthenticate = true;
                httpWebRequest.Method          = method;
                httpWebRequest.Accept          = _contentType;
                httpWebRequest.ContentType     = _contentType;
                // This allows 304 (NotModified) requests to catch
                //https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.allowautoredirect(v=vs.110).aspx
                httpWebRequest.AllowAutoRedirect = false;

                if (options.AdditionalHeaders != null)
                {
                    foreach (var kv in options.AdditionalHeaders)
                    {
                        httpWebRequest.Headers.Add(kv.Key, kv.Value);
                    }
                }
                long remainingTime = options.TimeoutMillis;

                if (input != null)
                {
                    // expecting the caller to seek to the beginning or to the location where it needs to be copied from
                    Stream req = null;
                    try
                    {
                        req = await httpWebRequest.GetRequestStreamAsync().WithTimeout(
                            TimeSpan.FromMilliseconds(remainingTime),
                            "Waiting for RequestStream");

                        remainingTime = options.TimeoutMillis - watch.ElapsedMilliseconds;
                        if (remainingTime <= 0)
                        {
                            remainingTime = 0;
                        }

                        await input.CopyToAsync(req).WithTimeout(
                            TimeSpan.FromMilliseconds(remainingTime),
                            "Waiting for CopyToAsync",
                            CancellationToken.None);
                    }
                    catch (TimeoutException)
                    {
                        httpWebRequest.Abort();
                        throw;
                    }
                    finally
                    {
                        if (req != null)
                        {
                            req.Close();
                        }
                    }
                }

                try
                {
                    remainingTime = options.TimeoutMillis - watch.ElapsedMilliseconds;
                    if (remainingTime <= 0)
                    {
                        remainingTime = 0;
                    }

                    Debug.WriteLine("Waiting for response for request {0} to endpoint {1}",
                                    Trace.CorrelationManager.ActivityId, target);

                    var response = (HttpWebResponse)await httpWebRequest.GetResponseAsync().WithTimeout(
                        TimeSpan.FromMilliseconds(remainingTime),
                        "Waiting for GetResponseAsync");

                    Debug.WriteLine("Web request {0} to endpoint {1} successful!", Trace.CorrelationManager.ActivityId,
                                    target);

                    return(new Response
                    {
                        WebResponse = response,
                        RequestLatency = watch.Elapsed,
                        PostRequestAction = r =>
                        {
                            if (r.WebResponse.StatusCode == HttpStatusCode.OK ||
                                r.WebResponse.StatusCode == HttpStatusCode.Created ||
                                r.WebResponse.StatusCode == HttpStatusCode.NotModified)
                            {
                                _balancer.RecordSuccess(balancedEndpoint);
                            }
                            else
                            {
                                _balancer.RecordFailure(balancedEndpoint);
                            }
                        }
                    });
                }
                catch (TimeoutException)
                {
                    httpWebRequest.Abort();
                    throw;
                }
            }
            catch (WebException we)
            {
                // 404 is valid response
                var resp = we.Response as HttpWebResponse;
                if (resp.StatusCode == HttpStatusCode.NotFound)
                {
                    _balancer.RecordSuccess(balancedEndpoint);
                    Debug.WriteLine("Web request {0} to endpoint {1} successful!", Trace.CorrelationManager.ActivityId,
                                    target);
                }
                else
                {
                    _balancer.RecordFailure(balancedEndpoint);
                    Debug.WriteLine("Web request {0} to endpoint {1} failed!", Trace.CorrelationManager.ActivityId,
                                    target);
                }

                throw we;
            }
            catch (Exception e)
            {
                _balancer.RecordFailure(balancedEndpoint);
                Debug.WriteLine("Web request {0} to endpoint {1} failed!", Trace.CorrelationManager.ActivityId, target);
                throw e;
            }
        }