پیکربندی کافکا – پارامترهای مهم سیستم‌عامل

آپاچی کافکا یکی از پلتفرم‌هایی هست که برای موارد متنوعی از خزشگر موتور جستجو گرفته تا سیستم‌های تحلیل لاگ کاربرد خاص خودش رو داره. هدفم از این پست بیان چند مورد از پیکربندی‌های مربوط به سیستم عامل هست که می‌تونه اولین گام برای بهبود کارایی کافکا باشه. در اینده در مورد سایر پارامترها هم صحبت می‌کنیم.

صفحات کثیف!

سیستم‌عامل برای اینکه عملیات I/O رو بهتر انجام بده از حافظه اصلی با دسترسی تصادفی (RAM) استفاده می‌کنه و باعث می‌شه کارایی سیستم به شکل قابل توجهی برای بارکاری (workload) نوشتن بهبود پیدا کنه. وقتی شما در حال نوشتن بر روی دیسک هستید داده‌ها ابتدا در حافظه اصلی ذخیره و بعدا در زمانی مشخص روی دیسک ذخیره می‌شن. به این صفحات از حافظه که هنوز روی دیسک فلاش نشده‌‌ان صفحات کثیف گفته می‌شه.
دو مورد از پارامترهای مهمی که در کرنل لینوکس صفحات کثیف رو کنترل می‌کنن در زیر ذکر شده:

  • vm.dirty_ratio:

بیشترین مقداری از حافظه available که می‌تونه برای ذخیره‌سازی صفحات کثیف استفاده بشه. این مقدار به درصد بیان می‌شه. بعد از اینکه این حدآستانه فرا برسه پردازه‌ای که در حال نوشتن بوده بلاک می‌شه و منتظر خالی شدن می‌مونه.

  • vm.dirty_background_ratio

درصدی از حافظه رو تعیین می‌کنه که به محض رسیدن میزان صفحات کثیف به اون، ترد pdflush شروع به کار می‌کنه و صفحات کثیف رو بر روی دیسک می‌نویسه. این مقدار به درصد بیان می‌شه و پیش‌فرض این پارامتر ۱۰ ست. بنابراین کاهش این مقدار سبب می‌شه تا کرنل در بازه‌های زمانی کوتاه‌تری فلاش کنه و اگه اون رو به صفر برسونیم کارایی سیستم به شکل قابل توجهی کاهش پیدا می‌کنه.

خب حالا؟
با توجه به اینکه در کافکا دیسک نقش تعیین کننده‌ای در کارایی سیستم داره پیکربندی این پارامترها مهمه. تجربه ما ثابت کرده که dirty_ratio رو بهتره در حدود ۶۰ قرار بدیم. این مقدار رو می‌تونیم حتی در حد ۸۰ درصد هم ببریم ولی در کل هر چه این مقدار افزایش پیدا کنه داده‌های فلاش نشده افزایش پیدا می‌کنه و باعث میشه زمانی که سیستم عامل فلاش کردن رو force میکنه (یعنی synchronous) یک وقفه در سیستم اتفاق بیفته. از طرفی دیگه حتی زمانی که کافکا crash می‌کنه باعث از دست رفتن داده می‌شه که این رو می‌تونیم با استفاده از replication‌ حل کنیم. در مورد پارامتر dirty_background_ratio هم توصیه می‌کنیم اون رو به ۵ کاهش بدید.
برای اطلاعات بیشتر این راهنما رو بخونید.

بافر شبکه

کرنل لینوکس این قابلیت رو به ما میده که خیلی راحت اون رو برای موارد خاص پیکربندی کنیم. فراموش نکنید که کرنل لینوکس برای انتقال‌های سریع و حجیم از پیش پیکربندی نشده. به همین دلیل توصیه می‌کنم برای کافکا این تنظیمات رو متناسب با بار کاری خودتون تنظیم کنید. بنابراین با استفاده از پارامترهای net.core.wmem_default و net.core.rmem_default میزان بافر read/write سوکت‌های سیستم رو مشخص کنید. توصیه می‌کنم که برای این دو پارامتر مقدار ۱۳۱۰۷۲ (۱۲۸ کیلوبایت) رو در نظر بگیرید. علاوه بر این دو پارامتر .net.core.[r|w]mem_max هم داریم که حداکثر مقدار این بافرها رو مشخص می‌کنن که توصیه میشه اون رو به ۲۰۹۷۱۵۲ (۲ مگابایت) مقدار دهی کنید.
علاوه بر این پارامترها، دو پارامتر net.ipv4.tcp_[w/r]mem هم برای تنظیمات tcp وجود داره که باید متناسب با بارکاری تغییر پیدا کنن. این دو پارامتر هر کدام ۳ مقدار min|default|max دارن که اولی حداقل میزان بافر و دومی مقدار پیش‌فرض و سومی حداکثر مقدار رو تعیین می‌کنه. این پارامترها رو با مقادیر ۴کیلوبایت (حداقل) ، ۶۴کیلوبایت(پیش‌فرض) و ۲ مگابایت (حداکثر) مقدار دهی کنید.

حافظه مجازی

در مرحله اول روی هر سرویس‌دهنده‌ای توصیه می‌کنم swap رو غیر فعال کنید چون اگر به هر دلیلی برنامه شما نیاز به حافظه بیشتر داشته باشه و از swap استفاده کنه به شدت کارایی‌ش رو از دست می‌ده. اگر اصرار بر این دارید که از swap استفاده کنید توصیه می‌کنم پارامتر vm.swappiness رو به یک مقدار کم (مثلا ۱) مقدار دهی کنید. از مقدار صفر استفاده نکنید مگر اینکه دقیقا کرنلی که استفاده می‌کنید رو بشناسید. در گذشته مقدار صفر باعث می‌شد فقط در زمانی که outOfMemory اتفاق می‌افتاد از swap استفاده بشه ولی در حال حاضر معمولا مقدار صفر باعث میشه که هیچ وقت swap استفاده نشه.

دیسک

برای دیسک تنظیمات خاصی لازم نیست انجام بدید فقط حتما برای moun point دیسک از noatime استفاده کنید چون درغیر این‌صورت باعث می‌شه بعد از هر بار read هم زمان دستیابی فایل‌ها تغییر کنه که به این معنی یک write هست. این مشکل در دیسک‌های ssd هم خودش رو به شکلی دیگه نشون می‌ده که کم شدن عمر ssd هست.

صدک ۹۹ام تاخیر

یکی از مشکلاتی که توی بیان کارایی سیستم توزیع شده داریم بحث زمان پاسخ یا همون response time هستش و برای اینکه کمی با این بحث و اهمیتش آشنا بشیم من این متن رو اینجا می‌نویسم.
همه می‌دونیم تأخیر در سیستم‌های کامپیوتری یعنی مدت زمانی که یک پردازه دستورالعمل‌های خودش رو انجام میده و خاتمه پیدا میکنه. روش‌های متفاوتی مثل میانه، میانگین و صدک‌ها برای اندازه‌گیری تأخیر توی این سیستم‌ها مطرح می‌شن. اما بایستی ببینیم واقعاً این معیارها برای اندازه‌گیری زمان پاسخ مناسب هستند؟
دو معیار اول یا همون معیارهای میانگین و میانه روش‌های مناسبی برای توصیف طول تأخیر سیستم‌های کامپیوتری نیستن! چون این روش‌ها بدترین حالت‌ها (زمان پاسخ‌های طولانی) رو توی خودشون محو می‌کنن و ابزارهای مانیتورینگی که بر این مبنا تأخیر رو محاسبه می‌کنن قادر به تشخیص موارد خاص نیستند. اگه واضح‌تر بخوام بگم فرض کنید ۲۰ تا درخواست به سیستم وارد شدن و زمان پاسخ اون‌ها بر حسب میلی‌ثانیه به شکل زیر هستش:

۱ ، ۱ ، ۱، ۱ ، ۲ ، ۲ ، ۲ ، ۳ ،۳ ، ۳ ، ۳ ، ۳ ، ۴ ، ۴ ، ۴ ، ۴ ، ۴ ، ۵ ، ۱۵ ، ۱۶

خب اگه بخواییم میانگین زمان پاسخ رو حساب کنیم میشه حدود ۴ میلی ثانیه و ما هم خیلی خوشحالیم! اما واقعیتش اینه که دو تا زمان پاسخ خیلی بد داشتیم که یطورایی توی نتیجه کلی محو شدن و اثری ازشون دیده نمیشه!
اگه در مقیاس وسیع نگاه کنید یک درصد چیز کمی نیست. ممکنه ۱۰۰۰ تا درخواست (کاربر) با تأخیر زیاد مواجه بشن و در نتیجه کسی از سیستم ما راضی نباشه و سراغ یک جایگزین بهتر بره (:

شاید این بحث روی نمودار جالبتر باشه. توی نمودار زیر به طور میانگین زمان پاسخ در حدود ۵۰ میلی ثانیه است و توی مواردی نادر به۱۰۰ میلی ثانیه می‌رسه.

نمودار میانه و میانگین

همونطور که می‌بینید این نمودار در بدترین حالت (تأخیر زیاد) توانایی نمایش تاخیر سیستم رو نداره.
حالا وضعیت سیستم رو با استفاده از یک معیار دیگه به نام صدک بررسی می‌کنیم. اینم بگم که ما انواع مختلفی از صدک داریم که توی نمودار زیر فقط صدک ۹۹ ام تأخیر نمایش داده شده و تمرکز رو روی «یک درصد زمان پاسخ خیلی بد» گذاشتیم.

صدک ۹۹ام تاخیر

نمودار بالا به طور باور نکردنی با نمودار اولیه (میانگین و میانه) تفاوت داره. این نمودار بیان می‌کنه که در ساعت ۹:۳۶ دقیقه ۹۹ درصد مقادیر کمتر از ۸۵۰ میلی ثانیه هستن یا به عبارتی دیگه یک درصد کاربرها تاخیری بیشتر از ۸۰۰ میلی ثانیه رو تجربه کردن!
نکته‌ای که وجود داره اینه که اگه از سیستم توزیع شده استفاده کنیم این طول تأخیر تشدید می‌شه چون معمولاً توی این سیستم‌ها یک درخواست به چندین درخواست کوچیکتر شکسته میشه و بصورت توزیع شده روی ماشین‌های زیادی (شاید بیشتر از هزارتا) اجرا می‌شه و در نهایت نتیجه کل پاسخ‌ها تجمیع و به کاربر تحویل داده می‌شن.

هر چند از احتمالی که توی دانشگاه بهمون درس دادن خاطره خوبی ندارم ولی برای اینکه یک کم مستند صحبت کنیم فرض کنید میانگین زمان پاسخ یک سرویس دهنده ۱۰ میلی‌ثانیه ست اما صدک ۹۹ ام تأخیر اون برابر با یک ثانیه باشه. بنابراین یک درصد از درخواست‌ها تاخیر یک ثانیه ای را تجربه می‌کنن. حالا تصور کنید درخواست کاربر برای انجام شدن نیاز به اجرا بر روی صد سرویس دهنده رو داشته باشه. یعنی ما داده‌ها رو بین ۱۰۰ سرویس‌دهنده توزیع کردیم (روش sharding) بنابراین :
درخواست توسط یک گره ریشه بین تعداد زیادی ماشین توزیع میشه و برای تولید پاسخ نهایی لازمه منتظر پاسخ تمام سرویس دهنده‌ها بمونیم.

خب اول فرض‌های مسأله رو می‌نویسیم:
احتمال اینکه «یک» سرویس دهنده به‌موقع پاسخ خود را تولید کند : ۹۹ درصد
تعداد کل سرویس دهنده ها : ۱۰۰
حالا مسئله مشخصه و می‌تونیم با داشتن این فرض‌ها احتمال تأخیر هر درخواست رو به صورت زیر محاسبه کنیم:

خب طبق این محاسبه ۶۳ درصد کاربرها تأخیر بیش از یک ثانیه رو تجربه می‌کنن و عملاً میشه گفت سیستم شما بدرد نمی‌خوره چون بیشتر مواقع کنده (:

 

سلام دنیا!

سلام بالاخره تصمیم گرفتم تا تنبلی رو کنار بذارم و شروع کنم به نوشتن. این وبلاگ رو با ایده اینکه قراره بیشتر در مورد سیستم‌های توزیع شده صحبت کنیم با نام اختاپوس انتخاب کردم و سعی دارم در این وبلاگ تجربه‌ها و دانش اندک خودم رو با بقیه به اشتراک بذارم. البته سعی می‌کنم وقت بیشتری روی این وبلاگ بذارم و بهترش کنم. (: