مونولیت یا میکروسرویس؟

بحث میکروسرویس در بیشتر جلساتی که دیدهایم زود به سمت فناوری میرود — کانتینر، صف پیام، دروازهٔ API — و همانجا از اصل مسئله دور میشود.
سؤال واقعی این نیست که چند سرویس داشته باشید. این است که چند تیم دارید که باید بدون هماهنگی با هم منتشر کنند.
آنچه واقعاً میخرید
میکروسرویس یک چیز را به شما میدهد: استقلال در انتشار. تیم الف میتواند سرویسش را امروز بالا ببرد بدون اینکه منتظر تیم ب بماند یا چیزی از او بشکند.
هر مزیت دیگری که برای این معماری گفته میشود — مقیاسپذیری مستقل، تنوع فناوری، تحمل خطا — یا با مونولیت هم قابل دستیابی است، یا آنقدر کوچک است که هزینهٔ معماری را توجیه نمیکند.
و اگر یک تیم دارید، استقلال در انتشار چیزی است که از قبل دارید. یعنی بابت چیزی پول میدهید که لازم ندارید.
آنچه میپردازید
این فهرست معمولاً کوتاهتر از واقعیت گفته میشود:
فراخوانی شبکه بهجای فراخوانی تابع. چیزی که در مونولیت قطعی و آنی بود، حالا میتواند کند شود، شکست بخورد، یا دو بار برسد. هر تماس بین سرویسها باید مهلت، تلاش مجدد و رفتار جایگزین داشته باشد.
تراکنش از دست میرود. در یک پایگاه داده، «سفارش ثبت شد و موجودی کم شد» یک تراکنش است؛ یا هر دو یا هیچکدام. وقتی این دو در دو سرویس باشند، آن تضمین وجود ندارد و باید با الگوهای جبرانی بازسازی شود. این تنها گرانترین قلم این فهرست است و بیشتر از همه دستکم گرفته میشود.
عیبیابی سختتر. یک درخواست از پنج سرویس رد میشود و برای فهمیدن اینکه کجا کند شده، به ردیابی توزیعشده نیاز دارید.
استقرار پیچیدهتر. پنج سرویس یعنی پنج خط لولهٔ انتشار، پنج مجموعه تنظیمات، و مدیریت نسخه بینشان.
داده تکهتکه میشود. گزارشی که قبلاً یک کوئری بود، حالا باید از چند جا جمع شود.
محیط توسعه. برنامهنویس تازهوارد باید بتواند همهچیز را روی لپتاپش بالا بیاورد. با پانزده سرویس، این خودش یک پروژه است.
نشانههایی که واقعاً میگویند وقتش رسیده
نه اندازهٔ کد، نه تعداد کاربر. اینها:
چند تیم روی یک مخزن کار میکنند و برای انتشار منتظر هم میمانند.
بخشی از سامانه بار کاملاً متفاوتی دارد و مجبورید کل برنامه را برایش بزرگ کنید.
بخشی نیاز فنی متفاوتی دارد که با بقیه نمیخواند.
یا بخشی چرخهٔ تغییر خیلی سریعتری دارد و انتشار مکررش، بقیه را به ریسک میاندازد.
اگر هیچکدام را ندارید و کد شما «شلوغ» شده، مسئلهٔ شما ساختار داخلی است نه مرز سرویس. تقسیم یک کد بههمریخته به پنج سرویس، پنج کد بههمریخته میسازد که حالا از شبکه هم رد میشوند.
مسیری که پیشنهاد میکنیم
با مونولیت شروع کنید، ولی با مرزهای داخلی روشن. یعنی کد را بر اساس حوزهٔ کسبوکار ماژولبندی کنید — سفارش، انبار، مشتری — طوری که هر ماژول فقط از طریق واسط مشخصی با بقیه حرف بزند و به جدولهای داخلی همدیگر دست نزند.
این کار امروز تقریباً هیچ هزینهای ندارد و دو چیز به شما میدهد: کد قابل نگهداری، و امکان جداکردن یک ماژول به سرویس مستقل هر وقت واقعاً لازم شد. اگر آن روز هرگز نرسید — که برای بیشتر سازمانها نمیرسد — چیزی از دست ندادهاید.
و اگر رسید، یکی را جدا کنید، نه همه را. معمولاً همان بخشی که یکی از چهار نشانهٔ بالا را دارد. الگوی این جداسازی تدریجی در مهاجرت تدریجی توضیح داده شده.
اشتباهی که زیاد دیدهایم
سازمانهایی که میکروسرویس را انتخاب کردهاند چون «مدرنتر» است، معمولاً به یک حالت میانی میرسند که بدترین هر دو دنیاست: چند سرویس که همه به یک پایگاه دادهٔ مشترک وصلاند.
اینجا هیچکدام از مزایای میکروسرویس را ندارید — چون تغییر ساختار داده هنوز همه را میشکند و انتشار مستقل ممکن نیست — و همهٔ هزینههای شبکه و استقرار را میپردازید.
اگر سرویسها پایگاه دادهٔ مشترک دارند، شما یک مونولیت توزیعشده دارید. اسمش را عوض کردن چیزی را حل نمیکند.
یک سؤال برای تصمیم
اگر باید یک سؤال بپرسید، این را بپرسید: اگر فردا بخواهیم فقط یک تغییر کوچک در بخش سفارش منتشر کنیم، چند نفر باید هماهنگ شوند و چه چیزهای دیگری تست میخواهند؟
اگر جواب «یک تیم، همان بخش» است، مونولیت شما مشکلی ندارد.
اگر جواب «سه تیم و تست کل سامانه» است، شما به مرزهای بهتر نیاز دارید — که ممکن است میکروسرویس باشد، و ممکن است فقط ماژولبندی درست همان مونولیت.