એક ભારે ચેટ અમારા 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 ના હતા, મોટે ભાગે સબ-એજન્ટના ટ્રાન્સક્રિપ્ટ: હેલ્પર એજન્ટ જેને મુખ્ય એજન્ટ કામના એક ભાગ પર સમાંતર કામ કરવા શરૂ કરે છે, અને જેનું સંપૂર્ણ કામ જવાબ સાથે સાચવવામાં આવે છે.
તે એક રિસ્પોન્સ બનાવવામાં API પાસે જેટલી heap હતી તેના કરતાં વધુ લીધી. અને પ્રોજેક્ટ ખોલવા કે રિફ્રેશ કરવા દરેક વખતે એ રિક્વેસ્ટ ફરી મોકલાતી. એક ચેટ તે સર્વરને બંધ કરી શકતી જેના પર તે પહોંચતી, અને પેજ રિલોડ થઈ શકતું હોવાથી, તે બંને સુધી પહોંચી શકતી.
"30 messages" ક્યારેય કદ પર સાચી મર્યાદા નહોતી. તે ગણતરી પર મર્યાદા હતી, જે સામાન્ય ચેટ માટે સંયોગથી નાની હતી.
ઉકેલ: ગણતરી ઉપરાંત કદ પ્રમાણે મર્યાદિત પેજ
ઇતિહાસનું એક પેજ હવે 30 મેસેજ અથવા તેમાંના લગભગ 4 MB, જે પહેલાં આવે તે.
તે બે પગલામાં કામ કરે છે:
- પહેલાં કદ માંગો. API ડેટાબેઝને નવીનતમ મેસેજના IDs અને સંગ્રહેલા કદ માંગે છે, તેમની સામગ્રી વગર. એ ક્વેરી મેસેજ કેટલા પણ મોટા હોય તો પણ સસ્તી છે.
- ફિટ થાય તેટલું જ લોડ કરો. નવીનતમથી જૂની તરફ ચાલતાં, આગલો મેસેજ પેજને 4 MB થી આગળ ધકેલે ત્યાં સુધી મેસેજ ઉમેરે છે. પછી માત્ર તે જ રો આખી લોડ થાય છે.
બે નિયમ આને સુરક્ષિત રાખે છે:
- નવીનતમ મેસેજ હંમેશાં પેજ પર જાય છે, તેનું કદ ગમે તે હોય. જે પેજ કંઈ પાછું ન આપે તે ચેટને અટકાવી દે, પાછળ સ્ક્રોલ કરવાનો કોઈ રસ્તો ન રહે.
- કંઈ કાપવામાં આવતું નથી. કોઈ મેસેજ ટ્રંકેટ કે છોડવામાં આવતો નથી. બાકીની ચેટ "Scroll up for earlier messages" કંટ્રોલ દ્વારા લોડ થાય છે, જે જૂના મેસેજ પહેલાંથી વાપરતા હતા, એક સમયે એક પેજ.
અમને એ જ આકારની બીજી જગ્યા પણ મળી. જ્યારે તમે ટર્ન રોકો છો, ત્યારે API છેલ્લા થોડા જવાબો તપાસે છે કે કોઈ ખાલી તો નથી અને સાફ કરવા જેવા તો નથી. તે આ માટે આખા આઠ મેસેજ લોડ કરતું. મલ્ટી-MB જવાબોવાળી ચેટ પર, તે જ સમસ્યા નાના રૂપે છે. હવે તે ડેટાબેઝને હા-કે-ના પ્રશ્ન પૂછે છે: શું આ મેસેજમાં કોઈ સામગ્રી છે? સામગ્રી પોતે લોડ કર્યા વગર.
અમે તેને કેવી રીતે ચકાસ્યું
ચેટની નકલ પર, જૂની 384 MiB મર્યાદા સાથે ચાલતા:
- પહેલું પેજ 5 MB છે. પહેલાં, એ જ રિક્વેસ્ટ API ને ક્રેશ કરતી.
- એક સાથે પાંચ બ્રાઉઝર ટેબ ચેટ ખોલે ત્યારે મેમરી ટોચે 154 MB પહોંચે છે.
- આખી ચેટમાં પાછળ સ્ક્રોલ કરતાં બધા 190 મેસેજ પાછા આવે છે, દરેક એક જ વાર, ક્રમમાં.
પેજ પસંદગીના લોજિક પર યુનિટ ટેસ્ટ પણ છે, જેમાં એક ટેસ્ટ એ ચેટના નવીનતમ મેસેજના વાસ્તવિક કદ પરથી બનાવેલો છે. પહેલું પેજ એક મેસેજ પાછું આપે છે, કહે છે કે વધુ છે, અને આગલું પેજ તેના પછીના મેસેજથી શરૂ થાય છે.
અમે શું શીખ્યા
- ગણતરી એ કદની મર્યાદા નથી. કોઈપણ એન્ડપોઇન્ટ જે અમર્યાદિત રીતે વધી શકે તેવી વસ્તુનો "નવીનતમ N" પાછો આપે તેને બાઇટ બજેટની પણ જરૂર છે. ડેટા આખરે એ ગેપ શોધી કાઢશે.
- દેખીતું શંકાસ્પદ હંમેશાં કારણ હોતું નથી. ડિપ્લોય કેટલાક વધારાના કામનું વાસ્તવિક ટ્રિગર હતું, અને વધુ મેમરી મૂલ્યવાન હતી. પણ ક્રેશ ડિપ્લોય વગર પણ ફરીથી બન્યો, અને તેને ફરીથી બનાવ્યા વગર અમે મેમરી વધારા પર અટકી ગયા હોત.
- એક જ રિક્વેસ્ટ મળે ત્યારે બે સર્વર એક સાથે નિષ્ફળ જાય છે. રિડન્ડન્સી એક સર્વર મરી જાય ત્યારે રક્ષણ આપે છે. જે રિક્વેસ્ટ પહોંચે તે દરેક સર્વરને મારી નાખે, ખાસ કરીને જેને યુઝર રિફ્રેશ કરીને સ્વાભાવિક રીતે ફરી મોકલશે, તેની સામે તે રક્ષણ આપતું નથી.
- તેને ગોઠવણીમાં ઠીક કરો, માત્ર બોક્સ પર નહીં. મેમરી વધારો તે જ દિવસે ડિપ્લોય ગોઠવણીમાં ગયો, જેથી આગલા ડિપ્લોયે તેને જાળવી રાખ્યો.
આ અમારી એજન્ટ આઉટપુટને લગતી તાજેતરની બીજી મેમરી વાર્તા છે. પહેલી એક પ્રોગ્રેસ લેબલમાં 690 MB સ્ટ્રિંગ કતારમાં મૂકતી સ્ટેટસ લેબલ હતી. જો તમે Mythex પર સબ-એજન્ટનો ઉપયોગ કરો છો, તો તેઓ કેવી રીતે કામ કરે છે તે docs માં વાંચી શકો છો.