تقریبا حدود سه هفته پیش بود که از طریق یک دوست با اسنپ کیو آشنا شدم .در واقع ایشون کنجکاو تکنولوژی های بکار رفته در اسنپ کیو هستن .علاقه ایشون و یه سوالی که از قبل تو پس زمینه ذهنی من (هارد ذهنم ) مونده بود باعث شد منم علاقه مند بشم به اینکه چنین سیستم هایی که در یک بازه زمانی خاص یهویی بار ترافیکی زیادی به سرور تحمیل میشه چطوری و با چه تکنولوژی هایی پیاده سازی میشه .
طبق گفته و دسته بندی های ارایه شده توسط مارتین فاولر در مورد Enterprise Application ها چنین اپلیکیشن هایی نباید business logic پیچیده ای داشته باشند و تنها چیزی که باید در موردش بیشتر تمرکز کرد بحث scaling و هندل کردن تعداد بالای کاربران ست .
قطعا با http و request /response های ساده چنین سیستم هایی هندل نمی شوند.
به عنوان برنامه نویس منو( اگه خدا قبول کنه ) و دوستم بالطبع بیشتر جنبه های نرم افزاری قضیه و تکنولوژی ها و پروتکل های بکار رفته در لایه اپلیکیشن برامون جذاب بود .
به واسطه این دوستم من توی این مدت با پروتکل های AMQPو MQTT و بروکرهایی چون RabbitMQ آشنا شدم و در واقع ایشون بودن که نیاز به یادگیری این تکنولوژی های message base و queue base رو در من به وجود اوردند.
به گفته این دوست از این تکنولوژی ها برای مدیریت تعداد زیاد کاربران استفاده می کنند حدس فنی شون این است در اسنپ کیو هم چنین تکنولوژی هایی بکاررفته ...
از اوقات فراغت این چن روزه استفاده کرده و تصمیم گرفتم کمی بیشتر روی این مدل پروژه ها مطالعه کنم .
داستان از پروتکل AMQP شروع شد به یادگیری RabbitMQ رسید بعدش سوالاتی توی ذهنم ایجاد شد و منحرف شدم سمت وب سوکت و چرایی استفاده از اون و تفاوتهایی که وب سوکت با AMQP دارند و اینکه چرا ما MQTT رو روی وب سوکت هم نیاز داریم و...
قسمت طنز ماجرا سوالی بود که صبح توی ذهنم ایجاد شد ؟
چن تا tcp socket روی کامپیوترم دارم من ؟ :/
اصلا سوکت چیه ؟
فرقش با پورت چیه ؟
و..
و...
یهویی همه چی تو ذهنم قاطی شد :///
پروتکل های msg base و وب سوکت و اسنپ کیو رو بی خیال شدم رفتم سراغ مفهوم سوکت و ماکزیمم تعداد tcp conn هایی که میشه روی یه سیستم زد .
نترسید نمی خوام در مورد این ها این جا حرف بزنم اما همین سوالات بدیهی باعث بشد من یکسری فاکتورهای تاثیرگذار در زمینه پشتیبانی از تعداد زیادی کاربر رو بتونم برای خودم لیست کنم شاید برای خواننده محترم مقاله هم جالب باشه این فاکتورها.
قبل از اینکه به فاکتور های مورد نظر خودم اشاره کنم ابتدا لازم میدونم فکتورهای سنجش کارایی و پرفورمنس یک پروژه (شامل سخت افزار و نرم افزار ) به صورت کلی بدون توجه به نوع Enterprise Application را از قول فاولر که در کتاب Patterns of Enterprise Appllication Architecture آنها رو لیست کرده رو اینجا بیارم
در دنیای سنجش performance چندین واژه / اصطلاح است که البته رعایت همه آنها با همدیگر کارایی بالای پروژه شما را تضمین نمیکند و ممکن است رعایت یک فاکتور باعث قربانی شدن فاکتورهای دیگر شود.
این فاکتورها از نظر فاولر اینها هستند :
فاکتور Response time : مدت زمانی که طول میکشد تا یک درخواست توسط سیستم پردازش شود.
فاکتور Responsiveness : یعنی سیستم چقدر در مقابل درخواست ها پاسخگو است . مثلاً فرایند کپی کردن فایل ممکن است چند ثانیه طول بکشد (response time ) ولی به محض اینکه کاربر عمل کپی کردن را شروع میکند سیستم بهش با یک علامت / شکلک منتظر باشید یا سیستم درحال کپی کردن فایل شماست به کاربر واکنش نشان دهد .
فاکتور Latency : یعنی کمترین زمانی که طول میکشد تا سیستم به درخواستی واکنش نشان دهد. این موضوع توی سیستمهای ریموت میتواند خیلی فاکتور تأثیر گذاری باشد مثلاً من از سیستمی خواستم کاری انجام دهد ولی وسط راه پشیمون شدم دکمه کنسل را زدم ولی سیستم بعد از اینکه کار را انجام داد و تموم شد اون دستور کنسلی منو لحاظ کنه و واکنش نشون بده چنین سیستمی اصلاً سیستم خوبی از نظر تأخیر (latency) نیست . باید همون لحظه که زدم هیچ کاری نکن هیچ کاری نکنه و بهم واکنش نشون بده .
فاکتورThroughput : یعنی سیستم در یک واحد زمانی چند کار میتواند انجام دهد مثلاً یک سیستم در یک ثانیه چند تراکنش انجام دهد .یا سیستم در یک واحد زمانی چند کیلو بایت میتواند کپی کند .معمولاً برای enterprise application ها چند تا از تراکنش های متداول پروژه را به عنوان معیار سنجش throughput انتخاب میکنند .
گاهی افزایش throughtput باعث کاهش فاکتور response time میشود . اما باز بستگی دارد به سیستم شما . گاهی از نقطه نظر کاربر بهبود resposiveness باعث بالا رفتن کارایی میشود در حالی که فاکتورهای throughput و یا حتی response time قربانی شوند .
فاکتور Load : معمولاً میگویند چه تعداد کاربر همزمان میتوانند به سیستم وصل بشوند و سیستم به درخواست آنها پاسخ مناسب بدهد.
فاکتور Load sensivity : یعنی سیستم براساس تعداد کاربران میزان response time ش چقدر تغییر میکند. مثلاً میگوییم سیستم A دارای زمان پاسخگویی 0.5 ثانیه به ازای 10-20 کاربر است .و سیستم B دارای زمان پاسخگویی 0.2 ثانیه به ازای 10 کاربر است که وقتی تعداد کاربران به 20 عدد میرسد مدت زمان پاسخگویی به 2 ثانیه میرسد .در این حالت سیستم A دارای load sensitivty پایینتری است .
فاکتور Efficiency : یعنی performance تقسیم برتعداد منابع . به عنوان مثال سیستمی که با دو cpu دارای 30 tps است دارای efficiency بالاتری نسبت به سیستمی ست که داری 40 tps با 4 cpu است .
فاکتور Capacity : برابر با بشینه throughput یا load مؤثر سیستم است . این مقدار را میتوان به صورت یک نمودار سهمی تصور کرد که در نقطه از نمودار دارای بشینه مقدار است .
فاکتور Scalability : با چه تعداد افزودن منابع میتوان performance را بهبود بخشید .
دو مدل scalability داریم :
با فرض اینکه مهمترین مساله ما در یک پروژه بحث هندل کردن تعداد زیاد کاربران اون هست رعایت فاکتورهای زیر به گمان من ( طبق مطالعاتی که امروز داشتم ) ممکنه باعث افزایش کارایی پروژه بشه ( از نظر فاکتور Load که در بالا بهش اشاره شد ) .
ما 65534 تا پورت نرم افزاری روی یک سیستم داریم( منظور روی یک سیستم عامل ) و همانطور که میدونید مفهوم port در لایه اپلیکیشن از استک tcp/ip معنی پیدا می کنه .
فرض کنید ما روی سرورمون فقط یک آدرس ip ( به آدرس x.y.z.s ) داریم و این سرور ما یک کلاینت ( کاربر ) دارد که میخواهد بهش وصل بشود . به نظرتون این کلاینت چن تا tcp conn می تواند به سرور بزند و باز کند ؟
جواب : 65534 تا
به این صورت که کلاینت ا 65354 تا درخواست به آدرس ip یکسان ولی با پورت های متفاوت می فرستد :
x.y.z.s:0
x.y.z.s:1
....
x.y.z.s:65354
این عدد روی کاغذ درسته فاکتورهای دیگر هم هستند که باعث می شوند این عدد محدود بشود از جمله :
میزان حافظه RAM در دسترس ( برای نگهداری اطلاعات سوکتها )
تعداد و قدرت کارتهای شبکه نصب شده روی ماشین سرور
سرعت اینترنت
همچنین روی سیستم عامل های یونیکس بیس و لینوکس بیس ما یک پارامتری هم داریم که ماکزیمم تعداد فایل های باز شده به صورت همزمان را مشخص می کنه این پارامتر باید در سطح کرنل باید تنظیم بشه .
حال فرض کنید سرور ما یک آدرس ip دارد وکلاینتهای ما فقط با یک پورت این سرور کار دارند . فرض کنید این بار تعداد خیلی زیادی کلاینت قصد وصل شدن به سرور رو دارند روی همان آدرس ip و همون پورت .
به نظرتون چن تا tcp conn می تونیم روی سرورمون باز کنیم با فرض اینکه ما محدودیت حافظه RAM و کارت شبکه و سرعت اینترنت و اون پارامتر داخل کرنل لینوکس رو نداریم میشه گفت بی نهایت
استدلالم برای این بی نهایت گفتن این توضیح و مثال زیر است ( اگه درست نیس بفرمایید )
هر packet که از سمت کلاینت به سرور ارسال میشه برای اینکه شناسایی بشه این packet از سمت چه کسی اومده و با چه اپلیکیشنی سرو کار داره به 4 پارامتر زیر نیاز داره :
client_address:client_port | server_address:application_port
ما گفتیم بی شمار کلاینت با آدرس ip های متفاوت داریم حالا از چه پورتی برای ارسال packet استفاده کردن زیاد مهم نیس اما این ور، سمت سرور، ادرس سرور و پورت کاملا مشخص و از دید همه کلاینت ها یکسان است .
وقتی packet دست سرور رسید اون فقط از tcp socketعبور میده و میده به لایه بالاتر از خودش یعنی لایه اپلیکیشن اونجا از روی پورت می فهمه دست چه اپلیکیشنی باید برسونه پیام رو .
فرض کنید چنین سیستمی از نظر زیرساخت ساخته و بهینه کانفیگ شده به نظرتون همه چی اوکیه ؟
جواب : نه
چون در سطح اپلیکیشن ما نیاز داریم نرم افزارهایی داشته باشیم که بتونه این حجم از پیامها / درخواستهای اومده سمتش را گرفته و پردازش کنه و اینجاست که غول هایی چون کافکا و بروکرهایی چون RabbitMQ و EMQX خودشون رو به رخ ما برنامه نویسان می کشند . و البته تا یادم نرفته بگم اگه از نرم افزارهامبتنی بر JVM و کلا ماشین های مجازی و Container استفاده می کنید اونها هم نیاز به تیون کردن بهینه دارند .
حین جستجو هام توی وب به این مقاله برخوردم برام خیلی مفید بود گفتم شاید برای شما همین همین طور باشه پس به اشتراک میزارم.
مطالبی که اینجا بخصوص برای بیان استدلالم نوشتم رو از منابع زیر برداشت کردم (شاید برداشتم اشتباه باشه خوشحال میشم اشتباهاتم رو تصحیح بفرمایید چون تنها هدفم از انتشار این مطالب به چالش کشیدن دانش و درک خودمه و خب اگه مفید هم باشه برای دوستان باعث افتخار منه :)
منابع
https://www.quora.com/How-many-open-TCP-connections-can-a-typical-PC-hold-at-once
https://www.quora.com/How-many-clients-can-connect-to-a-single-TCP-port
https://mrotaru.wordpress.com/2013/10/10/scaling-to-12-million-concurrent-connections-how-migratorydata-did-it/
https://docs.emqx.io/broker/v3/en/design.html#architecture