Галоўная / Артыкулы / Чаму падыш узгадчасці спрычыная HTTP 429: што такое частота запуску і ліміты на адного хоста

Чаму падыш узгадчасці спрычыная HTTP 429: што такое частота запуску і ліміты на адного хоста

Збільшэнне колькасці працоўнікаў без кантролю над шчыльнасцю запуску і лімітамі на адного хоста стварае спалахі, які вызываюць памылку 429. Пропускная здатнасць досягаецца за дапамогою рэгульавання паралельнасці, технік звяртання праз час і розумнага проектавання абаранку.

3571 слоў

TL;DR: Падыш у роўначаснасці працы адбываецца пад вывескай “бесплатны паралелізм”: больш работнікаў, больш запытоў, больш дадзейнасці. Дзесяць — гэта непарадны показнік, таму двадцать павінны быць лепей, а пяцьдзесят — непраўдападобны. Але прыбавленне колькасці ресурсаў не толькі падышвае роўначаснасць; гэта таксама вялікая мера таго, насколькі інтэнсыўна кліент падае запыты на хост з самага пачатку, а ў разе роботы з калькама хостоў — якая роўначаснасць за аднаго хоста будзе існаваць без якога-лібо прызначэння. Калі гэтыя “скрытые” настройкі перестаюць працаваць, код статусу часта становіць HTTP 429, што абоўсюды асоціюецца з “занадта большым колікствам роўначасных запытоў”. Тады команды скарочваюць колькасць ресурсаў, дадаюць проксі або проста пераходзяць да іншага рашэння. Не выявіўшы справжню прычыну, яны втрачаюць можлівасць падняць эфективнасць працы.

Частка I — Роўначаснасць працы проты швайна запуску: адна настройка пула керуе двумя лімітамі

Размах колькасці працоўнікоў (p-limit(n), семафор, колькасць нітав) абмежвае колькість операцыяў, якія можа выконвацца ў той момент. Ён не абмежвае швальнасць пачатку новых заданняў. У момент t=0 колькасць п’яцідзiesяти заданняў, якія чакают на выконанне, може дазволіць запускаць п’яцідзiesят запитоў за адну імпульсную період — тэкст спаду швальнасці пачатку, — навет якщо стабільная паралельнасць пазней будзе выглядаць “толькі п’яцідзiesятым”. Лімітары швальнасці уважаюць гэты раптовы сплеск так сама, як і стабільную паралельнасць.

Апылкаванне сплеску швальнасці пачатку

Дапамагае інструмент для павтаральных тэстаў. Возьміце невялікі набор URL-адрэсаў статэйкаў на Arch Linux Wiki:

https://wiki.archlinux.org/title/Arch_Linux
https://wiki.archlinux.org/title/Installation_guide
https://wiki.archlinux.org/title/Pacman
https://wiki.archlinux.org/title/Systemd
...and so on

Створыце навантажэння з 100 запитоў, парадуячы список:

function buildWorkload(urls, n) {
  return Array.from({ length: n }, (_, i) => urls[i % urls.length]);
}
async function runPooledFetch(urls, concurrencyLimit, agent, options = {}) {
  const limit = pLimit(concurrencyLimit);
  const results = await Promise.all(
    urls.map((url) => limit(() => fetchOne(url, agent)))
  );
  // ...
}

Заўядзейце з разнымі розмерамі басэна, класыфікуйце кожны результат як «годна» або 429 (і іншыя працэзломы), а таксавайце колькість завершаных запросоў за секунду разам з колькасцю «годных» результатаў. Разлік мае значэнне: швырак 429 таксама спадчынае да метрыкі «завершаных запросоў/секунду», хаця не дастае стораніцы.

Корыстная праўоцяснасць падваічвается з адным ростам глобальнай канкурантнасці

Калі колькасць запытак фіксаваная і зменшваецца толькі вялічына пула, працэўнае з’ёднанне практычна неэфективна. Пры канкурэнцыі 1 практычна всі 100 запытакаў выкананы, і колькасць завершаных запытакаў на секунду становіцца або блізка 2,4/с — трэба чакаць на завершэнне обробкі без можлівасці паралельных запускаў. Пры канкурэнцыі 10 корисных дадзеных застаецца мало: выкананыя стораніцы — або блізка 42, а 58% запытакаў вяртае код 429, тады колькасць завершаных запытакаў на секунду паднікае да або блізка 23,5/с. Пры канкурэнцыі 25 і 50 колькасць выкананых запытакаў продовжвае спадзяцца (апошней час — або блізка 24/100, потым 16/100) , тады колькасць завершаных запытакаў на секунду застаецца у дыяпазоне ад 18 да 22 на секунду (~18,2/с і 21,8/с).

Максімум прагізмы даесяць паралельных запускаў пры 23,5 завершаных запитоў/секунду — гэта сама высокая цыфра ў табліце — але разам з аднай з найгорэйшых колькасціў успешных запитоў. Для оптымізацыі па колькасці завершаных запитоў за секунду рэкамендуецца выбраць настройку, якая выкорыстоўвае большую частку «бюджету» на блакаванні запитоў. Рэальна корыстны показнік — успешных запитоў/секунду, а не проста загальная колькасць завершаных запитоў.

Даадзеўкі ліміту швыроці запуску пры той жа канкурэнцыі вырашае проблему

Зберагце розмер пула без змены і контролюйце, калі можа пачацца наступны запит. Мінімальную паўзу можна вылучыць на адной з наяўных настаўкаў па максымальнай колькасці запитоў за секунду:

// minGapMs derived from --max-rps; pool concurrency is untouched
if (minGapMs > 0) {
  const now = Date.now();
  const waitMs = Math.max(0, nextStartAt - now);
  if (waitMs > 0) await sleep(waitMs);
  nextStartAt = Math.max(Date.now(), nextStartAt) + minGapMs;
}

За дапамогою такога падходу тая ж канкурэнцыя, якая раней перавантажвала хоста, може завершыць практычна всі сторанкі, адтаку запускаў зменшыцца. Правільны падход — выкарыстоўваць два параметра: канкурэнцыю (запускаемых запитоў) і швыроцю запуску (запитоў, якія дазволены за секунду). Аднакаванне іх у адна цыфру масківае прычыны неудач.

Чаму кластэрны HTTP-кліент адправляе серыю запыткаў у момант t=0

Кластэры не ведаюць пра адлічаны темп выконання запыткаў. Яны ведаюць пра вольныя слоты. Пад час запуску кожны слот ўвесь час вольны, таму кожная задача, якая можа быць выконана, дыржыць і ўжо выконваецца. Павторнае выкарыстоўванне з’язкоў і мультіплексаванне HTTP/2 можа зробіць густоту запыткаў ў канэ лініі ўсё вышэй. Толькі кантроллер дазволаў — такі як контейнер з токенамі, правілы мінімальнага інтэрвалу часу, контейнер з выцекам — можа кантролюваць пачатак выконання задач незалежна ад лімітаваў, дзеяных пад час ўжо выконваных запыткаў.

Чы рэзідэнцыйскія проксі выправляюць проблему раптовага падвышэння тэхасу запыткаў?

Адлічаны темп выконання запыткаў — гэта спосаб выправлення проблем з правільнасцю: сабіраць даныя без раптоваг падвышэння навантажэння на цэль. Але інжынерныя рэаліі іноды вымагаюць такой швалькі, якую не можа забезпечыць ліміт у 2,4 запытка/секунду. Той самы наўмовны падход — без ліміту тэхасу запыткаў, кластэрныя запыткі ў момант t=0 — калі яны праходзяць через рэзідэнцыйскія проксі, можа даўаць прыблізна 98–99/100 успехоў, практычна без блакаванняў на розных рэвалюцыях паралельнага выконання, тады калі прямой шлях все ўсё равно страждае.

Это не значыць, што проксіы пазбегаюць неабходнасці разумець шчытласць запуска. Яны зменяюць репутацыю IP-адрэс і тое, насколькі агрэсыўна сайт прызначае трафік. Яны можу маскуваць спрыжчанне, якое могла б заблокаваць адзіну выходную IP-адрэсу. Якщо тэхнічная вакалатка продукту — «збираць даныя без адчування натоўпнага напору», то тэмпы застаюцца главным засобам кантролю; проксіы ўжо ўтвараюць слой магчымасцей і репутацыі, а не замену для вимеры колькасці запускаў.

Стварэнне проксі-агента зазвычай запоўняе даныя аб прывілегіях з аптэкі:

function buildProxyAgent() {
  const user = process.env.BRIGHT_DATA_PROXY_RESIDENTIAL_USERNAME;
  const pass = process.env.BRIGHT_DATA_PROXY_RESIDENTIAL_PASSWORD;
  if (!user || !pass) return null;
  const host = process.env.BRIGHT_DATA_PROXY_HOST || 'brd.superproxy.io';
  const port = process.env.BRIGHT_DATA_PROXY_PORT || '33335';
  const proxyUrl = `http://${encodeURIComponent(user)}:${encodeURIComponent(pass)}@${host}:${port}`;
  return new HttpsProxyAgent(proxyUrl);
}
const residentialAgent = buildProxyAgent();
await runPooledFetch(tasks, 50, residentialAgent);

Іспользуйце іх цярпліва, фіксуйце, чы робота была безпосередняя чы чераз проксі, і ўсё раве фіксуйце зафіксаваную шчытласць запускаў на секунду, каб знаты, які фактор паўлікваў рэзультат.

Частка II — Канкурэнція на адного хоста

Глобальныя пулы таксама маскуюць другі, новападзяўшы ліміт. Разглядзіце:

const limit = pLimit(50);
await Promise.all(urls.map((url) => limit(() => fetchOne(url))));

Пяцьдзесят глобальных слотаў, распадзеленых між большам чысла хостаў, не значыць, што кожны хост бачыць максымум пяцьдзесят запускаемых заданняў. Порядак у чарзе та адхіленьні ў часе адпаведзення вялікай меры вабяць, сколькі запитоў на самай працэ практычна приймае адны хост. Сумешаны список можа выглядаць збалансаваным на паперы:

1. arch
2. github
3. arch
4. mdn
5. npm
6. arch
7. cloudflare

але ўсё равно спрыяе значным навантажэнням на строгі хост, калі його URL-адрэсы знаходзяцца ў наборе заданняў, якія можна запусціць.

Аналіз паралельнай працы кожного хоста

Павтараюць выкарыстоўваеце цей інструмент з двума хостамі:

  • Строгі хост — Arch Linux Wiki (10 URL-адрэсаў статэйк), який блакуе пад навантажэнням, як і ў частцы I.
  • Благасклонны хост — стораніцы каталогу books.toscrape.com (10 URL-адрэсаў), якія рэдка блакуе і служыць для кантролю. Якщо сандбокс не працуе, значы кліент несправны.

Альтэнатыўны спіс дае 20 URL-аў × 5 павтарэнняў = 100 запытоў пры глобальнай канкуранцыі 50. Спісы фіксатуў і канструяторы знаходзяцца ў рэпазітарыі open-concurrency-trap-bench (напрыклад urls-mixed-arch-books.txt).

https://wiki.archlinux.org/title/Arch_Linux
https://books.toscrape.com/catalogue/page-1.html
https://wiki.archlinux.org/title/Installation_guide
https://books.toscrape.com/catalogue/page-2.html
https://wiki.archlinux.org/title/Pacman
https://books.toscrape.com/catalogue/page-3.html
...and so on

Упорядкованыя завадзбы можна выконваць за принцыпам round-robin, блакаваць па хостах або перасортаваць за дапамогою сэду:

function buildOrderedWorkload(urls, pattern, { repeatsPerUrl = 5, seed = null } = {}) {
  const n = urls.length * repeatsPerUrl;
  let list = Array.from({ length: n }, (_, i) => urls[i % urls.length]);
if (pattern === 'block') {
    // AxN, BxN, and so on. Repeat each URL before advancing.
    const out = [];
    for (const url of urls) {
      for (let i = 0; i < repeatsPerUrl; i++) out.push(url);
    }
    return out;
  }
if (pattern === 'shuffle') {
    // Fisher–Yates with a fixed seed so the run is reproducible
    for (let i = list.length - 1; i > 0; i--) {
      seed = (Math.imul(1664525, seed) + 1013904223) >>> 0;
      const j = seed % (i + 1);
      [list[i], list[j]] = [list[j], list[i]];
    }
  }
  // 'round-robin' leaves the alternating list as-is
return list;
}

Змяроўваецца максімальны пакет заданняў на кожнам хосте на адной з моментаў пачатку/заканчэння:

function maxConcurrentPerHost(results) {
  const eventsByHost = new Map();
  for (const r of results) {
    const host = new URL(r.url).hostname;
    if (!eventsByHost.has(host)) eventsByHost.set(host, []);
    const end = r.startedAt + r.ms;
    eventsByHost.get(host).push({ t: r.startedAt, delta: 1 }, { t: end, delta: -1 });
  }
  // sort events by time, sweep: +1 on start, -1 on finish, track max
}

Глобальная канкуранцыя застаецца стаячай; зменяецца толькі порядак. Чыгунтае цэ гучанне на кожны хост ад размеру пула.

Як порядак у черзі зменяе канкуранцыю на кожны хост

Рэальныя краулеры ніколі не выконваюць заданні за принцыпам perfect round-robin вечна. Сайтмапы, графы залежнасцяў і чергі на павторны запуск перасортаваюць заданні. Таму ідэнтычныя глобальныя настройкі можа даць разныя максімумы на кожны хост.

1. Round-robin: альтэнатыўнае равныя распадзеленыя хосты

Альтэнатыўны спіс (A B A B …) распрашчае работу. Максімум запрашанняў на строгам хосте застаецца ступеняваным, таму што іншы хост продовжвае займаць вільныя ресурсы.

2. Блок: агрупаванне запрашанняў з таго ж хоста

Агрупаванне всіх URL-адрэсаў Arch, а пасля ўсіх URL-адрэсаў кніг, дае строгаму хосту моцна длігкі перыяд роботы. Максімум запрашанняў на гэтым хосте падыходзіць да розмеру глобальнага пула, нават як «канкурантнасць застаецца 50».

3. Шуфляваўне (сэд 42): абыяковы порядак

Шуфляваўне з заданым сэдам знаходзіцца межа двух крайносцей і відпраўляе абыяковы порядак запрашанняў. Максімумы зменяюцца ў залежнасці ад сэда; урок тут — чувствяўнасць, а не магічная пермутацыя.

Тая ж глобальная канкурантнасць, разны тыроз на кожнага хоста

У разліце з гэтымі шаблонамі, практычны рэйт канектыбілітэта на строгай гульпе парадкавае свой максімум у процэсе выпалоў болей адточна, чым сталягае глобальнае значэнне c=50. Благасклонная гульпа застаецца здаровай. Зніжэнне глобальнага розмеру гульпы, каб «вылечыць» строгую гульпу, таксама зашкодзіць благасклонной гульпе і так і не дапаможаў бы стабілізаваць максімум строгай гульпы пад некаштовным порядкам выпалоў.

Рашэнне: аддзельна лімітувацыя канкурантнасці па гульпе

У Частцы I быў даданы ліміт на швальнасць запуску праз гульпу. У Частцы II дадаўся ліміт па гульпе: внутрані ліміт на тое, сколькіх запускаў у процэсе выпалоў можа маты цяперашній хост.

Памяцайце тры тэрміны:

  • Глобальная канкурантнасць — спяльны розмер гульпы (напрыклад p-limit(50)). Яго задаеце вы.
  • Канкурантнасць па гульпе — тое, што фактычна бачыў адзін хост (peak_inflight). Яго вимерваеце вы.
  • Ліміт на адміністрацыю — адзінэчны максімум, які вы выбираеце для колькась тымчасовых запыткаў, якія можа прыймаць адна конкрэтная адміністрацыя, якай знаходзится пад кераваннем глобальнага пула.
  • Якщо такі ліміт на адміністрацыю не існуе, кожны вольны глобальны слот можа быць выкарыстоўаны тымі URL-адрэсамі, якія ў той момент ў доступе — што можа прывести да перанасылення адной адміністрацыі. Даўжэнне внутрашняга ліміту дазволяе кожной адміністрацыі маты свой саўны:

    async function runPooledFetch(urls, concurrencyLimit, agent, { perHostLimit } = {}) {
      const globalLimit = pLimit(concurrencyLimit);
      const hostLimiters = new Map();
      async function fetchWithLimits(url, execute) {
        return globalLimit(async () => {
          if (perHostLimit && perHostLimit >= 1) {
            const host = new URL(url).hostname;
            if (!hostLimiters.has(host)) hostLimiters.set(host, pLimit(perHostLimit));
            return hostLimiters.get(host)(execute);
          }
          return execute();
        });
      }
      // ...
    }
    

    Такім чынам кластэр URL-адрэсаў з строгімі лімітамі не можа адразу зайняць усе глобальныя слоты. Адміністрацыі з менш строгімі лімітамі все ўсё можа выкарыстоўваць застатковую прыемнасць. Забаны стаюць наследкам тых лімітаваных параметраў, якія вы хацелі кераваць.

    Чаму спяльны пул працоўнікаў концентруе навантажэнне на адной адміністрацыі

    База дадзеных запоўняе асобкі паверхні любымі заданнямі, якія можна выконваць. Шырокаспектныя хосты быстра зваліваюць асобкі паверхні і беруць на сябе больш за сваімі можлівасцями заданняў — пакуль група URL-адрэсаў строгіх хостоў не стане спроможнаю выконваць заданняя разам і не успадкуе павышаную навантажэння. Размах павышанай навантажэння залежыць ад порядку выконвання, затрымкаў і сумешанні заданняя — нічога з гэтага не практыкуецца ў аднам целым для вырачэння канкурантнасці. Самэ гэтая прычына, чаму лімітар па кожны хост ёсць кращы, чым слепа зменшэнне глобальной базы дадзеных.

    Практычны чарткі

    • Спрыяйце шчытлу запуску як самастояму настройкі. Семафор не ёсць лімітарам RPS. Дадзіце явны ліміт шчыту запуску па боку канкурантнасці.
    • Спрыяйце канкурантнасці па кожны хост як самастояму настройкі. Заданняя для калько хостоў патрабуюць лімітара па кожны хост унутры глобальной базы дадзеных.
    • Зявіце логі observed_start_rps і паказнік peak_inflight па кожны хост. Нельга аналізаваць ліміты, якія ніколі не былі вымераны.
  • Оптымізавайце корыстны праўерхнёс. Урачыставайце показнік ok-per-second, а не completed-per-second; быстрыя 429s таксама лічыцца як неудачы.
  • Точныя прагі ў кожнай адзіной роботе блога не ўсёвыконныя: лімітары залежнаць ад стану системы і залежаць ад часу, історыі трафіку і репутаціі IP. Універсальны падход — ізоляцыя. Неудача, якая выглядае як «занадта велика канкурантнасць», можа быць проблемай швальнага темпу запуску, проблемай планавання для кожнага хоста або ж і тым, і іншым. Даколі гэтыя факторы не будуць аддзельнымі, скарчэнне колькасці ресурсаў падае толькі на симптам — і часта не на правы.

    Чытанне метрык без абману сабе

    Колькасць завершаных запыткаў за секунду зростае кожны раз, калі кліент можа быстра ачыняць сокеты — нават тады, калі большасць адпаведзей ёсць адмовы. Дашборды, якія фіксуюць роботу паўнароўнай паралельнасці без фільтра па статусу „ok“, будуць рэкамендаваць шкодныя настройкі. Паруйце кожную дыяграму праэфектыўнасці з кантэкстам статусу „ok“ і, як толькі можна, з колькасцю байтав корыстнага кантэнту, які засталіся. Якщо ваша система прабуе зноў выканаць запыткі, якія вярнулі код 429, пісачыце колькасць такіх спроб окрема, ўбачліва, каб надмерная колькасць прабаў не выглядала як продуктыва паралельнасць.

    Логі з колькасцю запыткаў, якія былі приймлены, должны фіксаваць часовы пазнак з кожнага приймання, а не толькі з кожнага завершэння. На аднойчыных дадзенах вы можете відтворыць сплескі акывнасці прыбліжна за першыя 100–500 мс, і самэ гэта є тым періядам, калі багато кліентаў выглядаюць аднакова, незалежна ад установленага розмеру пула. Якщо две настройкі маюць аднаковы сплеск пачатку акывнасці, не дзівіцеся, якщо ў іх будзе аднаковы патэрн адмов.

    Проксі, репутацыя і часовасць ў спраўе компромісаў

    Проксі для жытловых прыемнікаў чы сэрвераў збору дадзеных перадаюць ідэнтыфікацыю. Яны можаць ператварыць атаку з аднаго IP-адрэса на некалькі менш інтэнсыўных трафікаў. Це дапамагае проектам збору дадзеных і можа скрыць слабыя механізмы кантролю доступу ад пункта прыема, які ставіць ліміты на IP-адрэсы. Гэта не пазбавляе нас этычных і даговорных абавязакаў па відношэню да сайтаў, з якіх мы запрашываем дадзеныя, а таксама не пазбавляе нас тэхнічной неабходнасці разумець свога сопрацоўніка. Калі вы контролюеце сопрацоўніка, спачатку важліва стабільнасць; выкорыстоўвайце проксі тады, калі продукт практычна выклікае большую загальную праўоцэсу наявнасці через некалькі ідэнтыфікацый — і продовжайце мераваць навантажэнне на кожную ідэнтыфікацыю і кожны хост, ўбачліва не працаваючы слепа за шаром проксі.

    Аднае ў адно

    Програмы для аналізу працэй зазвычай патрабуюць або ўсіх этых параметраў: глобальны резерв для захавання рэсурсаў з вашай стороны, ліміт швырака запуску для адпаведнасці пад час прыемкі, а таксама ліміты на кожнага хоста, калі кантэйнеры дзеляюць аднойчы резерв. Ігнараванне хоць якога з іх восстанавляе ситуацыю краху, якая “выглядае як канкуранція” у кодах статусу HTTP. Адлагоджэнне не ўмоўнае; гэта апаратная падтрымка плюс другі лімітар, нацэлёваны на ту зменную, якую вы фактычна заазначылі.

    Прыметкі да дизайну прыладоў, якія забезпечваюць справядлівыя порэванні

    Зберагаеце ідэнтычную таксанамію успеху па всіх працаваннях: статусы «ok», HTML, HTTP 429, іншыя коды 4xx/5xx, працяўкі часу та бягучыя памилкі парсавання должны меткацца аднойчынна ў кожнай практыцы. Зменяйце толькі параметры, якія тэстуеце — велічыну пула, мінімальны прыемлівы інтэрвал, увёмкванне/выключэнне проксі чыста парад у черзі. Як толькі можна, адгрэйвайце DNS і TLS, каб першыя пункты графіка не былі занадта адчувальныя да парадоксаў холаднага адключэння, як толькі холадны запуск не ўскладнюецца як частка эксперыменту.

    Павтараюце заведамасці достатню колькість разоў, каб зменшыць шум, але не так часта, каб адаптатыўны лімітар сайту перманентна зменяўся ў ходзе эксперыменту. Калі лімітары маюць стан, зазначайце час дзяніны і чы можа паказваныя раней забароны ўсё яшчэ вплываць на роботу. Публікуйце значэння-семены для перасортавання, каб іншыя моглі відтворыць эфекты параду.

    Адресы URL должны быць стабільнымі. Заглавяў у Вікі і стороніцы каталогу сандбокса, якія зникаюць пад час аналізу, спакштуюць лік паводлів. Зберагаюце спісы фіксаў у системе кантролю версыйяй разам з іншымі дадзеннямі, як гэта робіць проект concurrency-trap-bench, каб графікі аднасіліся да вядомых вхідных дадзенняў.

    Як выглядае «прыдатны праўерхад» у пайплайне

    Сістэмы, якія працуюць пасля перадачы дадзенняў, актуальныя для ўсвайомлення дакументаў, а не колькасць з’являючыхся і зникаючых соектаў. Якщо скрапер падае дадзеныя індексатору, лічыце дакументы, якія былі індексаваны за хвіліну. Якщо ён падае дадзеныя базе даных цэнаў, лічыце паўнастаўленыя рэкорды. Салідаравайце цель оптымізацыі з задачамі данай бізнес-ячэйкі. Аднойчы больш інжынеры будуць максімізаваць прамежуточны показнік — колькасць завершаных HTTP-звяроўкаў — які включае велічызны колькасць тэлаў з кодам 429.

    Павтаральныя спробы пагубна вплываюць на басейны без регулярнага таймінгу. Разгар актывацыяў, які прыводзіць да забаранень, а пасля ягох негайныя павтаральныя спробы, можа ўсё больш збільшыць шчыльнасць запускаў. Павышайце інтэрвал павтаральных спроб у разы 429 з дэфляксам, адказваюце на параграф Retry-After, калі ён прысутны, і ніколі не дазволяйце штормам павтаральных спробаў абійсці правіла шчыльнасці запускаў. Контролер адмашчэння должен спрыймать павтаральныя спробы як новыя запускі.

    Распрацоўвальнікі з мнагама аб’ектамі і мнагами хостамі

    Сэрвісы, якіе выпалююць запускі за аднаковах кліяўцаў, часта вже маюць глобальныя ліміты паралельнасці для абэрнення небяспек. Їм таксама патрабуюцься бюджэты на кожную мету, каб список URL аднаго кліяўца не могаў монапалізаваць канкрэтны хост. Глобальныя, на аднаго аб’екта і на аднаго хоста — гэтыя ліміты складаюцься адна з іншай. Адкалікваўце іх як чыста выражаныя слоі, а не спадзяючыся, што справядліва черга будзе створвацца за дапамогою аднаго семафора.

    Калі адмініструемыя машыны значна разлічаюцца па часе адпаведзбы, баскаменты для розпадзелу задаў наклоняюцца да шырокаскорастай машыны. Такі наклон паслядзеюць для кэрыяткі ресурсаў, але шкодзіць медленай, строгай машыне, калі яе URL-адрэсы нарэшце стануць можлівымі да запуску. Ліміты на адную машыну скарочваюць шкоду; неабяжныя вагі для кожной машыны можаюць дапамогчы выражыць правілы вважлівасці.

    Інтэрпретацыя рэзультатаў проксі без магічных выкладак

    Якщо прымітны выход не ўдаецца, а выход чераз проксі успевае за ідэнтычных настройках баскаменту, магчыма, пункт прызначэння адбірае рашэнні на адвярсе на ідэнтычнасць сеті. Гэта корыстная практычная інформацыя. Гэта не ўскладненне, што змянілася фізыка частоты запуску. За проксіямі вам яшчэ трэба логаваць запускі па кожнай ідэнтычнасці выходу і па кожной цэльовай машыне. Аднак якщо гэта не зрабіць, вы проста перамешчаеце слепую пляму.

    Палітры правіл са адпаведнае дзеянне і роботы застаюцца вашай адпаведнае дагадкай. Вышэйшыя загальныя показнікі працяздатнасці через многа выходы падвайшваюць радіус уражэння логічных бягаў. Регулюванне швайнасці функцый і ліміты на адного хоста дзеяўць нават калі ўвёраны проксі, тады вы можете зменшыць ступень агрэсіўнасці без перапрацоўкі інфраструктуры айдэнтыкацыі.

    Закрыць цикл ад эксперыменту да стандартных настаўк

    Калі памеры пакажуць, што швайнасць запуску і максімумы на адного хоста краща прыводзяць да забаранень, чым сама глобальная велічына пула, тады неабходна закодаваць гэтыя нараджэнні як стандартныя настаўкі ў бібліятэцы кліента: выкарыстоўваць параметр RPS (або min-gap), задаць ліміт на адного хоста для режымаў з колькіма хостамі, а таксама экспортуваць показнікі для обох. Дакументацыя должна паказваць некоректную панель керування (зростаючыя значэнні completed req/s пад час спаду ok) разам з правильной. Навчанне пра способы абякання запобегае таму, каб наступная команда “вылечыла” проблему са адночаснасцю, чым спрычыніла тыхае перыванне корисных дадзеных.

    Чыстая рээксперыментаванне з эксперыментам працы выхаджэння

    Застаўце конкрэтныя версіі Pin Node і undici (альбо вашага HTTP стаку), каб практыка аб’еднання з’яўленняў залічвалася пахожай. Час адбыцца спрабаў падтрымкі, сэродзеўных браузеру, выключыце пад час адбыцца спрабаў. Ачысціце кэш DNS между працаваннем без посередніка і з посереднікам, якщо ваш прыстрой для тэставання разным чынам распрацоўвае хосты. Запісвайце час ад початку да канца для всей пачкі, а таксама часы запуску і завершэння кожнага запиту, ўпрымкі, каб можна было аналізаваць запыткі пры першых паўсекундзе — таму, дзе кліенты з аб’еднанням выглядаюць ідэнтычныя, незалежна ад стабільнага роўня канкурэнцыі, які, як вы смярдзіце, быў установлены.

    Пад час стварэння графіка завжды паказвайце колькість успешных запыткаў разам з колькасцю завершаных запыткаў/секунду. Графік з двумя восьмамі, які маскіруе колькість успешных запыткаў, — гэта спосаб, яким марнаваныя показнікі выграюць споры. Экспортуйце CSV з прыстрою для тэставання, каб іншыя моглі пераскладзіць даны без павернення ў спрабах.

    Інтэрпретаванне строгасці у стыле Arch Wiki

    Сервары для публічнай документацыі разнаюцца: якія-то обмежваюць працэю па IP-адрэсах і шляхах, якія-то — па User-Agent, якія-то — па канектаціях адночасна, якія-то — па частоте запыткаў у працуючых вакнах. 429-я памылка сёньдзе можа стаць менш выражаным споваленнем завтра, калі зменяецца політыка аператара. Таму цыфры ў стацыі ёсць толькі ілюстратывальнымі прыкладамі, а не вечнымі сталямі. Гэта, што ўсё роўна застаецца, — гэта методалогія: выдзельваеце розныя показнікі — размер басэна, шчытаўку запыткаў і максімумы на кожны сервер, а потым зменяеце адну зменную за раз.

    Якщо вы викорыстаеце свой сувёршана строгі сервер, трэба ў той жа прыем эксперыменту застаўляць сервер з менш строгім кантролем. Калі кантрольны сервер не працюе, ваш кліент таксама не будзе працаваць. Калі не працюе толькі строгі сервер, вы можаце аналізаваць, як іхня політыка вялоўна паўтараецца пад час вашага графіка.

    Деталі рэалізацыі ліміту начальной шчытаўкі

    Мінімальны прыем, вылічаны з максимальной колькасці запыткаў за секунду, ёсць простым і эфектывным рашэнням для кліентаў з аднам процесам. Кошкі токенаў дазваляюць короткія спалахі запыткаў, адночасна прабачаючы довгатраўнія среднія значэння — гэта корыстна, калі хочаце швайнах інтэрактыўных запыткаў, але таксама адпаведальных масовых сканаванняў. Кошкі з выцэчамі спрыяюць болейшай роўнасці. Які бы алгорытм вы не выбралі, прыменяйце яго да пачатку запыткаў, уключаючы праказы. Напор праказ, які амаль не прыводзіцься пад контроль, зноў стварае ситуацыю, падобную да той, якая была ў момент t=0 пасля першага забаранення.

    Многапроцесовыя сканеры патрабуюць распадзеленага замка дазволу (Redis, etcd або цэнтральны раскладчык). Толькі локальныя прыемы не зможу координаваць пяць працоўнікаў, кожны з якіх думае, што можа выканаць два запыткі за секунду.

    Деталі рэалізацыі ліміту на аднаго хоста

    Звычным патэрнам являюцца вкладзеныя семафоры, прыязваныя паведамленням хоста: спачатку захопляецца глобальны семафор, потым — семафор хоста, пасля чаго выконваецца запытка, а ў зворачным порядку — ўзвольненне ресурсаў. Паказваць, чыя www і apex адналежаць да аднаго ключа. Неабяжна вырашыць, як перэнаправленняя, якія зменшаюць колькасць хостаў, падчыняюцца лімітам. Шаркі таго ж сайту, заснованыя на паце, зазвычай яшчэ дзеліць аднаковы бюджет хоста, якщо толькі няма чынных доказаў ад CDN пра іншае.

    Выдаць метрыкі: inflight_global, inflight_per_host{host}, admissions_per_second, http_429_total{host}. Адмаўляць паведамленні, калі рэштка ліміту 429 падыходзіць да канца, а не толькі калі выкарыстоўваецца ліміт на памилкі 5xx.

    Парадакт у чергах у продакшн-скедуляроў

    Парадакт схемы сайта, алгорытм BFS з гэтаго «насення», калекулкі прыоритэта для «важлівых» URL-адрэсаў і калекулкі для павторных спроб усе гэта перакраявае максімумы навантажэння на кожны хост. Калекулка для павторных спроб, якая ставіць у пачатак список неудачных Arch-URL-адрэсаў, можа случайна зноў стварыць пэракрантаванне блакоў пасля частковага перыяву. Справядлівае распадзеленне у запятах між хостамі — калекулкі прыоритэта у формате round-robin для кожнага хоста — зменшае случайную концентрацію навантажэння ўсё раней, чым наступаюць жорсткія ліміты. Жорсткія ліміты заставаюцца неабходнымі, калі сама справядлівасць не можа обмежыць максімумы навантажэння пад асамацельным часу адпаведзення.

    Проксі без самахамання

    Домашнія сеті зменяюць распадзеленне ідэнтычнасцей. Але яны не скасоўвают законамі фізыкі: якщо кожная ідэнтычнасць усё равно праганяе п’ятдесят запытаў адразу, то серверы, якія вырашаюць пра доступ на адпаведнасць да падзеяў, а не толькі IP-адрэса, можа ўсё равно забаніць доступ. Хроніруйце запыты па кожнай ідэнтычнасці выходу. Адменавацыйна зміняйце іх адзін за другім. Следавайце правілам для роботаў і умовам контракту. Вярнавайцеся да адмеркаванага тэнара нават тады, калі праксі ўвёраны, каб баг не могаў распрасцірацца на вялікі радыус.

    Проксі-серверы датацэнтраў ёсць дешавейшыя і лёгкія да аўтентыфікацыі; проксі для домашніх вычынакоў ёсць дорожэйшыя і маюць этычныя проблемы. Выбірайце ўважна; не вважайце «проксі» сынонімам слова «радчы».

    Ад эксперыменту да стандартных настаўкі бібліятэкі

    Убудуйце два неабходныя параметры ў кэшэруючыя оберткі HTTP-кліентаў, якія викорыстоўваюцься краулерамі: maxInFlight і maxStartsPerSecond, а таксама maxInFlightPerHost, калі єсць больш ад однага хоста. Абмовіцеся ад стварэння кліента для режыму з колькіма хостамі без ліміту на кожнага хоста. Прадастыце шаблоны панелі керування, якія відображаюць колькісць успешных запыткаў за секунду. Навчайце працэўнікам на адной часовой шкале: паралельнае відвядзанне 10 запыткаў даходзіць да высокага розміру пропускной здатнасі, але водночас губяцца корыстныя сторанкі.

    Расширэны список пераконтраць

    • Установіце ліміт на запускі, а не толькі на актыўныя запыткі.
    • Установіце ліміт на кожнага хоста ў межах глобальнага пула.
    • Звярняйце увагу на колькісць запыткаў, якія прыймаюцца, і на максімальныя показнікі за кожнага хоста пасля кожнага запуску.
  • Ацэнаваець успех па базе корыстных стораначак, а не па колькасці завершэнных супрацоўкаў.
  • Застаўляць кантроль прыпуску да павторных спробах.
  • У сумешаных тэстах выкорыстоўваць лёгкія правілы кантролю.
  • Успех праексі спрацоўкі расследжваць як змяну репутацыі, а не як доказ таго, што планаванне працы ў стане.
  • Перазьвяртатыся да цифраў, калі змянююцца правілы парадоксу; застаўляць тую ж методыку.
  • Даколі гэтыя прывычкі не стануць неразлучнымі, каманды будуць продаваляць “вылечэнне канкурэнтнасці” ў тых падступных формах абяканняў, якія ўсё раве вяртаюць HTTP 429 і продаюць бюджэты краўлення.