Skip to content

فصل ۱ — میکروسرویس‌ها

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

کتاب Domain-Driven Design اثر Eric Evans (Addison-Wesley) به ما کمک کرد اهمیت بازنمایی دنیای واقعی در کد را بفهمیم و راه‌های بهتری برای مدل‌سازی سیستم‌ها نشان داد. مفهوم continuous delivery نشان داد چگونه می‌توانیم نرم‌افزار را مؤثرتر و کارآمدتر به production برسانیم و ایدهٔ این را در ذهنمان تثبیت کرد که هر check-in را باید یک release candidate در نظر بگیریم. درک ما از نحوهٔ کار وب، ما را به سمت راه‌های بهتر برای گفت‌وگوی ماشین‌ها با یکدیگر برد. مفهوم hexagonal architecture اثر Alistair Cockburn ما را از معماری‌های لایه‌ای که منطق کسب‌وکار در آن‌ها پنهان می‌شد دور کرد. پلتفرم‌های مجازی‌سازی اجازه دادند ماشین‌ها را آزادانه provision و resize کنیم و infrastructure automation راهی برای مدیریت این ماشین‌ها در مقیاس بزرگ داد. برخی سازمان‌های بزرگ و موفق مثل Amazon و Google دیدگاه تیم‌های کوچکی را ترویج کردند که چرخهٔ کامل عمر سرویس‌هایشان را مالک باشند. و اخیراً Netflix راه‌های ساخت سیستم‌های antifragile در مقیاسی را با ما به اشتراک گذاشت که ده سال پیش درک آن دشوار بود.

Domain-driven design. Continuous delivery. مجازی‌سازی on-demand. Infrastructure automation. تیم‌های کوچک و مستقل. سیستم‌ها در مقیاس. میکروسرویس‌ها از این دنیا برخاسته‌اند. قبل از وقوع اختراع یا توصیف نشدند؛ به‌عنوان روند یا الگو از کاربرد واقعی ظهور کردند. اما فقط به‌خاطر همهٔ آنچه پیش از این بوده‌اند وجود دارند. در سراسر این کتاب، رشته‌هایی از این کارهای پیشین را بیرون می‌کشم تا تصویری از چگونگی ساخت، مدیریت و تکامل میکروسرویس‌ها ترسیم کنم.

بسیاری از سازمان‌ها با پذیرش معماری‌های میکروسرویس fine-grained، توانسته‌اند سریع‌تر نرم‌افزار تحویل دهند و فناوری‌های جدیدتر را بپذیرند. میکروسرویس‌ها آزادی بسیار بیشتری برای واکنش و تصمیم‌گیری‌های متفاوت می‌دهند و به ما اجازه می‌دهند سریع‌تر به تغییر اجتناب‌ناپذیری که همهٔ ما را تحت تأثیر قرار می‌دهد پاسخ دهیم.

میکروسرویس‌ها چیستند؟

میکروسرویس‌ها سرویس‌های کوچک و مستقل هستند که با هم کار می‌کنند. بیایید این تعریف را کمی باز کنیم و ویژگی‌هایی را که میکروسرویس‌ها را متفاوت می‌کند در نظر بگیریم.

کوچک و متمرکز بر انجام یک کار به‌خوبی

codebaseها با نوشتن کد برای افزودن ویژگی‌های جدید رشد می‌کنند. با گذشت زمان، ممکن است دشوار باشد بدانیم تغییر باید کجا اعمال شود چون codebase آن‌قدر بزرگ است. با وجود تلاش برای codebaseهای monolithic واضح و modular، اغلب این مرزهای دلخواه درون‌فرآیندی فرو می‌ریزند. کد مرتبط با توابع مشابه شروع به پخش شدن در همه‌جا می‌کند و رفع باگ یا پیاده‌سازی را دشوارتر می‌سازد.

در یک سیستم monolithic، با تلاش برای cohesive بودن کد، اغلب با ایجاد abstraction یا module، با این نیروها می‌جنگیم. انسجام (cohesion) — تمایل به گروه‌بندی کد مرتبط — مفهوم مهمی است وقتی به میکروسرویس‌ها فکر می‌کنیم. این با تعریف Robert C. Martin از Single Responsibility Principle تقویت می‌شود: «آنچه به یک دلیل تغییر می‌کند را جمع کنید و آنچه به دلایل متفاوت تغییر می‌کند را جدا کنید.»

میکروسرویس‌ها همین رویکرد را برای سرویس‌های مستقل دنبال می‌کنند. مرزهای سرویس را روی مرزهای کسب‌وکار متمرکز می‌کنیم تا محل زندگی کد برای هر بخش از قابلیت‌ها واضح باشد. و با نگه داشتن این سرویس روی یک مرز صریح، از وسوسهٔ رشد بیش از حد آن و دشواری‌های مرتبط جلوگیری می‌کنیم.

سؤالی که اغلب می‌شنوم این است: چقدر کوچک، کوچک است؟ دادن عدد برای خطوط کد مشکل‌ساز است چون برخی زبان‌ها expressiveترند و در خطوط کمتر کار بیشتری می‌کنند. باید در نظر بگیریم ممکن است چند dependency بکشیم که خودشان خطوط زیادی دارند. همچنین بخشی از domain ممکن است مشروعاً پیچیده باشد و کد بیشتری بخواهد. Jon Eaves در RealEstate.com.au در استرالیا میکروسرویس را چیزی توصیف می‌کند که در دو هفته قابل بازنویسی باشد — قاعدهٔ سرانگشتی که برای زمینهٔ خاصش معنا دارد.

پاسخ دیگری که می‌توانم بدهم «به اندازهٔ کافی کوچک و نه کوچک‌تر» است. در کنفرانس‌ها تقریباً همیشه می‌پرسم چه کسی سیستمی دارد که خیلی بزرگ است و می‌خواهد بشکند؟ تقریباً همه دست بلند می‌کنند. به نظر می‌رسد حس خوبی از «خیلی بزرگ» داریم؛ پس می‌توان گفت وقتی دیگر یک تکه کد خیلی بزرگ به نظر نرسد، احتمالاً به اندازهٔ کافی کوچک است.

عامل قوی در پاسخ به «چقدر کوچک؟» این است که سرویس چقدر با ساختار تیم‌ها هم‌راستا است. اگر codebase برای یک تیم کوچک خیلی بزرگ است، شکستن آن بسیار منطقی است. بعداً بیشتر دربارهٔ هم‌راستایی سازمانی صحبت می‌کنیم.

وقتی به «چقدر کوچک به اندازهٔ کافی» فکر می‌کنم، این‌طور می‌بینم: هرچه سرویس کوچک‌تر باشد، مزایا و معایب معماری میکروسرویس را بیشتر maximize می‌کنید. با کوچک‌تر شدن، مزایای حول وابستگی متقابل بیشتر می‌شود؛ اما پیچیدگی ناشی از قطعات متحرک بیشتر هم افزایش می‌یابد — چیزی که در سراسر کتاب بررسی می‌کنیم. با بهتر شدن در مدیریت این پیچیدگی، می‌توانید به سمت سرویس‌های کوچک‌تر و کوچک‌تر حرکت کنید.

مستقل (Autonomous)

میکروسرویس ما یک موجودیت جداست. ممکن است به‌عنوان سرویس ایزوله روی platform as a service (PaaS) deploy شود یا فرآیند سیستم‌عامل خودش باشد. سعی می‌کنیم از بسته‌بندی چند سرویس روی یک ماشین اجتناب کنیم، هرچند تعریف ماشین امروز مبهم است! همان‌طور که بعداً بحث می‌کنیم، این ایزولاسیون overhead اضافه می‌کند اما سادگی حاصل، استدلال دربارهٔ سیستم توزیع‌شده را آسان‌تر می‌کند و فناوری‌های جدیدتر بسیاری از چالش‌های این نوع deployment را کاهش می‌دهند.

همهٔ ارتباط بین سرویس‌ها از طریق فراخوانی شبکه است تا جداسازی حفظ شود و خطرات tight coupling اجتناب شود.

این سرویس‌ها باید بتوانند مستقل از یکدیگر تغییر کنند و بدون نیاز به تغییر consumerها deploy شوند. باید فکر کنیم سرویس‌ها چه چیزی را expose کنند و چه چیزی را پنهان نگه دارند. اگر اشتراک‌گذاری زیاد باشد، سرویس‌های consuming به نمایش‌های داخلی ما coupled می‌شوند. این autonomy را کم می‌کند چون هنگام تغییر، هماهنگی بیشتری با consumerها لازم است.

سرویس ما یک application programming interface (API) expose می‌کند و سرویس‌های همکار از طریق آن APIها با ما ارتباط برقرار می‌کنند. همچنین باید فکر کنیم چه فناوری برای اطمینان از عدم coupling consumerها مناسب است. ممکن است APIهای technology-agnostic انتخاب کنیم تا انتخاب فناوری را محدود نکنیم. در سراسر کتاب بارها به اهمیت APIهای خوب و decoupled برمی‌گردیم.

بدون decoupling، همه‌چیز برای ما فرو می‌ریزد. قانون طلایی: آیا می‌توانید تغییری در یک سرویس بدهید و آن را به‌تنهایی deploy کنید بدون تغییر چیز دیگری؟ اگر پاسخ نه است، بسیاری از مزایایی که در این کتاب بحث می‌کنیم برای شما دشوار خواهد بود.

برای decoupling خوب، باید سرویس‌ها و APIها را درست مدل کنید. زیاد دربارهٔ این صحبت خواهم کرد.

مزایای کلیدی

مزایای میکروسرویس‌ها زیاد و متنوع است. بسیاری از این مزایا را می‌توان به هر سیستم توزیع‌شده نسبت داد. اما میکروسرویس‌ها عمدتاً به‌خاطر اینکه مفاهیم سیستم‌های توزیع‌شده و service-oriented architecture را تا حد زیادی پیش می‌برند، این مزایا را درجهٔ بالاتری می‌یابند.

ناهمگونی فناوری (Technology Heterogeneity)

در سیستمی از چند سرویس همکار، می‌توانیم در هر کدام فناوری متفاوت به کار ببریم. این اجازه می‌دهد ابزار مناسب هر کار را انتخاب کنیم، نه رویکرد standardized و one-size-fits-all که اغلب به کمترین مخرج تقلیل می‌یابد.

اگر بخشی از سیستم باید performance بهتری داشته باشد، می‌توانیم stack فناوری متفاوتی انتخاب کنیم. همچنین ممکن است نحوهٔ ذخیرهٔ داده برای بخش‌های مختلف سیستم باید تغییر کند. برای یک شبکهٔ اجتماعی، مثلاً تعاملات کاربران را در پایگاه دادهٔ graph-oriented ذخیره کنیم و پست‌ها را در document store — معماری ناهمگونی مانند شکل ۱-۱.

شکل ۱-۱. میکروسرویس‌ها می‌توانند پذیرش فناوری‌های مختلف را آسان‌تر کنند

با میکروسرویس‌ها می‌توانیم سریع‌تر فناوری جدید را بپذیریم و بفهمیم پیشرفت‌های جدید چگونه کمک می‌کنند. یکی از بزرگ‌ترین موانع امتحان فناوری جدید، ریسک آن است. در یک برنامهٔ monolithic، تغییر زبان، پایگاه داده یا framework روی بخش زیادی از سیستم اثر می‌گذارد. در سیستم چندسرویسی، چند نقطهٔ جدید برای امتحان فناوری دارید. می‌توانید سرویسی با کمترین ریسک را انتخاب کنید و آنجا فناوری جدید را امتحان کنید. بسیاری از سازمان‌ها این توانایی جذب سریع‌تر فناوری را مزیت واقعی می‌دانند.

پذیرش چند فناوری بدون overhead نیست. برخی سازمان‌ها محدودیت‌هایی روی انتخاب زبان می‌گذارند. Netflix و Twitter مثلاً عمدتاً از Java Virtual Machine (JVM) استفاده می‌کنند چون reliability و performance آن را خوب می‌فهمند و کتابخانه و ابزار برای JVM توسعه داده‌اند که کار در مقیاس را آسان‌تر می‌کند، اما برای سرویس‌ها یا clientهای غیر Java دشوارتر است. اما هیچ‌کدام فقط یک stack برای همهٔ کارها ندارند. نکتهٔ دیگر دربارهٔ نگرانی از مخلوط کردن فناوری‌ها، اندازه است. اگر واقعاً بتوانم میکروسرویس را در دو هفته بازنویسی کنم، ریسک پذیرش فناوری جدید را کاهش می‌دهید.

در سراسر کتاب خواهید دید، مانند بسیاری از موضوعات میکروسرویس، همه‌چیز یافتن تعادل درست است. در (ارجاع آینده) دربارهٔ انتخاب فناوری صحبت می‌کنیم؛ و در فصل ۲ دربارهٔ integration یاد می‌گیرید چگونه سرویس‌ها فناوری‌شان را بدون coupling نامتناسب مستقل تکامل دهند.

تاب‌آوری (Resilience)

مفهوم کلیدی در resilience engineering، bulkhead است. اگر یک جزء سیستم fail کند اما failure cascade نشود، مشکل را ایزوله می‌کنید و بقیهٔ سیستم کار می‌کند. مرزهای سرویس bulkheadهای واضح شما هستند. در سرویس monolithic، اگر سرویس fail کند همه‌چیز متوقف می‌شود. در سیستم monolithic می‌توانیم روی چند ماشین اجرا کنیم تا احتمال failure کم شود، اما با میکروسرویس‌ها می‌توانیم سیستم‌هایی بسازیم که failure کامل سرویس‌ها را handle کنند و قابلیت‌ها را متناسب degrade کنند.

باید مراقب باشیم. برای بهره‌گیری از این تاب‌آوری، باید منابع جدید failure در سیستم‌های توزیع‌شده را بفهمیم. شبکه fail می‌کند، ماشین‌ها هم. باید بدانیم چگونه handle کنیم و چه اثری روی کاربر نهایی دارد.

در فصل ۳ بیشتر دربارهٔ مدیریت تاب‌آوری و failure modeها صحبت می‌کنیم.

مقیاس‌پذیری (Scaling)

با یک سرویس monolithic بزرگ، باید همه‌چیز را با هم scale کنیم. بخش کوچکی از سیستم در performance محدود است، اما اگر آن رفتار در یک برنامهٔ monolithic غول‌پیکر قفل شده باشد، باید همه را به‌عنوان یک تکه scale کنیم. با سرویس‌های کوچک‌تر، فقط سرویس‌هایی را scale می‌کنیم که نیاز دارند — مانند شکل ۱-۲.

شکل ۱-۲. می‌توانید scaling را فقط روی میکروسرویس‌هایی که نیاز دارند هدف بگیرید

Gilt، خرده‌فروش آنلاین مد، به همین دلیل میکروسرویس را پذیرفت. از ۲۰۰۷ با برنامهٔ monolithic Rails شروع کرد و تا ۲۰۰۹ سیستم تحمل بار را نداشت. با جدا کردن بخش‌های هسته، بهتر با spikeهای ترافیک کنار آمد و امروز بیش از ۴۵۰ میکروسرویس دارد، هر کدام روی چند ماشین جدا.

با پذیرش سیستم‌های on-demand provisioning مثل AWS، می‌توانیم scaling را on-demand برای بخش‌های لازم اعمال کنیم و هزینه را بهتر کنترل کنیم. کم نیست که رویکرد معماری این‌قدر به صرفه‌جویی فوری هزینه نزدیک باشد.

سهولت deployment

یک تغییر یک‌خطی در برنامهٔ monolithic میلیون‌خطی مستلزم deploy کل برنامه برای release تغییر است. deployment با impact بالا و ریسک بالا. در عمل، چنین deploymentهایی به‌ندرت انجام می‌شوند به‌خاطر ترس قابل‌درک. متأسفانه تغییرات بین releaseها انباشته می‌شوند تا نسخهٔ جدید با انبوهی از تغییرات به production برسد. و هرچه delta بین releaseها بزرگ‌تر باشد، ریسک اشتباه بیشتر است!

با میکروسرویس‌ها می‌توانید یک سرویس را تغییر دهید و مستقل از بقیه deploy کنید. کد سریع‌تر deploy می‌شود. اگر مشکلی پیش آید، سریع به یک سرویس محدود می‌شود و rollback آسان است. قابلیت جدید سریع‌تر به مشتری می‌رسد. یکی از دلایل اصلی استفادهٔ Amazon و Netflix از این معماری‌ها، حذف موانع تحویل نرم‌افزار است.

فناوری این حوزه در چند سال اخیر زیاد تغییر کرده و در (ارجاع آینده) عمیق‌تر دربارهٔ deployment در دنیای میکروسرویس صحبت می‌کنیم.

هم‌راستایی سازمانی

بسیاری از ما مشکلات تیم‌های بزرگ و codebaseهای بزرگ را تجربه کرده‌ایم. وقتی تیم توزیع‌شده است بدتر می‌شود. می‌دانیم تیم‌های کوچک‌تر روی codebaseهای کوچک‌تر productiveترند. میکروسرویس‌ها معماری را بهتر با سازمان هم‌راستا می‌کنند و تعداد افراد روی هر codebase را در نقطهٔ بهینهٔ اندازهٔ تیم نگه می‌دارند. می‌توانیم مالکیت سرویس‌ها را بین تیم‌ها جابه‌جا کنیم تا افراد روی یک سرویس colocated بمانند. در (ارجاع آینده) هنگام بحث قانون Conway جزئیات بیشتری می‌دهیم.

ترکیب‌پذیری (Composability)

یکی از وعده‌های کلیدی سیستم‌های توزیع‌شده و معماری service-oriented، باز کردن فرصت‌های reuse قابلیت‌هاست. با میکروسرویس‌ها، قابلیت‌ها را به روش‌های مختلف برای اهداف مختلف consume می‌کنیم. این هنگام فکر کردن به نحوهٔ استفادهٔ consumerها از نرم‌افزارمان مهم است. دیگر نمی‌توانیم فقط به وب‌سایت دسکتاپ یا اپ موبایل فکر کنیم. باید به روش‌های بی‌شماری که می‌خواهیم قابلیت‌ها را برای وب، اپ native، موبایل وب، تبلت یا wearable ببافیم فکر کنیم. با دور شدن سازمان‌ها از کانال‌های باریک به سمت engagement جامع مشتری، به معماری‌هایی نیاز داریم که همگام بمانند.

با میکروسرویس‌ها، درزهایی در سیستم باز می‌کنیم که طرف‌های بیرونی به آن‌ها دسترسی دارند. با تغییر شرایط، می‌توانیم چیزها را متفاوت بسازیم. در برنامهٔ monolithic اغلب یک درز coarse-grained دارید که از بیرون قابل استفاده است. برای شکستن آن به چیز مفیدتر، به چکش نیاز دارید! در (ارجاع آینده) راه‌های شکستن سیستم‌های monolithic موجود و تبدیل آن‌ها به میکروسرویس‌های قابل استفادهٔ مجدد را بحث می‌کنم.

بهینه‌سازی برای جایگزینی‌پذیری

اگر در سازمان متوسط یا بزرگ‌تر کار می‌کنید، احتمالاً از سیستم legacy بزرگ و ناخوشایندی در گوشه‌ای آگاهید — آن که کسی نمی‌خواهد لمس کند، برای شرکت حیاتی است اما با Fortran عجیب نوشته شده و فقط روی سخت‌افزار end-of-life اجرا می‌شود. چرا جایگزین نشده؟ می‌دانید: کار خیلی بزرگ و پرریسک است.

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

تیم‌هایی که از میکروسرویس استفاده می‌کنند، راحت‌اند وقتی لازم است سرویس را کاملاً بازنویسی یا kill کنند. وقتی codebase فقط چند صد خط است، دشوار است به آن وابسته شوید و هزینهٔ جایگزینی کم است.

معماری service-oriented چطور؟

معماری service-oriented (SOA) رویکردی است که چند سرویس برای ارائهٔ مجموعه‌ای از قابلیت‌ها همکاری می‌کنند. سرویس اینجا معمولاً فرآیند سیستم‌عامل جداست. ارتباط از طریق فراخوانی شبکه است نه فراخوانی method در مرز فرآیند.

SOA برای مقابله با چالش‌های برنامه‌های monolithic بزرگ ظهور کرد. هدفش ترویج reusability نرم‌افزار است؛ دو یا چند برنامهٔ end-user می‌توانند از همان سرویس‌ها استفاده کنند. نگهداری یا بازنویسی را آسان‌تر می‌کند چون در تئوری می‌توانید یک سرویس را با دیگری جایگزین کنید بدون اینکه کسی بفهمد، تا وقتی semantics سرویس زیاد تغییر نکند.

SOA در اصل ایدهٔ معقولی است. اما با وجود تلاش‌های زیاد، consensus خوبی روی انجام درست SOA نیست. به نظرم صنعت به‌اندازهٔ کافی holistic به مشکل نگاه نکرده و جایگزین قانع‌کننده‌ای به روایت vendorها ارائه نکرده است.

بسیاری از مشکلاتی که به SOA نسبت داده می‌شود، در واقع مشکلات پروتکل‌های ارتباطی (مثل SOAP)، middleware فروشنده، نبود راهنمایی دربارهٔ granularity سرویس، یا راهنمایی اشتباه در انتخاب محل شکستن سیستم است. در بقیهٔ کتاب هر کدام را بررسی می‌کنیم. یک cynic ممکن است بگوید vendorها حرکت SOA را co-opt کردند (و گاهی هدایت کردند) برای فروش محصول بیشتر، و همان محصولات در نهایت هدف SOA را تضعیف کردند.

بسیاری از حکمت متعارف دربارهٔ SOA به شما نمی‌گوید چگونه چیز بزرگ را به چیز کوچک بشکند. دربارهٔ «چقدر بزرگ، خیلی بزرگ است» کافی صحبت نمی‌کند. راه‌های عملی کافی برای جلوگیری از coupling بیش از حد سرویس‌ها نمی‌گوید. چیزهایی که گفته نمی‌شوند منشأ بسیاری از pitfalls مرتبط با SOA هستند.

رویکرد میکروسرویس از کاربرد واقعی برخاسته و با درک بهتر سیستم‌ها و معماری، SOA را درست انجام می‌دهد. پس میکروسرویس‌ها را رویکرد خاصی برای SOA بدانید، همان‌طور که XP یا Scrum رویکردهای خاصی برای Agile هستند.

تکنیک‌های دیگر تجزیه

وقتی به آن نگاه می‌کنید، بسیاری از مزایای معماری میکروسرویس از ماهیت granular و انتخاب‌های بیشتر برای حل مسئله می‌آید. آیا تکنیک‌های تجزیهٔ مشابه می‌توانند همان مزایا را بدهند؟

کتابخانه‌های مشترک

تکنیک استاندارد تجزیه که در تقریباً هر زبانی هست، شکستن codebase به چند کتابخانه است — از شخص ثالث یا داخل سازمان.

کتابخانه‌ها اشتراک قابلیت بین تیم‌ها و سرویس‌ها را می‌دهند. مثلاً مجموعه‌ای از utilityهای collection یا کتابخانهٔ آمار قابل reuse.

تیم‌ها می‌توانند حول کتابخانه‌ها سازمان‌دهی شوند و کتابخانه‌ها reuse شوند. اما معایبی دارد.

اول، ناهمگونی واقعی فناوری را از دست می‌دهید. کتابخانه باید همان زبان یا حداقل همان platform باشد. دوم، سهولت scale مستقل بخش‌های سیستم محدود می‌شود. سوم، مگر dynamically linked libraries استفاده کنید، نمی‌توانید کتابخانهٔ جدید را بدون redeploy کل فرآیند deploy کنید. و شاید مهم‌تر: درزهای واضح برای اقدامات ایمنی معماری برای resilience سیستم ندارید.

کتابخانه‌های مشترک جای خود را دارند. کد مشترک برای وظایفی که خاص domain کسب‌وکار نیست و می‌خواهید در سازمان reuse کنید، کاندیدای کتابخانه است. باید مراقب باشید. کد مشترک برای ارتباط بین سرویس‌ها می‌تواند نقطهٔ coupling شود — در فصل ۲ بحث می‌کنیم.

سرویس‌ها باید از کتابخانه‌های شخص ثالث برای reuse کد مشترک استفاده کنند، اما همهٔ راه را نمی‌پوشانند.

ماژول‌ها

برخی زبان‌ها تکنیک‌های modular decomposition فراتر از کتابخانهٔ ساده دارند و مدیریت lifecycle ماژول را می‌دهند تا در فرآیند در حال اجرا deploy شوند بدون خاموش کردن کل فرآیند.

Open Source Gateway Initiative (OSGI) را به‌عنوان رویکرد technology-specific به modular decomposition نام می‌برم. Java خود مفهوم واقعی module ندارد و باید حداقل تا Java 9 صبر کنیم. OSGI که از framework برای plug-in در Eclipse Java IDE برخاست، اکنون module را در Java از طریق کتابخانه retrofit می‌کند.

مشکل OSGI این است که lifecycle management ماژول را بدون پشتیبانی کافی در زبان enforce می‌کند. نویسندگان ماژول کار بیشتری برای isolation درست انجام می‌دهند. در مرز فرآیند، راحت‌تر است ماژول‌ها overly coupled شوند. تجربهٔ من و همکاران در صنعت این است که حتی با تیم‌های خوب، OSGI به منبع پیچیدگی بزرگ‌تر از مزایایش تبدیل می‌شود.

Erlang رویکرد متفاوتی دارد؛ ماژول‌ها در runtime زبان bake شده‌اند. Erlang رویکرد بالغ modular decomposition است. ماژول‌های Erlang را می‌توان stop، restart و upgrade کرد. Erlang حتی اجرای بیش از یک نسخهٔ ماژول را پشتیبانی می‌کند.

قابلیت‌های ماژول Erlang impressive است، اما حتی با چنین platformی، همان کمبودهای کتابخانهٔ مشترک را داریم: محدودیت فناوری جدید، scale مستقل محدود، drift به integration overly coupling، و نبود درز برای اقدامات ایمنی معماری.

یک مشاهدهٔ نهایی: از نظر فنی باید بتوان moduleهای well-factored و مستقل در یک فرآیند monolithic ساخت. اما به‌ندرت می‌بینیم. ماژول‌ها زود tightly coupled با بقیهٔ کد می‌شوند. جداسازی مرز فرآیند hygiene تمیز را enforce می‌کند (یا حداقل کار اشتباه را سخت‌تر می‌کند!). این نباید محرک اصلی جداسازی فرآیند باشد، اما جالب است که وعدهٔ جداسازی modular در مرز فرآیند در دنیای واقعی به‌ندرت تحقق می‌یابد.

پس modular decomposition در مرز فرآیند ممکن است بخواهید انجام دهید، اما به‌تنهایی همه‌چیز را حل نمی‌کند. اگر فروشگاه pure Erlang هستید، کیفیت module Erlang شاید خیلی راه ببرد؛ اما بسیاری از ما در آن وضعیت نیستیم. برای بقیه، ماژول‌ها مزایای مشابه کتابخانه‌های مشترک دارند.

گلولهٔ نقره‌ای نیست

قبل از پایان، باید بگویم میکروسرویس‌ها ناهار رایگان یا گلولهٔ نقره‌ای نیستند و به‌عنوان golden hammer انتخاب بدی هستند. همهٔ پیچیدگی‌های سیستم‌های توزیع‌شده را دارند و اگرچه زیاد یاد گرفته‌ایم چگونه سیستم‌های توزیع‌شده را خوب مدیریت کنیم (در سراسر کتاب بحث می‌کنیم)، هنوز سخت است. اگر از monolithic می‌آیید، باید در deployment، testing و monitoring خیلی بهتر شوید تا مزایا را باز کنید. همچنین باید متفاوت فکر کنید چگونه سیستم‌ها را scale و resilient نگه دارید. تعجب نکنید اگر distributed transaction یا قضیهٔ CAP سردرد بدهد!

هر شرکت، سازمان و سیستم متفاوت است. عوامل زیادی تعیین می‌کنند میکروسرویس‌ها برای شما مناسب‌اند یا چقدر تهاجمی می‌توانید بپذیرید. در هر فصل راهنمایی و pitfalls احتمالی می‌دهم تا مسیر پایدار بکشید.

جمع‌بندی

امیدوارم اکنون بدانید میکروسرویس چیست، چه چیزی آن را از تکنیک‌های ترکیبی دیگر متمایز می‌کند و برخی مزایای کلیدی چیست. در فصل‌های بعد جزئیات بیشتری دربارهٔ دستیابی به این مزایا و اجتناب از pitfalls رایج می‌دهیم.

موضوعات زیادی هست، اما باید جایی شروع کنیم. یکی از چالش‌های اصلی میکروسرویس‌ها، تغییر نقش کسانی است که اغلب تکامل سیستم‌ها را هدایت می‌کنند: معماران. در فصل بعد برخی رویکردهای مختلف به این نقش را می‌بینیم که از این معماری جدید بیشترین بهره را ببریم.