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
Sunday, 15 September 2024
ПолліCity in Alaska USA (optional, probably does not need a translation) є критичною частиною набору інструментів розробника.NET. Це бібліотека, яка надає вам змогу визначати правила роботи з винятками і повтореннями у вашій програмі. У цій статті ми дослідимо, як це робити. I використовувати для обробки повторень у цій програмі.
Хоча Поллі справді добре пише, це не все, що він може зробити, це справді інструментат для додавання стійкості до ваших рекомендацій. І те, і друге закликає до позаурочних послуг, і інше.
Вони взяті з Основна сторінка Polly і є основними шаблонами, які ви можете використовувати за допомогою Polly:
У цій програмі я використовую Polly у багатьох місцях.
Для запуску служби перекладу і перевірки серверів EasyNMT доступні. Thsi дозволяє мені перевірити, що сервіс доступний перед тим, як почати "пропонувати" перекладацьку службу в моєму додатку. Ви пам'ятаєте, що це обидва використовується для Мій редактор " іграшкова" щоб ви могли перекласти відмітку на мою "на муху" Рушій перекладу блогу. Отже, це критично. Я перевіряю, що EasyNMT не зменшився (і вмикання очікування до того часу, коли воно прийде; що може тривати декілька секунд).
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 рази з 5 секунд очікування між кожною спробою. Якщо службу після спроб служби не буде знайдено, ми вестимемо запис про помилку і оброблятимемо помилку за допомогою параметра TranslationServiceUp flag to false. Тоді будь - які служби, які використовують перекладацьку службу, знають, що вона недоступна.
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
А ещё я использую Полли в моей библиотеке "Уамами.Net," чтобы уладить сделки, когда высылаю приглашения в API Umami. Це критична частина бібліотеки, яка дозволяє мені впоратися з будь-якими проблемами з API і повторити запит, якщо потрібно.
Ось мій. HttpClient для використання правила повторення; у цьому випадку я перевіряю на HttpStatusCode.ServiceUnavailable і повторила спробу запиту, якщо це сталося. Я також використовую a Decorrelated Jitter Backoff Стратегія очікування між рецидивами. Це добра стратегія, яку слід використовувати, щоб уникнути проблеми "розподілу," де всі клієнти знову намагаються одночасно (хоча це тільки я:). За допомогою цього пункту можна зменшити навантаження на сервер і збільшити ймовірність успішного надсилання запиту.
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 Просьба є важливим способом поліпшення надійності. Хоча нам подобається думати, що наші веб-служби завжди доступні, завжди є деяке скорочення (в моєму випадку, коли, наприклад, Вартова Башта визначає пріоритет оновлення і перезапускає контейнер Umami). Отже, якщо ви будете дотримуватись політики повторення, це допоможе вам з приємністю справлятися з такими ситуаціями.
Ще одне використання, яке я роблю з Polly, це коли йдеться про завантаження і збереження файлів у моїй програмі. I use a FileSystemWatcher для спостереження за каталогом, у якому зберігаються мої файли markdown. Під час створення або оновлення файла я завантажую файл і обробляти його. Це може бути проблемою, якщо файл все ще буде записано під час вмикання події. Тож я використовую a RetryPolicy чтобы справиться с этой ситуацией.
Тут ви бачите, що я маю справу з IOException викине цей параметр, якщо файл використовується, і повторить спробу дії. I use a WaitAndRetryAsync правило повторення операції 5 разів з затримкою між кожною спробою. Це дозволяє мені впоратися з ситуацією, до якої файл все ще пишеться, і повторити операцію до того часу, доки він не буде успішним.
Важливим тут є те, що я кидаю "в" до IOException від мого SavePost метод, за допомогою якого правила Політики можуть керувати спробою. Це хороший шаблон для того, щоб ви могли впоратися з логікою повторення в центральному місці і не турбуватися про це у всіх методах, які можуть повторити операцію.
Загалом завжди мати справу з винятками, де ви можете і bill up на вищий рівень, де ви можете працювати з ними більш централізованим чином (чи записувати їх). Це допоможе зменшити складність вашого коду і зробити його послідовним у винятті винятків.
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);
...
});
...
}
Знову ж таки, це приклад мого коду, який взаємодіє з зовнішньою службою, у даному випадку з файловою системою. Там, де я EXEXECT певних типів помилок, має з'явитися. Я також записую їх за допомогою SerilogTracing что отправит их в Сек, который телепортирует мне письмо, когда проигрыша входит в журнал, так что я смогу опознать любые проблемы, которые могут произойти.
Знову ж таки, загальний підхід до справи з винятками, де ви можете, запишіть їх, коли не можете і впевніться, що маєте спосіб дізнатися, що відбувається. Це допоможе вам бути гнучкими і справлятися з будь - якими проблемами.
У своїй поштовій службі я користуюся обома CircuitBreaker Візерунок і правила повторення. Правила повторення використовуються для роботи з службами електронної пошти, де служби електронної пошти недоступні, а також для роботи з районним вимикачом, коли служба електронної пошти зайнята або перенавантаження.
Обидва ці пункти важливі для повідомлень електронної пошти; SMTP - відносно повільний і потенційно ненадійний протокол.
Тут я розробляю SmtpExcodings, де, коли з служби SMTP приходять помилки, спочатку буде повторено три рази з затримкою між кожною спробою. Якщо після повторних спроб (і ще два для нового надсилання) служби не буде знайдено, засіб для пересилання районного зв' язку на хвилину відкриє і припинить відсилання електронних листів. За допомогою цього пункту ви можете запобігти перевантаження служби електронної пошти (і заблокуванню мого облікового запису) та удосконалити шанси успішного надсилання повідомлення електронної пошти.
// 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);
Цей елемент використовується у циклі надсилання пошти, який чекає на додавання нових повідомлень на канал, а потім намагається надіслати їх.
Для цього в процесі відправки електронної пошти використовується все, що пов'язане з фантіоантулію, щоб додати стійкості до процесу відсилання повідомлень електронної пошти.
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);
}
}
Поллі - це могутня бібліотека, яка може допомогти вам додати гнучкості до ваших програм. За допомогою поліцій ви можете керувати розкладами, переривами, тайм- аудиторією, обмеженням швидкості, поверненням назад і зверненням до вашої програми. Це допоможе вам переконатися, що ваше застосування надійне і може розв'язати будь - які проблеми. У цьому пості я дійсно тільки що охоплює один аспект Поллі; звернення, це механізм, який може покращити стійкість і надійність вашого застосування. Якщо ви користуєтесь поліцією, то зможете послідовно впоратися з картами і переконатися, що ваша програма вирішить будь - які проблеми.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.