chat တစ်ခုက ကျွန်တော်တို့ API ကို ဘယ်လို ပိတ်နိုင်လဲ
စက်တင်ဘာ 28 မှာ release တစ်ခုပြီးနောက် ~17 မိနစ်အကြာ ကျွန်တော်တို့ production API ဆာဗာနှစ်လုံးစလုံး တစ်ပြိုင်တည်း memory ကုန်သွားပြီး restart ဖြစ်ခဲ့ပါတယ်။ ~5 မိနစ်ခန့် load balancer မှာ traffic ပို့စရာ healthy ဆာဗာ မရှိခဲ့ပါဘူး။ ပထမ ပြင်ဆင်ချက်အနေနဲ့ API ကို memory နှစ်ဆ ပေးခဲ့ပါတယ်။ အမှန်တကယ် အကြောင်းရင်းကတော့ နေ့ကျမှ တွေ့ခဲ့ပါတယ်– chat တစ်ခုကို ဖွင့်တဲ့အခါ API က မက်ဆေ့ချ် 53 MB ကို request တစ်ခုတည်းနဲ့ load ခိုင်းခဲ့ပါတယ်။ ယခု chat history ကို အရေအတွက်နဲ့သာမက အရွယ်အစားနဲ့ပါ ကန့်သတ်ထားတဲ့ စာမျက်နှာတွေနဲ့ load လုပ်ပြီး၊ အဲဒီ chat က crash မဖြစ်ဘဲ 5 MB ပထမစာမျက်နှာနဲ့ ဖွင့်ပါတယ်။
ဘာတွေ ပျက်သွားလဲ
ကျွန်တော်တို့ API က load balancer နောက်က ဆာဗာနှစ်လုံးစီပေါ်မှာ container တစ်ခုအနေနဲ့ run ပါတယ်။ container တစ်ခုစီမှာ memory ကန့်သတ်ချက် 384 MiB ရှိပါတယ်။ ငြိမ်နေချိန် 130–140 MiB သုံးတာမို့ ကန့်သတ်ချက်က နေရာလွတ် အများကြီး ရှိပုံရပါတယ်။
container နှစ်ခုစလုံး အဲဒီ ကန့်သတ်ချက်ကို တစ်ပြိုင်တည်း ရောက်ပြီး "JavaScript heap out of memory" နဲ့ crash ဖြစ်ပါတယ်။ heap ဆိုတာ Node.js process က object တွေ အလုပ်လုပ်ဖို့ သုံးတဲ့ memory ပါ။ ဆာဗာနှစ်လုံးစလုံး တစ်ပြိုင်တည်း ပျက်သွားလို့ request ပို့စရာ နေရာ မကျန်ပါဘူး။ ဆာဗာနှစ်လုံး ရှိတဲ့ စနစ်အတွက် ဒါက အဆိုးဆုံး outage ပုံစံ ဖြစ်ပါတယ်– redundancy က ပျက်ခြင်းတွေ တစ်ပြိုင်တည်း မဖြစ်မှသာ အကျိုးရှိပါတယ်။
ပထမ ပြင်ဆင်ချက်– နေရာ ပိုပေးခြင်း
အချိန်က deploy ကို ညွှန်ပြနေပါတယ်။ release ပြီးနောက် deploy က ရပ်သွားခဲ့တဲ့ agent turn တွေ ပြန်လည် run ပြီး transcript တွေ ပြန်သိမ်းပါတယ်။ အဲဒီ အလုပ် အရေအတွက် တက်လာတာက memory တက်ရတဲ့ ရှင်းရှင်း အကြောင်းရင်း ဖြစ်ပုံ ပေါ်ပါတယ်။
ဒါကြောင့် ပထမ ပြောင်းလဲမှုက API ရဲ့ ကန့်သတ်ချက်ကို 384 MiB ကနေ 768 MiB ထိ တိုးပေးခဲ့ပါတယ်။ ဆာဗာနှစ်လုံးပေါ်မှာ အဲဒီနေ့ live ပြင်ခဲ့ပြီး၊ နောက် deploy က 384 ကို တိတ်တဆိတ် ပြန်မထားအောင် deploy configuration ထဲ commit လုပ်ခဲ့ပါတယ်။ ဆာဗာပေါ်မှာ လက်နဲ့ ပြင်ထားတာကို နောက် deploy က ပြန်ပြောင်းပစ်ရင် တူညီတဲ့ outage ပြန်ဖြစ်တတ်တဲ့ အသိပညာပါ။
memory တိုးတာ ကောင်းတဲ့ အကာအကွယ် ဖြစ်ပေမယ့် ရှင်းပြချက် မဟုတ်ပါဘူး။
အမှန်တကယ် အကြောင်းရင်း– request တစ်ခု၊ 71 MB
နောက်ပိုင်းမှာ ပြဿနာကို chat တစ်ခု၏ မိတ္တူပေါ်မှာ ပြန်ဖန်တီးနိုင်ခဲ့ပါတယ်၊ production ရဲ့ ဘောင်ကန့်သတ်ချက်ဟောင်းကို သုံးပြီး။ မိတ္တူက deploy မပါဘဲ API ကို သူ့ဘာသာ crash ပြုလုပ်ခဲ့ပါတယ်။
ပရောဂျက်တစ်ခု ဖွင့်တဲ့အခါ web app က chat ရဲ့ history ကို API ဆီ တောင်းပါတယ်။ endpoint က နောက်ဆုံး မက်ဆေ့ချ် 30 ကို အပြည့်ပြန်ပေးပါတယ်။ လူအများစုရဲ့ chat အတွက် မက်ဆေ့ချ် 30 က သေးပါတယ်။ ဒီ chat အတွက်တော့ နောက်ဆုံး မက်ဆေ့ချ် 30 က database ထဲ 53 MB ရှိပြီး response 71 MB ဖြစ်ပါတယ်။ agent ရဲ့ ပြန်ကြားချက် အချို့ကတော့ တစ်ခုလျှင် 4–10 MB ရှိပြီး အများစုက sub-agent တွေရဲ့ transcript တွေပါ။ sub-agent ဆိုတာ main agent က တာဝန်တစ်စိတ်တစ်ပိုင်းကို တပြိုင်နက် လုပ်ဖို့ စတင်ထားတဲ့ အကူ agent တွေပါ၊ သူတို့ရဲ့ အလုပ်အပြည့်က ပြန်ကြားချက်နဲ့ အတူ သိမ်းထားပါတယ်။
အဲဒီ response တစ်ခုတည်း တည်ဆောက်ဖို့ API ရဲ့ heap ထက် ပိုလိုခဲ့ပါတယ်။ ပရောဂျက်တစ်ခု ဖွင့်တိုင်း သို့မဟုတ် refresh လုပ်တိုင်း request ပြန်ပို့ပါတယ်။ chat တစ်ခုတည်းက ဆာဗာ ဘယ်တစ်လုံးပေါ် ကျသွားတာမဆို ပိတ်နိုင်ပြီး၊ စာမျက်နှာကို reload လုပ်နိုင်လို့ ဆာဗာနှစ်လုံးလုံး ရောက်နိုင်ပါတယ်။
"မက်ဆေ့ချ် 30" ဟာ အရွယ်အစား ကန့်သတ်ချက် တစ်ခု မဟုတ်ခဲ့ပါဘူး၊ အရေအတွက် ကန့်သတ်ချက်သာ ဖြစ်ပြီး ပုံမှန် chat အတွက် သေးတာကြောင့်သာ ဖြစ်ခဲ့ပါတယ်။
ပြင်ဆင်ချက်– အရေအတွက်နဲ့ အရွယ်အစား နှစ်မျိုးလုံး ကန့်သတ်ထားတဲ့ စာမျက်နှာများ
အခု history စာမျက်နှာတစ်ခုသည် မက်ဆေ့ချ် 30 သို့မဟုတ် ~4 MB ဖြစ်ပြီး ဘယ်ဟာ ဦးစွာ ရောက်လာသလဲဆိုတာပေါ် မူတည်ပါတယ်။
အဆင့်နှစ်ဆင့်နဲ့ အလုပ်လုပ်ပါတယ်–
- အရွယ်အစားကို အရင် တောင်းပါ။ API က database ကို နောက်ဆုံး မက်ဆေ့ချ်တွေရဲ့ ID နဲ့ သိမ်းထားတဲ့ အရွယ်အစားကို အကြောင်းအရာမပါဘဲ မေးပါတယ်။ အဲဒီ query က မက်ဆေ့ချ်တွေ ဘယ်လောက်ကြီးကြီး သိပ်မကုန်ပါဘူး။
- ထိုက်တာကိုသာ load လုပ်ပါ။ အသစ်ဆုံးက အဟောင်းဆုံးဆီ သွားရင်း၊ နောက်တစ်ခုက စာမျက်နှာကို 4 MB ကျော်စေမယ်ဆိုရင် ရပ်ပါတယ်။ ထိုအတိုင်းသာ အပြည့် load လုပ်ပါတယ်။
ဘေးကင်းအောင် စည်းမျဉ်း နှစ်ခု ရှိပါတယ်–
- နောက်ဆုံး မက်ဆေ့ချ်က အရွယ်ဘယ်လောက်ပဲ ဖြစ်ဖြစ် စာမျက်နှာထဲ အမြဲ ပါပါတယ်။ စာမျက်နှာတစ်ခုက ဘာမှ ပြန်မပေးရင် chat က ရပ်သွားပြီး ပြန်ဆင်းလို့ မရတော့ပါ။
- ဘာမှ မဖြတ်ပါ။ မက်ဆေ့ချ်တစ်ခုမှ မဖြတ်ပါ၊ မပျောက်စေပါ။ chat ကျန်တာက ရှိပြီးသား "Scroll up for earlier messages" ခလုတ်နဲ့ စာမျက်နှာတစ်ခုစီ load ပါလိမ့်မယ်။
အလားတူ ပုံစံ နေရာတစ်ခု ထပ်တွေ့ခဲ့ပါတယ်။ turn ကို ရပ်တဲ့အခါ API က နောက်ဆုံး ပြန်ကြားချက် အနည်းငယ်ကို ဗလာဖြစ်လား စစ်ပြီး ဖယ်ရှားဖို့ လုပ်ပါတယ်။ အဲဒါကို မက်ဆေ့ချ် ရှစ်ခုကို အပြည့် load လုပ်ပြီး လုပ်ခဲ့ပါတယ်။ ပြန်ကြားချက် megabyte များစွာ ရှိတဲ့ chat မှာ ဒါက အသေးစား ပုံစံ တူညီတဲ့ ပြဿနာ ဖြစ်ပါတယ်။ အခု database ကို ဟုတ်/မဟုတ် မေးခွန်းတစ်ခုသာ မေးပါတယ်– ဒီမက်ဆေ့ချ်မှာ content တစ်ခုခု ရှိလား၊ content ကိုယ်တိုင် မတင်ဘဲ။
ဘယ်လို စမ်းသပ်ခဲ့လဲ
chat ရဲ့ မိတ္တူပေါ်မှာ၊ ဟောင်း 384 MiB ကန့်သတ်ချက်နဲ့ run ပြီး–
- ပထမ စာမျက်နှာက 5 MB။ ယခင် တူညီတဲ့ request က API ကို crash ဖြစ်စေခဲ့ပါတယ်။
- browser tab 5 ခု တစ်ပြိုင်တည်း chat ဖွင့်တဲ့အခါ memory အထွတ်အထိပ် 154 MB။
- chat တစ်ခုလုံးကို နောက်ပြန် scroll လုပ်တဲ့အခါ မက်ဆေ့ချ် 190 ခု အားလုံး တစ်ခါစီ၊ အစီအစဉ်အတိုင်း ပြန်ရပါတယ်။
စာမျက်နှာရွေးတဲ့ logic မှာလည်း unit test တွေ ရှိပြီး၊ အဲဒီ chat ရဲ့ နောက်ဆုံး မက်ဆေ့ချ်တွေရဲ့ အမှန်တကယ် အရွယ်တွေနဲ့ တည်ဆောက်ထားတဲ့ test ပါဝင်ပါတယ်။ ပထမ စာမျက်နှာက မက်ဆေ့ချ်တစ်ခု ပြန်ပေးပြီး ထပ်ရှိကြောင်း ပြောပြပြီး၊ နောက်စာမျက်နှာက ၎င်းရဲ့ နောက်တစ်ခုကနေ စတင်ပါတယ်။
ဒီကနေ ရလာတာတွေ
- အရေအတွက်က အရွယ်အစား ကန့်သတ်ချက် မဟုတ်ပါ။ အဆုံးမရှိ ကြီးလာနိုင်တဲ့ အရာရဲ့ "နောက်ဆုံး N" ကို ပြန်ပေးတဲ့ endpoint တိုင်းမှာ byte budget လည်း လိုပါတယ်။ ဒေတာက နောက်ဆုံးတော့ ကွာဟချက်ကို ရှာတွေ့ပါလိမ့်မယ်။
- လူသိများတဲ့ သံသယရှိသူက အမြဲ အကြောင်းရင်း မဟုတ်ပါ။ deploy က တကယ့် လှုံ့ဆော်ချက် ဖြစ်ပြီး memory တိုးတာ တန်ဖိုးရှိပါတယ်။ ဒါပေမယ့် deploy မပါဘဲ crash ပြန်ဖြစ်တာကြောင့် ပြန်ဖန်တီးမှ မဟုတ်ရင် memory တိုးတာနဲ့ရပ်ခဲ့မှာပါ။
- တူညီတဲ့ request ကို လက်ခံရင် ဆာဗာနှစ်လုံး တစ်ပြိုင်တည်း ပျက်ပါတယ်။ redundancy က ဆာဗာတစ်လုံး ပျက်တာကို ကာကွယ်ပေးပေမယ့်၊ ဆာဗာ ဘယ်တစ်လုံးရောက်ရောက် သတ်နိုင်တဲ့ request ကို ကာကွယ်မပေးပါ၊ အထူးသဖြင့် အသုံးပြုသူက refresh လုပ်ပြီး ထပ်ကြိုးစားတတ်တဲ့ request ဆိုရင် ပိုဆိုးပါတယ်။
- config မှာ ပြင်ပါ၊ box ပေါ်မှာသာ မပြင်ပါနဲ့။ memory တိုးတာကို အဲဒီနေ့ပဲ deploy configuration ထဲ ထည့်ထားလို့ နောက် deploy မှာ ပျောက်မသွားပါ။
ဒါက agent ရဲ့ output နဲ့ ပတ်သက်တဲ့ ကျွန်တော်တို့ မကြာသေးမီ memory ဇာတ်လမ်း ဒုတိယအကြိမ် ဖြစ်ပါတယ်။ ပထမတစ်ခုက strings 690 MB ကို queue လုပ်ခဲ့တဲ့ status label ဖြစ်ပါတယ်။ Mythex မှာ sub-agent တွေ သုံးချင်ရင် ဘယ်လို အလုပ်လုပ်လဲ docs မှာ ဖတ်နိုင်ပါတယ်။