اخیرا مقالهای منتشر شده با عنوان It’s Time to Replace TCP in the Datacenter، که خوندنش خالی از لطف نیست. مقاله کارایی پروتکل TCP در دیتاسنترها رو زیر سوال برده و با اشاره به مشکلات این پروتکل، پروتکل جدیدی رو معرفی کرده.
نویسنده مقاله پروفسور John Ousterhout از اساتید دانشگاه Stanford هست که برخی دستاوردهای ایشون رو میتونید از ویکیپدیا مطالعه کنید.
اصلیترین خصوصیتهای پروتکل TCP عبارتند از:
Stream orientation
• Connection orientation
• Bandwidth sharing (“fair” scheduling)
• Sender-driven congestion control
• In-order packet delivery
در مقاله به طور خلاصه در مورد هر کدام توضیحاتی ارائه میشه و گفته میشه چرا این اصول طراحی باعث بوجود اومدن کارایی پایین این پروتکل در دیتاسنترها میشه.
مثلا در مورد stream orientation در مقاله گفته میشه که در پروتکل TCP دیتامدل به کار گرفته شده جریان بایت (stream of bytes) هست. در حالی که این دیتامدل برای اکثر نرمافزارهای دیتاسنتر مدل مناسبی نیست. نرمافزارهای دیتاسنتر عموما با رد و بدل کردن پیامهای گسسته (y exchange discrete messages) به پیاده سازی الگوی remote procedure calls یا همون RPC میپردازند. وقتی این پیامها (messages) به جریانی از TCP تبدیل میشوند، پروتکل TCP هیچ ایدهای نداره که مرز بین messageها کجاست. این مساله باعث میشه که نرمافزار وقتی که جریان دادههای TCP رو میخونه هیچ تضمینی وجود نداره که یک message رو بصورت کامل دریافت کنه، ممکنه بخشی از یک message رو دریافت کنه و حتی بخشهایی از چندین message مختلف رو دریافت کرده باشه. نرمافزارهای مبتنی بر TCP مجبور هستند که مرز messageهای خود را هنگام serialize کردن مشخص کنند. (طول هر message به عنوان prefix به پیام اضافه میشه).
این نرمافزارها مجبور هستند از همین اطلاعات (طول message) برای سر هم کردن پیام در سمت گیرنده استفاده کنند. این موضوع هم پیچیدگی بیشتری اضافه میکنه و هم overhead بیشتر. مثلا اینکه در سمت گیرنده نرمافزار مجبور میشه وضعیت پیامهای ناقص دریافت شده رو نگه داره…
مثلا ابزارهایی که درخواستهای TCP رو load-balance میکنند در نظر بگیرید. فرض کنید تعدادی thread قرار هست که درخواستهای ورودی مرتبط با چند stream مختلف رو پاسخگو باشند. در حالت ایدهآل هر thread میتونه پیامهای مرتبط با هر streamی رو دریافت کنه. اما چون عملیات خواندن از stream تضمین نمیکنه که یک message کامل رو بخونه، اگه چندتا thread همزمان از یک stream عملیات خوندن رو انجام بدن، ممکنه بخشهای مختلفی از یک message توسط چند thream مختلف انجام بشه. بنابراین، نرمافزارهای مبتنی بر TCP برای عملیات load-balancing مجبور هستند یکی از این دو راه رو انتخاب کنند:
یک - مجموعهای از streamها بین تعدادی thread تقسیم میشه بگونهای که مسئولیت خواندن از یک stream فقط به یک thread خاص داده میشه. این روش توسط memcached پیادهسازی شده و استفاده میشه. این روش مستعد هست که با مشکل hot spots مواجه بشه، جایی که stream خاصی که توسط یک thread خوانده میشه درصد قابل توجهی از درخواست های ورودی رو شامل بشه در حالیکه threadهای دیگه بیکار یا کمکار هستند.
دو - یک thread خاص مسئولیت خواندن همه درخواستهای ورودی از همه streamها رو بر عهده میگیره، سپس messageهارو بین threadهای دیگه سرویس توزیع میکنه. این روش که در RAMCloud استفاده میشه باعث میشه threadی که messageها رو توزیع میکنه پاشنه آشیل سیستم باشه. همچنین این موضوع که یک درخواست (request) باید بین ۲ تا thread رد و بدل بشه هم باعث میشه overhead سیستم بیشتر بشه و هم latency پاسخ بالا میره.
پیشنهاد میکنم که برای آشنایی بیشتر با مشکلات پروتکل TCP نگاهی به مقاله داشته باشید.