Приемете, че ще се счупи
Всяко извикване на външна услуга е обещание, което може да не бъде изпълнено: мрежата пада, лимитът се изчерпва, услугата има авария, отговорът се бави твърде дълго. Разликата между демонстрация и работеща система е точно в обработката на тези случаи.
| Случай | Повтаря ли се опитът | Какво вижда потребителят |
|---|---|---|
| Мрежова грешка | да, до 3 пъти | нищо — поправя се само |
| 429 (лимит) | да, с нарастващо изчакване | евентуално „изчакайте малко“ |
| 500 / 503 | да, до 2 пъти | нищо, ако успее |
| 401 / 403 | не — ключът няма да се оправи сам | обща грешка + сигнал към вас |
| 400 (лоша заявка) | не — вина е на кода | обща грешка + запис в журнала |
| Таймаут | веднъж, с по-кратък промпт | „отговорът се забави“ |
Повторен опит с нарастващо изчакване
Отстъпление с нарастващо изчакване (exponential backoff)
След неуспех се изчаква 1, после 2, после 4 секунди — вместо да се повтаря веднага. Добавя се и малко случайност, за да не тръгнат всички клиенти едновременно.
import time, random
def s_povtorenie(f, opiti=3):
for i in range(opiti):
try:
return f()
except VremenElement as e: # само временните грешки
if i == opiti - 1:
raise
izchakvane = (2 ** i) + random.uniform(0, 0.5)
time.sleep(izchakvane)Не повтаряйте всичко
Повторният опит при 401 или 400 само хаби време и пари. Повтарят се само грешките, които могат да минат сами: мрежа, лимит, авария.
Таймаут и бюджет на времето
Заявка без таймаут може да виси минути и да задържи ресурси. Всяко извикване има таван — обикновено 20–60 секунди според задачата.
- Таймаутът се задава при клиента на модела, не се разчита на подразбиране.
- Таймаутът плюс повторните опити трябва да се събират в общия бюджет на заявката.
- При изчерпан бюджет се връща разбираемо съобщение, не се чака „още малко“.
Прекъсвач
Прекъсвач (circuit breaker)
Механизъм, който след няколко поредни неуспеха спира да опитва за известно време и връща грешка веднага.
Смисълът: когато услугата е паднала, стотиците чакащи заявки само влошават положението и задържат вашите ресурси. По-добре е бърз отказ и опит след минута.
- Броим последователните неуспехи.
- След 5 поредни спираме да звъним за 60 секунди — връщаме грешка веднага.
- След това пускаме една пробна заявка.
- Ако успее, връщаме се към нормална работа.
Резервни варианти
| Ниво | Какво прави | Кога |
|---|---|---|
| По-евтин модел | същата задача с по-малък модел | при лимит на основния |
| Кеширан отговор | връща предишен отговор на същия въпрос | при често повтарящи се въпроси |
| Само търсене | показва намерените документи без генериран отговор | когато моделът е недостъпен |
| Човек | прехвърля към служител или форма | при критични случаи |
Най-подцененият резервен вариант
Търсенето без генериране. То работи изцяло върху вашата инфраструктура и почти винаги е по-полезно от съобщение за грешка — потребителят вижда откъсите и сам чете отговора.
Защита на бюджета
- Лимит на потребител — брой запитвания на час и на ден.
- Таван на дължината — и на входа, и на изхода.
- Общ дневен таван — при достигане системата минава на резервен режим, вместо да генерира сметка.
- Наблюдение — сигнал при рязък скок на разхода (урок 24).
Класическата авария
Грешка в кода, която повтаря заявка в безкраен цикъл. Дневният таван е това, което превръща тази грешка от финансова катастрофа в неприятност.