با شکستن یک برنامه یک-تکه(مانولیت) به مجموعهای از سرویس های کوچکتر ما با مسائل جدید مواجه میشویم که ذاتی سیستمهای توزیع شده میباشد و باید برای آنها راهکاری داشته باشیم. یکی از این مسائل بحث تراکنش هایی است که قبلاً در سطح یک پراسس و یک دیتابیس(معمولا)مدیریت میشد و در حال حاضر این تراکنش بین چندین سرویس پخش شده است. به عنوان مثال یک سیستم مدیریت سفارش در یک سیستم گردشگری آنلاین را در نظر بگیرید. فردی درخواست سفارش هتل و پرواز را دارد. در صورتی که پس از رزرو پرواز مشخص شود که برای فرد هتلی در روز درخواست شده با ظرفیت کافی در دسترس نیست باید عملیات قبلی(پرواز رزرو شده) کنسل شود(Roll back). عملیات رزرو(هتل و پرواز) تنها زمانی نهایی خواهد شد که فرد اقدام به پرداخت صورتحساب نماید(مسئله عنوان شده در اینجا چه در حالتی که یک برنامه یک-تکه داریم و چه در حالت داشتن چندین سرویس یک مسئله از نوع Long Live Transaction(LLT) می باشد.).
قبل از شکستن برنامه یک-تکه به مجموعهای از سرویس های کوچکتر تمام ماژول های مورد نیاز همه در یک پراسس اجرا میشدند و در نتیجه به هنگام نیاز به تعامل و صحبت بین ماژول های مختلف ما با صدا زدنهای درون سرویسی (In-Process Communication) سروکار داشتیم. به عنوان مثال ماژول Order با درخواست ماژول مدیریت هتل(به عنوان مثال با درخواست اینترفیس آن و تزریق از طریق سازنده) میتوانست براحتی با ماژول مدیریت هتل ارتباط برقرار کند و درخواست رزرو هتل را به ماژول مورد نظر delegate کند.
ماژول های برنامه یک-تکه گردشکری آنلاین مورد بحث حالا به سرویس های کوچکتری از جمله سرویس مدیریت هتل، سرویس مدیریت پرواز و سرویس پرداخت شکسته شده است و هر سرویس جداگانه توسعه و منتشر می شود. در این حالت ما نیاز به راه حلی جهت صحبت بین سرویس های مختلف خواهیم داشت.
در این بخش در مورد دو روش متداول جهت ارتباط و تعامل سرویس ها با مبادله پیام صحبت خواهم کرد.
2-روش Orchestration
در این روش یک نقطه مرکزی جهت مدیریت بخاطر سپاری وضعیتهای مختلف تشکیلدهنده تراکنش کلی وجود دارد. این نقطه ی مرکزی تمام گام ها جهت تکمیل(موفقیت آمیز یا شکست آمیز) یک تراکنش همانند مثالی که عنوان شده را بصورت کامل می داند. نقطه ی شروع هر گام و همچنین سرویسی که وظیفه ی انجام آن گام را بر عهده دارد را میشناسد. در مثال عنوان شده نقطه ی مرکزی ابتدا درخواست رزرو هتل را به سرویس هتل میفرستد. در این حالت سفارش مشتری در حالت در انتظار رزرو هتل می باشد. با تکمیل هر گام سفارش یک وضعیت جدید پیدا می کند. پس از دریافت پیغام موفقیت آمیز رزرو هتل از سرویس هتل وضعیت سفارش به رزرو هتل تغییر می کند. سپس نقطه ی مرکزی درخواست سفارش پرواز را به سرویس مدیریت پرواز ارسال می کند. و وضعیت میتواند به وضعیت “در انتظار رزرو پرواز” تغییر کند. پس از دریافت پیغام موفقیت آمیز رزرو هواپیما توسط سرویس مدیریت پرواز وضعیت سفارش به رزرو هواپیما تغییر کرده و سپس درخواست به سیستم پرداخت جهت پرداخت هزینه سفارش ارسال می شود. پس از پرداخت موفقیت آمیز هزینه سفارش، سفارش به وضعیت تکمیل شده تغییر وضعیت می دهد. در صورتی که در هر مرحله مشکلی بوجود بیاد نقطه ی مرکزی میتواند با طی کردن بر عکس گام های سپری شده و ارسال درخواست های لغو کردن سفارش( Request Compensating) اقدام به لغو تدریجی منابع سفارش شده و در نتیجه لغو کردن کل درخواست سفارش کند. نقطه ی مرکزی در این روش Orchestrator نامیده می شود.
2-1-مزایای این روش:
2-2-اما معایب این روش:
منتقدان روش بالا بخصوص با تأکید بر مشکل دوم این روش را تقبیح کرده و بصورت افراطی سعی در استفاده از روش دوم که در زیر توضیح داده خواهد شد دارند.
3-روش Choreography
در این روش با حذف نقطه ی مرکزی سعی میشود که نقطه ی مرکزی شکست را از بین برد و همچنین وابستگی بین سرویس ها را نیز از بین برد(خوشحال نباشید در این باره توضیح خواهم داد). در اینجا هر سرویس پس از انجام وظیفه ی خود در قالب یک ایونت به سایر سرویس ها اعلام میکند که کارش را انجام داده است. مثلاً سرویس مدیریت هتل پس از رزرو هتل با ارسال یک ایونت اعلام میدارد که یک هتل در تاریخ مشخص برای یک مشتری خاص رزرو شده است. سایر سرویس ها با گوش دادن به این ایونت فرآیند را ادامه خواهند داد. مثلاً در اینجا سرویس مدیریت سفارش وضعیت سفارش را تغییر خواهد داد. و سپس سرویس مدیریت پرواز عملیات خود را شروع می کند.
همانطور که ملاحضه می کنید در این روش نقطه مرکزی که در مورد آن نگرانی داشتیم از بین رفته است. سرویس های بصورت loosely couple با یکدیگر ارتباط دارند. ارتباط بین سرویس ها بصورت ارسال مسیج و گوش داد به مسیج ها در طرف دیگر ارتباط می باشد.
3-1-مزیت ها:
3-2-معایب:
یکی از نکات مهمی که در مورد این دو روش بیشتر مورد تاکید می باشدبحث وابستگی شدید/ضعیف بین سرویس ها است. ابتدا باید توجه داشت که بین اجزای تشکیل دهنده یک فرآیند گاها بصورت ذاتی وابستگی وجود دارد و در نتیجه حذف و از بین بردن واسبتگی در این مسائل اساسا بی معنی است. ما فقط می توانیم این جهت این وابستگی را تغیر دهیم.
یکی از ایراداتی که به روش اول گرفته می شود وابستگی سرویس ها که در روش دوم ظاهرا این مشکل حل شده است. اما در روش دوم ما با یک چالش بسیار مهم تر مواجه هستیم. در روش دوم هر سرویس باید وابستگی های ورودی و خروجی خود که بصورت implicit بوجود آمده را کاملا بداند. مثلا سرویس پرداخت صورتحساب باید بداند که چه موقع باید برای انجام عملیات پرداخت تریگر شود(وابستگی های خروجی از سرویس پرداخت به سایر سرویس ها) و هم اینکه باید خبر داشته باشد که چه سرویس هایی احیانا پس از اتمام عملیات پرداخت نسبت به نتایج آن و ادامه فرآیند علاقمند هستند و بر اساس آن اقدام به ارسال مسیج اتمام موفقیت آمیز عملیات پرداخت نماید.(واسبتگی های ورودی از سایر سرویس ها).
بین اجزای تشکیل دهنده یک فرآیند گاها بصورت ذاتی وابستگی وجود دارد و در نتیجه حذف و از بین بردن واسبتگی در این مسائل اساسا بی معنی است.
بیایید یک مثال دیگر را در بررسی کنیم. فرض کنید میخواهیم کمی فرآیند را تغییر دهیم و مثلا فرآیند رزرو هتل(که در حال حاضر اولین فرآیند است) و فرآیند بلافاصل بعد از آن یعنی رزرو بلیط هواپیما را جابجا کنیم. این تغییر بر روی حداقل دو تا سرویس پخش خواهد شد و دو سرویس تحت تاثیر این تغییر خواهند بود. تاثیر این مورد وقتی تیم های مختلفی درگیر توسعه این دو سرویس باشند مشخص تر و نمایان تر خواهد شد. تغییر که دو تیم مختلف را درگیر خواهد کرد.
همچنین به عنوان مثال در صورتی که تصمیم بگیریم پس از رزرو هواپیما سرویس ترنسفر فرودگاهی را نیز اضافه کنیم این کار هم سرویس رزرو هواپیما و هم سرویس پرداخت و هم احیانا سرویس هایی دیگری که از اتفاقات خروجی این دو سرویس تحت تاثیر قرار میگرفتند را نیز تحت تاثیر قرار می دهد.
به عنوان مثال آخری فرض کنید که سرویس V.I.P. نیز جزو خدماتی بود که پس از رزرو هتل و هواپیما کاربر امکان افرودن آن به سبد خرید را داشت. اما پس از مدتی تصمیم گرفته می شود که این سرویس فقط برای کاربرانی قابل استفاده باشد که سبد خرید آنها به یک مینیمم قیمتی رسیده باشد. به عنوان مثال در صورتی که سبد خرید حداقل 1200000 تومان رسیده باشد کاربر می تواند سرویس V.I.P. فرودگاهی را انتخاب کند در غیر اینصورت باید وارد سرویس پرداخت شده و اقدام به پرداخت نماید. در اینحالت با این چالش مواجه خواهیم شد که این عملیات باید کجا کنترل شود. آیا باید در فرآیند خرید هواپیما چک شود در اینصورت چگونه باید سرویس V.I.P. رد شود. و اینکه سرویس پرداخت باید به چه مسیج هایی گوش دهد و چه موقع باید تریگر شود.
در جواب این سوال باید گفت انتخاب هر کدام از روش های بالا بستگی به شرایط و ماهیت مسیله دارد. هر کدام از روش های بالا معایب و مزایایی دارند که در بالا عنوان شد. برخی از مسایل دارای ماهیتی sequential هستند. و می توان آن فرآیند را به تعدادی مراحل کوچکتر که قابل اجرای پی در پی با ترتیبی مشخص را دارند. برای همچنین مسایلی انتخاب بهتر روش Orchestration می باشد. مثال رزروی که در بالا عنوان شد مثال خوبی از این این دسته مسایل می باشد. در نقطه ی مقابل در یک فرآیند ممکن است ما با ریز فرآیندهایی سروکار داشته باشیم که ضمن اینکه خود آنها در پی بوقوع پیوستن یک رخداد خاص تریگر می شوند اما احتمالا رخ دادن خود این ریز فرآیندها منجر به تریگر شدن ریز فرآیندی دیگری نخواهد شد. یا اینها می توانند بصورت موازی با سایر ریز فرآیندها اعمال و تریگر شوند. مثالی از این ریز فرآیندها ارسال ایمیل یا پیامک به کاربر پس از رزرو هتل یا خرید تور می باشد. اینگونه مسایل گزینه های خوبی برای استفاده از روش Choreography هستند.
بصورت کلی ترکیبی از Orchestration و Choreography بهترین گزینه در اکثر موارد می باشد.
این مقاله نخستین بار در این آدرس منتشر شد.