Блог

Како еден тежок разговор можеше да го сруши нашиот API

На 28 септември, околу 17 минути по едно издание, двата наши производствени API сервери истовремено останаа без меморија, се рестартираа, а околу пет минути балансерот на оптоварување немаше ниту еден здрав сервер до кој да испраќа сообраќај. Нашето прво решение на API-то му го удвои меморијата. Вистинската причина се појави подоцна истиот ден: отворањето на еден конкретен разговор го натера API-то да вчита 53 MB пораки во едно барање. Историјата на разговорите сега се вчитува по страници ограничени и по големина и по број, а тој разговор се отвора со прва страница од 5 MB наместо со пад.

Што падна

Нашето API работи како контејнер на секој од двата сервери зад балансер на оптоварување. Секој контејнер имаше ограничување на меморијата од 384 MiB. Во мирување користи 130–140 MiB, па ограничувањето изгледаше како доволно простор.

И двата контејнери го достигнаа ограничувањето истовремено и паднаа со „JavaScript heap out of memory“. Heap-от е меморијата што ја користи Node.js процесот за објектите со кои работи. Бидејќи двата сервери паднаа истовремено, немаше каде да се пренасочат барањата. Тоа е најлошиот вид прекин за поставка со два сервери: резервноста помага само кога дефектите не се случуваат во исто време.

Првото решение: повеќе простор

Времето укажуваше на издањето. По едно издание, агентските извршувања што беа прекинати од распоредувањето се продолжуваат и повторно ги зачувуваат своите транскрипти, а тој бран работа изгледаше како очигледен извор на скок во меморијата.

Затоа првата промена го подигна ограничувањето на API-то од 384 MiB на 768 MiB. Ја применивме во живо на двата сервери истиот ден и ја внесовме во конфигурацијата за распоредување, за следното распоредување тивко да не го врати на 384. Поправка направена рачно на сервер што следното распоредување ја поништува е вообичаен начин истиот прекин да се врати.

Повеќе меморија беше разумна безбедносна граница. Но не беше објаснување.

Вистинската причина: едно барање, 71 MB

Подоцна истиот ден го репродуциравме падот на копија од еден разговор, со старото ограничување на меморијата во продукција. Копијата сама го сруши API-то, без да има распоредување.

Кога отворате проект, веб-апликацијата бара од API-то историјата на разговорот. Крајната точка ги враќаше најновите 30 пораки, целосни. За повеќето разговори, 30 пораки е малку. За овој, најновите 30 пораки беа 53 MB во базата и одговор од 71 MB. Неколку од агентските одговори беа по 4–10 MB секој, главно транскрипти од под-агенти: помошните агенти што главниот агент ги стартува за да работат паралелно на дел од задача, а нивниот целосен труд се зачувува со одговорот.

Изградбата на тој еден одговор зеде повеќе heap од колку што API-то имаше. И секое отворање или освежување на тој проект го праќаше барањето повторно. Еден разговор можеше да го сруши секој сервер на кој ќе падне, а бидејќи страницата можеше да се презарди, можеше да стигне до двата.

„30 пораки“ никогаш не било вистинско ограничување на големината. Било ограничување на бројот, што случајно било мало за обични разговори.

Поправката: страници ограничени по големина и по број

Една страница од историјата сега има 30 пораки или околу 4 MB од нив, што ќе дојде прво.

Тоа работи во два чекора:

  1. Прво побарај големини. API-то од базата ги бара ИД-јата и зачуваните големини на најновите пораки, без нивните содржини. Тоа барање е евтино без оглед на тоа колку се големи пораките.
  2. Вчитај само што ќе стане. Одејќи од најновата кон најстарата, додава пораки додека следната не би ја пренела страницата над 4 MB. Потоа се вчитуваат целосно само тие редови.

Два правила ја одржуваат ова безбедно:

  • Најновата порака секогаш оди на страницата, без оглед на нејзината големина. Страница што ништо не враќа би го задржала разговорот заглавен, без начин да се врати наназад.
  • Ништо не се сече. Ниту една порака не се скратува и не се фрла. Остатокот од разговорот се вчитува преку контролата „Scroll up for earlier messages“ што ја користеа и постарите пораки, една страница по една.

Најдовме уште едно место со иста форма. Кога ќе прекинете еден тек, API-то ги проверува последните неколку одговори за да види дали некои се празни и треба да се исчистат. Тоа го правеше така што вчитуваше осум целосни пораки. Кај разговор со одговори од по неколку мегабајти, тоа е истиот проблем во помал облик. Сега му поставува на базата едно да-или-не прашање — дали оваа порака има содржина? — без да ја вчитува самата содржина.

Како го проверивме

На копијата од разговорот, со старото ограничување од 384 MiB:

  • Првата страница е 5 MB. Порано истото барање го сруши API-то.
  • Пет прозорци на прелистувачот што истовремено го отвораат разговорот достигнуваат врв од 154 MB меморија.
  • Враќањето наназад низ целиот разговор ги враќа сите 190 пораки, секоја точно еднаш, по редослед.

Логиката за избор на страници има и единечни тестови, вклучително и еден составен од вистинските големини на најновите пораки на тој разговор. Првата страница се враќа со една порака, јавува дека има уште, а следната страница почнува од следната.

Што научивме

  • Бројот не е ограничување на големината. Секоја крајна точка што враќа „најновите N“ од нешто што може да расте без граници треба и буџет во бајти. Податоците на крајот ќе ја најдат празнината.
  • Очигледниот осомничен не е секогаш причината. Распоредувањето беше вистински поттик за дополнителна работа, а повеќе меморија вреди. Но падот се репродуцираше без распоредување, а без репродукцијата би застанеле кај зголемувањето на меморијата.
  • Два сервери паѓаат заедно кога добиваат исто барање. Резервноста ве штити од тоа еден сервер да умре. Не ве штити од барање што го убива секој сервер на кој ќе стигне, особено кога корисникот природно ќе го повтори со освежување.
  • Поправете го во конфигурацијата, не само на серверот. Зголемувањето на меморијата влезе во конфигурацијата за распоредување истиот ден, па следното распоредување го задржа.

Ова е нашата втора неодамнешна приказна за меморија поврзана со излезот на агентот. Првата беше етикета за статус што ставаше во ред 690 MB стрингови. Ако користите под-агенти на Mythex, можете да прочитате како функционираат во документацијата.

Mythex · Pricing · Градете што било со AI · Шаблони за веб-страници и апликации · Mythex во споредба · Речник за градење апликации со AI · Бесплатни алатки за градење апликации со AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)