Ejemplo n.º 1
0
        private static IAsyncPolicy GetPolicy(ILogger logger)
        {
            if (circuitBreakerPolicy == null)
            {
                circuitBreakerPolicy = Policy.Handle <Exception>().CircuitBreakerAsync(_errorCountForCircuitbreak, TimeSpan.FromMilliseconds(_circuitBreakDuration),
                                                                                       (ex, breakDelay) =>
                {
                    logger.Log(LogSeverity.Error, (ex.InnerException != null) ? ex.InnerException.Message : ex.Message + "\r\n GetTrendingStocks Circuit broken");
                },
                                                                                       () => { });
            }

            var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromSeconds(_timeoutSeconds), TimeoutStrategy.Pessimistic);
            var retryPolicy   = Policy.Handle <Exception>((ex) =>
            {
                logger.Log(LogSeverity.Error, (ex.InnerException != null) ? ex.InnerException.Message : ex.Message + "\r\n GetTrendingStocks retry FAILURE");
                return(!(ex is Polly.CircuitBreaker.BrokenCircuitException));
            }).WaitAndRetryAsync(_retryCount, x => TimeSpan.FromMilliseconds(_sleepTimeAfterFail));
            var pollyWrap = Policy.WrapAsync(circuitBreakerPolicy, timeoutPolicy, retryPolicy);

            return(pollyWrap);
        }
Ejemplo n.º 2
0
        static void Main(string[] args)
        {
            var builder = new HostBuilder()
                          .ConfigureServices((hostContext, services) =>
            {
                // v1 services.AddHttpClient();
                services.AddTransient <IMyService, MyService1>();

                // v2 - named HttpClients
                services.AddHttpClient("GitHub", client =>
                {
                    // works
                    client.BaseAddress = new Uri("https://github.com/");
                    // doesn't (no header for API key)
                    // client.BaseAddress = new Uri("https://api.github.com/");
                    client.DefaultRequestHeaders.Add("Accept", "text/html");     // returned from HTML pages
                    // client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); // not returned from HTML pages
                });

                // v3 retry against flaky service
                services.AddHttpClient("flakyService", client =>
                {
                    client.BaseAddress = new Uri("http://localhost:5000");
                    client.DefaultRequestHeaders.Add("Accept", "application/json");     // not returned from HTML pages
                })
                .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[] // v3 add HttpErrorPolicy for retry on 5XX and 408 errors
                {
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(5),
                    TimeSpan.FromSeconds(10)
                }));

                services.AddHttpClient("flakyServiceCB", client =>
                {
                    client.BaseAddress = new Uri("http://localhost:5000");
                    client.DefaultRequestHeaders.Add("Accept", "application/json");     // not returned from HTML pages
                });
            }).UseConsoleLifetime();

            var host = builder.Build();

            using (var serviceScope = host.Services.CreateScope())
            {
                var services = serviceScope.ServiceProvider;

                DateTime now = DateTime.Now, done;

                try
                {
                    // v1 (hardcoded)
                    MyService1 myService = (MyService1)services.GetRequiredService <IMyService>();
                    myService.URL = "http://www.microsoft.com";
                    Console.WriteLine(myService.GetPage().Result.Substring(0, 500));

                    // v2 (GitHub)
                    IHttpClientFactory _httpClientFactory = services.GetService <IHttpClientFactory>();
                    var client = _httpClientFactory.CreateClient("GitHub"); // pull the registered client out of factory
                    Console.WriteLine(client.GetStringAsync("/bwloomis").Result.Substring(0, 500));

                    // v3 - retry against flaky service
                    client = _httpClientFactory.CreateClient("flakyService"); // pull the registered client out of factory
                    Console.WriteLine(client.GetStringAsync("/weatherforecast?hitCount=2").Result);

                    Console.WriteLine("now trying one that won't work");
                    //now = DateTime.Now;
                    //Console.WriteLine(client.GetStringAsync("/weatherforecast?hitCount=3").Result);
                    //done = DateTime.Now;
                    //TimeSpan elapsed = done - now;
                    //Console.WriteLine($"took {elapsed.TotalMilliseconds} ms");

                    // v4 circuit breaker against flaky service (retry twice)
                    client = _httpClientFactory.CreateClient("flakyServiceCB"); // pull the registered client out of factory
                    Polly.CircuitBreaker.AsyncCircuitBreakerPolicy cbPolicy = Policy
                                                                              .Handle <Exception /* HttpRequestException */>()
                                                                              .CircuitBreakerAsync(
                        exceptionsAllowedBeforeBreaking: 1,
                        durationOfBreak: TimeSpan.FromMinutes(10),      // if not a while, the breaker will reset before failures occur
                        (ex, t) =>
                    {
                        Console.WriteLine("*****************   Circuit broken    ***************************");
                    },
                        () =>
                    {
                        Console.WriteLine("Circuit reset");
                    });

                    Task <string> innerResponse;
                    // first try, succeeds
                    for (int i = 1; i <= 4; i++)
                    {
                        try
                        {
                            // first try passes in a 6 (succeeds), second try trips the breaker (with a 7), then others revert back to 6
                            int param = (i == 2) ? 7 : 6;
                            if (i == 4)
                            {
                                cbPolicy.Reset();
                            }

                            // if you do not check CB status, and it is open, then this will not be executed
                            var response = cbPolicy.ExecuteAsync <string>(async() =>
                            {
                                innerResponse = client.GetStringAsync($"/weatherforecast?hitCount={param}");
                                if (innerResponse != null)
                                {
                                    Console.WriteLine($"innerResponse was: {innerResponse.Result}");
                                }
                                return((innerResponse != null) ? innerResponse.Result : null);
                            });

                            Console.WriteLine($"Circuit breaker is {cbPolicy.CircuitState.ToString()}");
                            Console.WriteLine();
                        }
                        catch (HttpRequestException hre) // typically do these through handlers on the policy, not through try/catch
                        {
                            // if you are securing an HTTP resource, you'll get a 503 error from time to time on our flaky service
                            Console.WriteLine($"An HTTP request exception occurred: {hre} {hre.InnerException}");
                        }
                        catch (Exception ex)
                        {
                            // this would be the other type of error, aggregate exception
                            Console.WriteLine($"An exception occurred: {ex} {ex.InnerException}");
                        }
                    }

                    // extra credit - add timeouts to calls...
                }
                catch (Exception ex)
                {
                    done = DateTime.Now;
                    TimeSpan elapsed = done - now;
                    Console.WriteLine($"An error occurred: {ex} {ex.InnerException}");
                    Console.WriteLine($"took {elapsed.TotalMilliseconds} ms");
                }
            }

            Console.ReadLine();
            // host.RunAsync();
        }