Back to "Використовуючи Polly для відліків"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET C# Polly

Використовуючи Polly для відліків

Sunday, 15 September 2024

Введение

Полі є вирішальним компонентом будь-якого . NET-розробника ' інструментарію M SK2 Це бібліотека, яка дозволяє вам визначити правила для використання винятків та повторів у вашій програмі Я використати Polly для обробки повторів у цій програмі.

Полі

Полі справді добре справляється з цим. МСК0 - це не все, що вона може зробити. МSK1 - це справді інструментарій для додавання стійкості до ваших програм. . - Обидві способи підключення дозовні та внутрішнього зв 'язку

Вони взяті з Поллі Strona główna і є основними шаблонами, які можна використовувати з Polly:

  • Повторно спробувати: Знову спробувати, якщо щось не вийде . Це може бути корисним, коли проблема є тимчасовою і може зникнути
  • Маршрутний розривник: Перестаньте пробувати, якщо щось зламано чи зайнятіM SK1 Це допоможе вам уникнути марнування часу і гіршого вигляду речей
  • Timeout: Позбутись, якщо щось займає надто багато часуM SK1 Це може покращити вашу продуктивність, звільняючи простір та ресурси
  • Оцінювач оцінок: Оцінювати кількість запити, які ви робите чи приймаєтеM SK1 Це дає вам змогу контролювати навантаження і запобігати проблемам або штрафам.
  • Fallback: Зробіть щось інше, якщо щось не вийде Збереження: Робіть більше, ніж одну річ водночас і візьміть найшвидшу з нихM SK1 Це зробить вашу програму швидшою та більш чутливою

Як я користуюсь Поллі

В цій програмі я користуюсь Polly в багатьох місцях.

Служба перекладу на фоновому рівні

Для запуску мого перекладу та перевірки того, чи є доступні сервери EasyNMT. THSI дозволяє мені перевірити доступність сервісу перед запуском M SK1пропонувати' перекладу в моєму додатокіMST3 ВиM ST4 пам 'ятаєте, що це обидва Мій редактор 'toyM SK1 для того, щоб ви могли перекладати позначку вниз і для мого ' в польотіM SK1 блог пост переклад. Отже, це важливий момент. Я перевіряю, чи EasyNMT не знизився ' МSK3 і дозволяю чекати, поки він не підніметься МSK4 , що може зайняти декілька секунд

 private async Task StartupHealthCheck(CancellationToken cancellationToken)
    {
        var retryPolicy = Policy
            .HandleResult<bool>(result => !result) // Retry when Ping returns false (service not available)
            .WaitAndRetryAsync(3, // Retry 3 times
                attempt => TimeSpan.FromSeconds(5), // Wait 5 seconds between retries
                (result, timeSpan, retryCount, context) =>
                {
                    logger.LogWarning("Translation service is not available, retrying attempt {RetryCount}", retryCount);
                });

        try
        {
            var isUp = await retryPolicy.ExecuteAsync(async () =>
            {
                return await Ping(cancellationToken); // Ping to check if the service is up
            });

            if (isUp)
            {
                logger.LogInformation("Translation service is available");
                TranslationServiceUp = true;
            }
            else
            {
                logger.LogError("Translation service is not available after retries");
                await HandleTranslationServiceFailure();
                TranslationServiceUp = false;
            }
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "An error occurred while checking the translation service availability");
            await HandleTranslationServiceFailure();
            TranslationServiceUp = false;
        }
    }

Тут ви бачите, що ми встановили концепцію Полі повторити спробу , яка повторить спробу 3 разів за один секундний відстанок між кожним повторенням спроби. TranslationServiceUp прапорець на фальшивий. Таким чином, будь-які послуги, які користуються перекладовою послугою, можуть знати, що він не доступнийM SK1

graph LR
    A[Start Health Check] --> B[Define Retry Policy]
    B --> C[Retry Policy: Retry 3 times]
    C --> D[Wait 5 seconds between retries]
    D --> E[Ping Translation Service]

    E --> F{Ping successful?}
    F -- Yes --> G[Log: Translation service is available]
    G --> H[Set TranslationServiceUp = true]

    F -- No --> I[Log: Translation service not available]
    I --> J[Check retry count]

    J -- Retry Limit Reached --> K[Log: Translation service not available after retries]
    K --> L[HandleTranslationServiceFailure]
    L --> M[Set TranslationServiceUp = false]

    J -- Retry Again --> E

    E --> N{Exception Occurs?}
    N -- Yes --> O[Log: Error occurred]
    O --> L

Umami.Net

Я також використовую Polly у своїй Umami.Net-ліbraрії, щоб виконувати повторні спроби, коли я роблю запити в API Umami. . Це критична частина бібліотеки, тому що вона дозволяє мені вирішувати будь-які проблеми з API і повторювати запити, якщо це необхідно.

Ось я створив HttpClient для використання Policy Retry; в цьому випадку IM SK1m перевіряє HttpStatusCode.ServiceUnavailable і повторює запит, якщо він виникає. IM SK1m також використовуючи Decorrelated Jitter Backoff стратегію чекати між повторами. Це хороша стратегія, яку можна використати, бо вона допомагає уникнути проблеми, коли всі клієнти повторюють спробу в один і той же час. M SK3 незважаючи на те, що це \ '\ - це тільки я \ МSK5. Це може допомогти зменшити завантаження на сервері та підвищити шанси, що запити будуть успішними.

     var httpClientBuilder = services.AddHttpClient<AuthService>(options =>
            {
                options.BaseAddress = new Uri(umamiSettings.UmamiPath);
            })
            .SetHandlerLifetime(TimeSpan.FromMinutes(5)) 
            .AddPolicyHandler(RetryPolicyExtension.GetRetryPolicy());


    public static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
    {
        var delay = Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromSeconds(1), 3);
        return HttpPolicyExtensions
            .HandleTransientHttpError()
            .OrResult(msg => msg.StatusCode == HttpStatusCode.ServiceUnavailable)
            .WaitAndRetryAsync(delay);
    }

Використовуючи політику повторного спробування HttpClient запити є важливим способом покращення надійності. Хоча ми любимо думати, що наші веб-сервіси завжди доступні там 's always SOME downtime МSK2in my case when for example Вежба виявляє, що закінчується оновлення, і перезапускає контейнер Umami). Таким чином, якщо у вас є політика повторного спроби, то це допоможе вам впевнитись, що ваша програма може легко справлятися з такими ситуаціями

FileSystemWatcher

Ще одна річ, яку я користуюся Polly - це коли працюю з завантаженням та збереженням файлів в моєму програмі. Я використовую FileSystemWatcher для моніторингу папки, де зберігаються мої відміткові файли. Коли файл створюється або оновується, я завантажую його і оброблюю . Це може стати проблемою, якщо файл все ще записується до того часу, коли відбувається триггеруванняM SK2 Тому я використовую RetryPolicy для вирішення цієї ситуації.

Тут ви бачите, що я керую IOException що викидається, коли файл використовується і повторює операцію. Я використовую WaitAndRetryAsync policy для повторного спробування операції 5 разів з затримкою між кожним повторним спробуваннямM SK1 Це дозволяє мені справлятися з ситуацією, коли файл все ще записується, і повторювати операцію допоки він не закінчиться

Найважливішим тут є те, що я кидаю IOException від мого SavePost метод, який дозволяє політиці Поллі керувати повторним випробуванням. Це хороший шаблон, який слід слідкувати, оскільки він дозволяє керувати логікою повторного випробування в центральному місці і не обов 'язково турбуватися про нього у кожній методиці, яка може потребувати повторного виконання операції.

В цілому завжди керувати винятками, коли ви можете і кидати на вищий рівень, де ви можете працювати з ними більш централізовано. ( або записувати їх в журналі

      private async Task OnChangedAsync(WaitForChangedResult e)
    {
       ...
        var retryPolicy = Policy
            .Handle<IOException>() // Only handle IO exceptions (like file in use)
            .WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromMilliseconds(500 * retryAttempt),
                (exception, timeSpan, retryCount, context) =>
                {
                    activity?.Activity?.SetTag("Retry Attempt", retryCount);
                    // Log the retry attempt
                    logger.LogWarning("File is in use, retrying attempt {RetryCount} after {TimeSpan}", retryCount,
                        timeSpan);
                });

      ...

            // Use the Polly retry policy for executing the operation
            await retryPolicy.ExecuteAsync(async () =>
            {
              ...
                var blogService = scope.ServiceProvider.GetRequiredService<IBlogService>();
                await blogService.SavePost(blogModel);
               ...
            });
...
    }

Знову ж таки, це приклад мого коду, який взаємодіє з зовнішньою послугою, в цьому випадку - з файловою системою . Там, де я Враховую певні типи помилок, які трапляютьсяM SK2 Я також записую їх за допомогою Серілогобстеження який надсилає їх Seq, який тоді надсилить мені електронну пошту, коли errror зареєструється, щоб я міг визначити будь-які проблеми, які могли б виникнути.

Знову ж таки, , загальною концепцією є справлятися з винятками, де можна , записувати їх, коли це можливо МSK2t і впевнитись, що у вас є спосіб дізнатися, що відбувається | ' | МSK4 | Це може допомогти переконатися, що ваша програма стійка до змін та здатна справлятись з будь-якими проблемами, які можуть виникнути

Служба електронної пошти

У моєму сервісі електронної пошти я використовую CircuitBreaker шаблон і правила повторного спробування. Правила повторного пробування використовуються для того, щоб розв 'язати проблему, коли електронні листи недоступні, а блокатор схеми використовується для розв' язання проблеми, коли електронний лист зайнятий або переповнений

Обидві з них важливі в випадку з е-мейлами; SMTP - відносно повільний і потенційно ненадійний протокол

Тут я управляю SMtpExceptions, де, коли виникає помилка з SMTP-сервісу, він спочатку повторює спробу тричі з затримкою між кожним повторенням . Якщо служба ще не доступна після репетицій МSK2 і ще два для нового відправлення M SK3 блокатор схеми відкриється і припинить відправляти електронні листи на хвилину . Це може допомогти запобігти надмірному навантаженням електронної служби MSC5 та заблокуванню мого konta МSK6 і підвищити шанси успішного відправлення електронної листи MST7

         // Initialize the retry policy
            var retryPolicy = Policy
                .Handle<SmtpException>() // Retry on any exception
                .WaitAndRetryAsync(3, // Retry 3 times
                    attempt => TimeSpan.FromSeconds(2 * attempt),
                    (exception, timeSpan, retryCount, context) =>
                    {
                        logger.LogWarning(exception, "Retry {RetryCount} for sending email failed", retryCount);
                    });

            // Initialize the circuit breaker policy
            var circuitBreakerPolicy = Policy
                .Handle<SmtpException>()
                .CircuitBreakerAsync(
                    5,
                    TimeSpan.FromMinutes(1), 
                    onBreak: (exception, timespan) =>
                    {
                        logger.LogError("Circuit broken due to too many failures. Breaking for {BreakDuration}", timespan);
                    },
                    onReset: () =>
                    {
                        logger.LogInformation("Circuit reset. Resuming email delivery.");
                    },
                    onHalfOpen: () =>
                    {
                        logger.LogInformation("Circuit in half-open state. Testing connection...");
                    });
            _policyWrap = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);
            
            

Потім це використовується в циклі відсилання електронної пошти, який чекає, щоб нові повідомлення були додані до каналу, а потім намагається їх надіслати.

Це використовує всю конфігураційність у policy, щоб додати гнучкість до процесу відправлення електронної листи.

 while (await _mailMessages.Reader.WaitToReadAsync(token))
        {
            BaseEmailModel? message = null;
            try
            {
                message = await _mailMessages.Reader.ReadAsync(token);

                // Execute retry policy and circuit breaker around the email sending logic
                await _policyWrap.ExecuteAsync(async () =>
                {
                    switch (message)
                    {
                        case ContactEmailModel contactEmailModel:
                            await _emailService.SendContactEmail(contactEmailModel);
                            break;
                        case CommentEmailModel commentEmailModel:
                            await _emailService.SendCommentEmail(commentEmailModel);
                            break;
                    }
                });

                _logger.LogInformation("Email from {SenderEmail} sent", message.SenderEmail);
            }
            catch (OperationCanceledException)
            {
                break;
            }
            catch (Exception exc)
            {
                _logger.LogError(exc, "Couldn't send an e-mail from {SenderEmail}", message?.SenderEmail);
            }
        }

На завершення

Поллі - це потужна бібліотека, яка може допомогти вам додати стійкість до ваших програм. Використовуючи Polly, ви можете справлятися з ретриями , блокаторами схем МSK2 відхиленням часу M SK3 обмеженнями швидкості , падіннями та хеджуванням в вашій програмі MSC5 Це допоможе вам бути впевненим у тому, що ваша програма надійна і здатна справлятись з будь-якими проблемами, які можуть виникнути В цьому пості я насправді лише розповідав про один аспект Polly; ретрийів, це механізм, який може покращити гнучкість і надійність вашої програми . Використовуючи Polly ви можете впоратися з ретриями в послідовний спосіб та переконатись, що ваша програма може справлятися з будь-якими проблемами, які можуть виникнути M SK3

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.