ProHoster > وبلاگ > اداره > SRE: تجزیه و تحلیل عملکرد. روش پیکربندی با استفاده از یک وب سرور ساده در Go
SRE: تجزیه و تحلیل عملکرد. روش پیکربندی با استفاده از یک وب سرور ساده در Go
تجزیه و تحلیل و تنظیم عملکرد یک ابزار قدرتمند برای تأیید انطباق عملکرد برای مشتریان است.
تجزیه و تحلیل عملکرد را می توان برای بررسی تنگناها در یک برنامه با استفاده از یک رویکرد علمی برای آزمایش آزمایش های تنظیم استفاده کرد. این مقاله یک رویکرد کلی برای تجزیه و تحلیل عملکرد و تنظیم، با استفاده از یک وب سرور Go به عنوان مثال تعریف می کند.
Go به خصوص در اینجا خوب است زیرا ابزارهای پروفایل دارد pprof در کتابخانه استاندارد
استراتژی
بیایید یک لیست خلاصه برای تحلیل ساختاری خود ایجاد کنیم. ما سعی خواهیم کرد به جای ایجاد تغییرات بر اساس شهود یا حدس و گمان، از برخی داده ها برای تصمیم گیری استفاده کنیم. برای انجام این کار ما این کار را انجام خواهیم داد:
ما مرزهای بهینه سازی (الزامات) را تعیین می کنیم.
ما بار تراکنش را برای سیستم محاسبه می کنیم.
ما آزمایش را انجام می دهیم (داده ایجاد می کنیم).
مشاهده می کنیم؛
ما تجزیه و تحلیل می کنیم - آیا همه الزامات برآورده شده است؟
ما آن را به صورت علمی تنظیم کردیم، یک فرضیه ایجاد کردیم.
ما آزمایشی را برای آزمایش این فرضیه انجام می دهیم.
معماری ساده سرور HTTP
برای این مقاله از یک سرور HTTP کوچک در Golang استفاده خواهیم کرد. همه کدهای این مقاله را می توان یافت اینجا.
برنامه مورد تجزیه و تحلیل یک سرور HTTP است که Postgresql را برای هر درخواست نظرسنجی می کند. علاوه بر این، Prometheus، node_exporter و Grafana برای جمع آوری و نمایش معیارهای برنامه و سیستم وجود دارد.
برای ساده کردن، در نظر می گیریم که برای مقیاس افقی (و ساده کردن محاسبات) هر سرویس و پایگاه داده با هم مستقر می شوند:
تعریف اهداف
در این مرحله ما در مورد هدف تصمیم می گیریم. چه چیزی را می خواهیم تحلیل کنیم؟ چگونه بفهمیم که زمان پایان آن فرا رسیده است؟ در این مقاله تصور می کنیم که مشتری داریم و سرویس ما در هر ثانیه 10 درخواست را پردازش می کند.
В کتاب Google SRE روش های انتخاب و مدل سازی به تفصیل مورد بحث قرار گرفته است. بیایید همین کار را انجام دهیم و مدل هایی بسازیم:
تأخیر: 99 درصد درخواست ها باید در کمتر از 60 میلی ثانیه تکمیل شوند.
هزینه: سرویس باید حداقل مقدار پولی را مصرف کند که ما فکر می کنیم به طور منطقی ممکن است. برای انجام این کار، ما توان عملیاتی را به حداکثر میرسانیم.
برنامه ریزی ظرفیت: نیاز به درک و مستندسازی چند نمونه از برنامه کاربردی برای اجرا دارد، از جمله عملکرد مقیاس کلی، و چند نمونه برای برآورده کردن بار اولیه و الزامات تدارک مورد نیاز است. افزونگی n+1.
تأخیر ممکن است علاوه بر تجزیه و تحلیل نیاز به بهینه سازی داشته باشد، اما توان عملیاتی به وضوح نیاز به تجزیه و تحلیل دارد. هنگام استفاده از فرآیند SRE SLO، درخواست تاخیر از سوی مشتری یا کسبوکار که توسط مالک محصول ارائه میشود، ارسال میشود. و سرویس ما از همان ابتدا بدون هیچ تنظیماتی این تعهد را انجام خواهد داد!
راه اندازی محیط تست
با کمک یک محیط تست، ما قادر خواهیم بود یک بار اندازه گیری شده را روی سیستم خود قرار دهیم. برای تجزیه و تحلیل، داده هایی در مورد عملکرد وب سرویس تولید خواهد شد.
بار تراکنش
این محیط استفاده می کند گیاهی برای ایجاد نرخ درخواست HTTP سفارشی تا زمانی که متوقف شود:
$ make load-test LOAD_TEST_RATE=50
echo "POST http://localhost:8080" | vegeta attack -body tests/fixtures/age_no_match.json -rate=50 -duration=0 | tee results.bin | vegeta report
مشاهده
بار تراکنش در زمان اجرا اعمال خواهد شد. علاوه بر معیارهای برنامه (تعداد درخواستها، تأخیر پاسخ) و سیستم عامل (حافظه، CPU، IOPS)، پروفایلسازی برنامه اجرا میشود تا بفهمیم کجا مشکل دارد و زمان CPU چگونه مصرف میشود.
پروفایل کردن
نمایه سازی نوعی اندازه گیری است که به شما امکان می دهد زمانی که یک برنامه در حال اجرا است، زمان CPU را ببینید. این به شما امکان می دهد دقیقاً تعیین کنید که در کجا و چه مقدار از زمان پردازنده صرف شده است:
این داده ها را می توان در طول تجزیه و تحلیل برای به دست آوردن بینش در مورد زمان تلف شده CPU و کارهای غیر ضروری در حال انجام استفاده کرد. Go (pprof) می تواند پروفایل ها را تولید کند و با استفاده از مجموعه ای استاندارد از ابزار، آنها را به صورت نمودارهای شعله تجسم کند. من در مورد راهنمای استفاده و راه اندازی آنها بعداً در مقاله صحبت خواهم کرد.
اجرا، مشاهده، تجزیه و تحلیل.
بیایید یک آزمایش انجام دهیم. تا زمانی که از عملکرد راضی باشیم اجرا، مشاهده و تحلیل خواهیم کرد. اجازه دهید یک مقدار بار کم دلخواه را برای اعمال آن برای به دست آوردن نتایج مشاهدات اول انتخاب کنیم. در هر مرحله بعدی، بار را با یک ضریب پوسته پوسته شدن خاص که با مقداری تغییر انتخاب شده است، افزایش خواهیم داد. هر بار آزمایش بار با تعداد درخواست های تنظیم شده انجام می شود: make load-test LOAD_TEST_RATE=X.
50 درخواست در ثانیه
به دو نمودار بالا دقت کنید. بالا سمت چپ نشان می دهد که برنامه ما 50 درخواست در ثانیه را پردازش می کند (فکر می کند) و سمت راست بالا مدت زمان هر درخواست را نشان می دهد. هر دو پارامتر به ما کمک می کنند ببینیم و تجزیه و تحلیل کنیم که آیا در محدوده عملکرد خود هستیم یا نه. خط قرمز روی نمودار تأخیر درخواست HTTP SLO را در 60 میلی ثانیه نشان می دهد. خط نشان می دهد که ما بسیار کمتر از حداکثر زمان پاسخگویی خود هستیم.
بیایید به جنبه هزینه نگاه کنیم:
10000 درخواست در ثانیه / 50 درخواست در هر سرور = 200 سرور + 1
ما هنوز هم می توانیم این رقم را بهبود ببخشیم.
500 درخواست در ثانیه
وقتی بار به 500 درخواست در ثانیه می رسد، چیزهای جالب تری شروع می شود:
باز هم در نمودار بالا سمت چپ می بینید که برنامه در حال ضبط بار عادی است. اگر اینطور نیست، مشکلی در سروری که برنامه روی آن اجرا می شود وجود دارد. نمودار تأخیر پاسخ در بالا سمت راست قرار دارد و نشان میدهد که 500 درخواست در ثانیه منجر به تأخیر پاسخ 25 تا 40 میلیثانیه میشود. صدک 99 همچنان به خوبی در 60 میلی ثانیه SLO انتخاب شده در بالا قرار می گیرد.
از نظر هزینه:
10000 درخواست در ثانیه / 500 درخواست در هر سرور = 20 سرور + 1
همه چیز هنوز قابل بهبود است.
1000 درخواست در ثانیه
راه اندازی عالی! این برنامه نشان می دهد که 1000 درخواست در ثانیه را پردازش کرده است، اما محدودیت تاخیر توسط SLO نقض شده است. این را می توان در خط p99 در نمودار بالا سمت راست مشاهده کرد. علیرغم این واقعیت که خط p100 بسیار بالاتر است، تاخیرهای واقعی بیشتر از حداکثر 60 میلی ثانیه است. بیایید به نمایه سازی بپردازیم تا دریابیم که برنامه در واقع چه کاری انجام می دهد.
پروفایل کردن
برای پروفایل، بار را روی 1000 درخواست در ثانیه تنظیم می کنیم، سپس استفاده می کنیم pprof برای گرفتن داده ها برای یافتن اینکه برنامه زمان CPU را کجا می گذراند. این را می توان با فعال کردن نقطه پایانی HTTP انجام داد pprofو سپس تحت بارگذاری، نتایج را با استفاده از curl ذخیره کنید:
$ go tool pprof -http=:12345 cpu.1000_reqs_sec_no_optimizations.prof
نمودار نشان می دهد که برنامه در کجا و چقدر زمان CPU را صرف می کند. از توضیحات از برندان گرگ:
محور X جمعیت پروفایل پشته است که بر اساس حروف الفبا مرتب شده است (این زمان نیست)، محور Y عمق پشته را نشان می دهد و از صفر در [بالا] شمارش می شود. هر مستطیل یک قاب پشته است. هرچه قاب پهن تر باشد، بیشتر در پشته ها وجود دارد. آنچه در بالا است روی CPU اجرا می شود و آنچه در زیر آمده است عناصر فرزند هستند. رنگها معمولاً معنایی ندارند، اما بهطور تصادفی انتخاب میشوند تا قابها را متمایز کنند.
تجزیه و تحلیل - فرضیه
برای تنظیم، ما بر تلاش برای یافتن زمان تلف شده CPU تمرکز خواهیم کرد. ما به دنبال بزرگترین منابع هزینه های بیهوده خواهیم بود و آنها را حذف خواهیم کرد. خوب، با توجه به اینکه نمایه سازی بسیار دقیق نشان می دهد که برنامه دقیقاً زمان پردازنده خود را کجا می گذراند، ممکن است مجبور شوید چندین بار این کار را انجام دهید و همچنین باید کد منبع برنامه را تغییر دهید، آزمایش ها را مجدداً اجرا کنید و ببینید که عملکرد به هدف نزدیک می شود.
با توجه به توصیه های برندان گرگ، نمودار را از بالا به پایین می خوانیم. هر خط یک قاب پشته ای (تماس تابع) را نمایش می دهد. خط اول نقطه ورود به برنامه است، والد همه تماس های دیگر (به عبارت دیگر، همه تماس های دیگر آن را در پشته خود خواهند داشت). خط بعدی قبلاً متفاوت است:
اگر مکان نما را روی نام یک تابع در نمودار نگه دارید، کل زمان آن در پشته در هنگام اشکال زدایی نمایش داده می شود. تابع HTTPServe در 65 درصد مواقع وجود داشت، سایر توابع زمان اجرا runtime.mcall, mstart и gc، بقیه زمان را گرفت. واقعیت جالب: 5٪ از کل زمان صرف پرس و جوهای DNS می شود:
آدرس هایی که برنامه به دنبال آن است متعلق به Postgresql است. را کلیک کنید FindByAge:
جالب توجه است که این برنامه نشان می دهد که در اصل، سه منبع اصلی وجود دارد که تاخیر را اضافه می کند: باز کردن و بستن اتصالات، درخواست داده و اتصال به پایگاه داده. نمودار نشان می دهد که درخواست های DNS، باز کردن و بستن اتصالات حدود 13 درصد از کل زمان اجرا را به خود اختصاص می دهند.
فرضیه: استفاده مجدد از اتصالات با استفاده از ادغام باید زمان یک درخواست HTTP منفرد را کاهش دهد و به توان عملیاتی بالاتر و تاخیر کمتری اجازه دهد..
راه اندازی برنامه - آزمایش
ما کد منبع را به روز می کنیم، سعی می کنیم برای هر درخواست اتصال به Postgresql را حذف کنیم. اولین گزینه استفاده است استخر اتصال در سطح برنامه در این آزمایش ما بیایید آن را تنظیم کنیم ادغام اتصال با استفاده از درایور sql for go:
پس از شروع مجدد تست با 1000 درخواست در ثانیه، مشخص است که سطوح تاخیر p99 با SLO 60 میلیثانیه به حالت عادی بازگشته است!
هزینه اش چقدر است؟
10000 درخواست در ثانیه / 1000 درخواست در هر سرور = 10 سرور + 1
بیایید آن را حتی بهتر انجام دهیم!
2000 درخواست در ثانیه
دوبرابر کردن بار همان چیزی را نشان می دهد، نمودار بالا سمت چپ نشان می دهد که برنامه موفق به پردازش 2000 درخواست در ثانیه می شود، p100 کمتر از 60ms است، p99 SLO را برآورده می کند.
از نظر هزینه:
10000 درخواست در ثانیه / 2000 درخواست در هر سرور = 5 سرور + 1
3000 درخواست در ثانیه
در اینجا برنامه می تواند 3000 درخواست را با تاخیر p99 کمتر از 60 میلی ثانیه پردازش کند. SLO نقض نمی شود و هزینه به شرح زیر پذیرفته می شود:
10000 درخواست در ثانیه / در هر 3000 درخواست در هر سرور = 4 سرور + 1 (نویسنده جمع کرده است، تقریبا مترجم)
بیایید دور دیگری از تحلیل را امتحان کنیم.
تجزیه و تحلیل - فرضیه
ما نتایج اشکال زدایی برنامه را با 3000 درخواست در ثانیه جمع آوری و نمایش می دهیم:
هنوز 6 درصد از زمان صرف ایجاد ارتباطات می شود. راهاندازی استخر عملکرد را بهبود بخشیده است، اما همچنان میتوانید ببینید که برنامه به کار بر روی ایجاد اتصالات جدید به پایگاه داده ادامه میدهد.
فرضیه: اتصالات، علیرغم وجود استخر، همچنان حذف و پاک می شوند، بنابراین برنامه باید آنها را بازنشانی کند. تنظیم تعداد اتصالات معلق به اندازه استخر باید با به حداقل رساندن زمانی که برنامه برای ایجاد یک اتصال صرف می کند، به تأخیر کمک کند..
راه اندازی برنامه - آزمایش
در حال تلاش برای نصب MaxIdleConns برابر با اندازه استخر (همچنین شرح داده شده است اینجا):
بررسی نمودار شعله نشان می دهد که اتصال دیگر قابل توجه نیست! بیایید با جزئیات بیشتر بررسی کنیم pg(*conn).query - ما همچنین متوجه برقراری ارتباط در اینجا نمی شویم.
نتیجه
تجزیه و تحلیل عملکرد برای درک اینکه انتظارات مشتری و الزامات غیرعملکردی برآورده می شوند بسیار مهم است. تجزیه و تحلیل با مقایسه مشاهدات با انتظارات مشتری می تواند به تعیین اینکه چه چیزی قابل قبول است و چه چیزی قابل قبول نیست کمک کند. Go ابزارهای قدرتمندی را ارائه می دهد که در کتابخانه استاندارد تعبیه شده است که تجزیه و تحلیل را ساده و در دسترس می کند.