سرویس های stateful در برابر سرویس های stateless

مقدمه

برای مدت ها سرویس‌های stateful انتخاب اصلی توسعه‌دهندگان بود، اما امروزه استفاده از container ها و ابزار‌های مدیریت container به خصوص داکر و kubernetes به ابزاری همه‌گیر برای مدیریت و مقیاس کردن سیستم‌های توزیع شده، تبدیل شده است.

kubernetes ابزار بسیار مناسبی برای مدیریت سرویس های stateless می‌‌باشد اما توسعه و مدیریت سرویس داده محور و stateful همچنان چالش برانگیز است.

در این مقاله مروری برای مزایا و معایب سرویس های stateful و stateless خواهیم داشت.


سرویس stateful و stateless چیست

سرویس stateful برای پاسخ‌گویی به درخواست‌ها از وضعیت داخلی خود استفاده می‌کند و به ازای هر درخواست به دیتابیس کوئری نمی‌زند. به عبارتی استیت مورد نیازش را در حافظه کَش می‌کند. در مقابل سرویس stateless از دیتابیس و یا سرویس های کش برای نگهداری وضعیت خود استفاده می کند.


مشکل سرویس های stateful

فرض کنید دو نمونه از یک اپلیکیشن stateful یکسان داریم. از یک لودبالانسر برای توزیع بار درخواست‌ها بین این دو سرویس استفاده می‌کنیم. اولین درخواست به سرویس شماره یک می رود و دومین درخواست به سرویس شماره دو، از آنجا که سروییکس در استیت خودش وضعیت لاگین را true کرده است درخواست دوم متوجه لاگین بودن نمی شود. این مشکل از آنجا ناشی می شود که استیت دو تا سرویس یکسان و فعال با یکدیگر سینک نیستند.

یک راه توزیع چنین سرویس هایی استفاده sharding است که ابزارهایی مثل akka برای چنین جنس سرویس هایی طراحی شده اند.

اکتورهای akka ذاتا stateful هستند زیرا اکتور بدون استیت یکی از مزیت های اصلی خود را از دست می دهد و در دنیای اکتور هم anti-pattern به حساب می آید. بنابراین اپلیکیشن هایی که با اکتور نوشته می شوند از این جنس هستند و باید به این صورت توزیع شوند.


مزایای سرویس های stateful

  • مدیریت consistency بدون نیاز به lock :‌ با استفاده از sharding می توان توزیع شدگی را بدون ایجاد lock پیاده سازی کرد.
  • پاسخگویی سریع تر به درخواست ها : از آنجا که داده ها در حافظه خود سرویس نگهداری می شود، دسترسی به آن ها نیز سریع تر خواهد بود.

سرویس های stateless برای پاسخگویی به هر درخواست به دیتابیس و یا کش سرور کوئری می‌زنند. این نوع سرویس ها استیت خود را در سرور ذخیره نمی کنند و همه داده‌های مورد نیاز این سرویس‌ها در دیتابیس و کش ذخیره سازی می شود.

این جنس سرویس ها هیچ استیتی را در رم و یا دیسک خود ذخیره سازی نمی کنند و وابسته به سرویس های دیگری برای ذخیره سازی استیت هستند.

مزایای سرویس های stateless

  • ایزولیشن بین استیت و رفتار :‌ توسعه معمولا بر روی رفتار هست و ناپایداری در سرویس رفتار تاثیری روی استیت نمی گذارد و همچنین هنگام نسخه دادن نیازی به ریستارت سرویس های استیت نیست.
  • استقلال بین استیت و رفتار :‌ این استقلال امکانی را به ما می دهد که از ابزار مناسب مختص هر کار استفاده کنیم. برای مثال JVM و Managed Memory ابزار مناسبی برای کش نیست زیرا مقدار حافظه محدودی دارد و همچنین مکانیزم Garbage Collector کارایی چنین سرویس هایی رو کاهش می دهد. در مقابل سرویس هایی مثل ردیس که با C نوشته شده اند برای چنین کاربردهایی بسیار مناسب‌تر هستند.
  • افزایش سرعت بروزرسانی سرویس‌ها :‌ با هر نسخه نیازی به بروز رسانی سرویس های استیت نداریم.
  • ریپلیکیت سرویس ها : در لحظه چندین سرویس یکسان می تواند فعال باشد که در صورت نیاز به بروزرسانی، فقط با فوروارد کانکشن ها، درخواست ها و عملیات آن ها به سرویس مورد نظر فوروارد خواهد شد.
  • باکت تستینگ : پردازش درخواست ها در همان‌جایی که کانکشن متصل هست انجام می شود. بنابراین با جدا کردن کانکشن کاربرهای مورد نظر می توان به سادگی و بدون نوشتن کد اضافه باکت تست را پیاده سازی کرد.
  • برون سپاری :‌پیدا کردن متخصص پستگرس و ردیس خیلی راحت تر از متخصص akka cluster هست! همچنین سرویس هایی مثل ردیس و پستگرس در سرویس‌های کلود مثل آمازون و گوگل ارائه می‌شوند که می توان نگهداری این سرویس ها را به شرکت هایی که تخصص این کار را دارند سپرد.
  • مالتی دیتاسنتر : در مالتی دیتاسنتر باید استیت تمامی کاربران در دو دیتاسنتر وجود داشته باشد در نتیجه نیاز به سینک شدن دیتاسنترها به ازای تغییر استیت ها داریم که این در سیستم های statsful چالش برانگیز است.
  • استفاده بهینه از رم : در مجموع کاهش کارایی در نتیجه ی خواندن استیت ها از DB در سیستم های statesless نسبت به کاهش تعداد سرورها موردنیاز برای این سیستم در مقایسه با statefulها بسیار بسیار ناچیز است هر چند همان کاهش کارایی را میتوان با استفاده از DBهای مقیاس پذیر مانند کاساندرا و استفاده از کش های میانی سرور و DB مانند redis، جبران کرد.
  • کاهش تعداد نودها و در نتیجه کاهش هزینه نگهداری : نیازی نیست مدیریت کلاستر در سطح سرویس هایی که ما توسعه دادیم انجام بشود و به عهده سرویس های اوپن سورس و پایداری مثل کاساندرا و ردیس خواهد بود.
  • کاهش پیچیدگی برنامه نویسی:‌ در واقع پیچیدگی از سطح سرویس ما به سرویس هایی که وظیفشون مدیریت چنین پیچیدگی هایی است انتقال پیدا می کند.

معایب سرویس‌های stateless

  • برای consistency باید از lock استفاده کنیم و یا راه حل های دیگر همزمانی مثل CSP و غیره
  • تاخیر رفت و برگشت شبکه برای دریافت داده

نظرات برخی از شرکت ها

شرکت Netflix

در کنفرانس GoTo سال ۲۰۱۶ شرکت Netflix ارائه ای با عنوان Microservices at Netflix Scale برگزار می کند. در این ارائه ادعا می کند که سرویس ها باید stateless باشند. یکی از علت های چنین ادعایی نتیجه ای است که از Chaos Testing به دست آورده اند.

Chaos Testing و به طور کلی تر Chaos Engineering به مجموعه تمهیداتی گفته می‌شود نرم‌افزار را در محیط واقعی یا اصطلاحاً Production Environment زیر بار فشارهای مختلفی قرار دهند تا در نهایت دریابند که سرویس مذکور تا چه حد تحمل شرایط غیرمنتظره را دارا است. برای اطلاعات بیشتر به لینک زیر مراجعه کنید

https://tinyurl.com/yxrbmhaq

شرکت Lightbend

شرکت lightbend توسعه دهنده فریم ورک آکا و یکی از مدعیان اصلی سرویس های stateful است. این شرکت در مقاله که در ادامه بخشی از آن نقل قول شده است توضیح می دهد که سرویس های stateful برای چه کاربردهایی مناسب تر هستند.


چکیده ای از مقاله Design Techniques for Building Stateful از lightbend
چکیده ای از مقاله Design Techniques for Building Stateful از lightbend


اینجا به دو تا از مزیت های stateless اشاره کرده:

  • کاهش پیچیدگی برنامه نویسی
  • کاهش پیچیدگی های مربوط به نگهداری استیت

اینجا هم به نکته بسیار مهمی اشاره شده که سسیتم های stateful برای Realtime Streaming Data بسیار مناسب هستند و برای دیگر کاربردها stateless ها به اندازه کافی خوب هستند.


نتیجه گیری

  • اگرچه سرویس های stateless سربار کوئری زدن به دیتابیس را دارند اما به شدت مقیاس پذیر هستند.
  • با توجه به توضیحات داده شده اکتورها در دنیای stateless کاربرد چندانی نخواهند داشت. همچنین هزینه نگهداری سرویس های stateless بسیار پایین تر از سرویس های stateful هست.
  • سسیتم های stateful برای Realtime Streaming Data بسیار مناسب‌تر هستند و برای دیگر کاربردها stateless ها به اندازه کافی خوب هستند.


در انتها از دوستان خوبم سید مصطفی مشکاتی و امین پایدار تشکر می کنم که من را در نگارش این مقاله یاری کردند.


مراجع

  • مقاله ای عالی از lightbend که تفاوت و کاربرد stateful و stateless رو به خوبی نشان داده است

https://www.lightbend.com/blog/design-techniques-stateful-cloud-native-applications-resilience-recoverability-scalability

  • کنفرانس GoTo با موضوع Microservices at Netflix Scale

https://www.dideo.ir/v/yt/57UK46qfBLY

  • اسلایدها

https://drive.google.com/file/d/1AkIp9eabmyXhD7un4g-obh9eG-UtM52Z/view?usp=sharing

  • مقاله برای تبیین تفاوت های سرویس های stateless و stateful

https://www.xenonstack.com/insights/what-are-stateful-and-stateless-applications/

  • مقاله ای از lightbend برای طرفداران stateful :)

https://drive.google.com/file/d/1WBachZCQSHfetvg9nZTUkcKISHnpiwvm/view?usp=sharing