الگوی Outbox

در این پست به این سوالات پاسخ میدم :1- الگوی Outbox چه مشکلی رو حل می کنه ؟2- الگوی Outbox چطور پیاده سازی میشه ؟3- چالش های این الگو چیه؟4- یک مثال کاربردی از Outbox1- الگوی Outbox چه مشکلی رو حل می کنه ؟در معماری میکروسرویس یا هر معماری ای که ارتباط بین سرویس ها براساس پیام هایی روی Message Broker ها (مانند RabbitMq یا Kafka) باشد ، معمولا سرویس فرستنده پیام ، همزمان با ارسال پیام بایستی دیتاهایی در دیتابیس خود نیز ثبت کند که این فرآیند به چند صورت قابل انجام است :ذخیره اطلاعات در دیتابیس سپس ارسال پیام به Message Brokerمشکل این روش این است که ممکن است اطلاعات با موفقیت ذخیره شود ولی ارسال پیام با موفقیت انجام نشود (مثلا اتصال به Message Broker انجام نشود یا ..) . بنابراین سرویس گیرنده پیام از انجام تراکنش بی خبر است و بخشی از عملیات مورد نظر انجام نخواهد شد .ارسال پیام به Message Broker سپس ذخیره اطلاعاتمشکل این روش برعکس روش قبلی است یعنی ممکن است پیام ارسال شود ولی اطلاعات با موفقیت ذخیره نشود (مثلا اتصال به دیتابیس انجام نشود یا ..) . بنابراین سرویس گیرنده پیام ، پیام اشتباه دریافت خواهد کرد و ممکن است در فرآیند کاری سیستم اختلال ایجاد شود ، مشکل دیگر این روش این است که حتی اگر هر دو عملیات موفقیت آمیز انجام شود ممکن است ذخیره سازی اطلاعات در دیتابیس کمی طول بکشد و در این فاصله ، سرویس گیرنده پیام را دریافت و پردازش کند و ترتیب اجرای عملیات با مشکل مواجه شود .استفاده از Two-phase commitمشکل این روش این است که توسط برخی از دیتابیس ها پشتیبانی نمی شود .استفاده از الگوی Outboxاین روش موضوع این مقاله است و مشکلات روش های قبلی را ندارد و اصطلاحا atomically عملیات ذخیره اطلاعات و ارسال پیام را انجام می دهد .2- الگوی Outbox چطور پیاده سازی میشه ؟یک جدول در دیتابیس با نام outbox اضافه می شود و هنگام ذخیره اطلاعات ، پیام هایی که باید به Message Broker ارسال شوند همزمان با سایر اطلاعات در این جدول ذخیره می شوند .یک سرویس خودکار ، هر چند ثانیه یکبار لیست پیام های جدول Outbox را خوانده و به Message Broker ارسال می نماید و از جدول حذف می کند .با این روش ، مطمئن هستیم که پیام بعد از ذخیره سازی موفق دیتا ، ارسال خواهد شد و ضمنا مطمئن هستیم که پیام ارسال خواهد شد .اگر ذخیره سازی اطلاعات با مشکل مواجه شود پیام ها نیز در جدول outbox ذخیره نخواهند شد (به دلیل اینکه کل اطلاعات با یک تراکنش به دیتابیس ارسال شده است) .اگر ارسال پیام ها به Message Broker با مشکل مواجه شود ، مجددا چند ثانیه دیگر برای ارسال تلاش خواهد شد و این چرحه تا زمان ارسال موفق پیام ها ادامه پیدا خواهد کرد .نکته 1 : می توانید به جای حذف پیام ها از جدول Outbox ، یا یک فیلد bit وضعیت ارسال را تغییر دهید ، این راهکار به شما کمک می کند تا سابقه ارسال پیام ها را در دیتابیس داشته باشید .نکته 2 : برای رعایت ترتیب ارسال پیام ها ، بایستی هنگام ارسال پیام ها را به ترتیب ثبت در جدول واکشی و ارسال کنیم و ضمنا از ارسال موازی پیام ها خودداری کنیم .3- چالش های این الگو چیه؟تنها مشکل این الگو این است که ممکن است پس از ارسال موفق پیام ، عملیات حذف پیام از جدول outbox با موفقیت انجام نشود .راهکار این مشکل Idempotent بودن سرویس گیرنده پیام می باشد . یعنی اگر چند بار یک پیام یکسان را دریافت کرد فقط یکبار پردازش انجام دهد .4- یک مثال کاربردی از Outboxفرض کنید در یک سایت فروشگاهی بعد از ثبت سفارش بایستی پیامک به خریدار ارسال گردد و سرویس سفارش و پیامک جدا هستند .کاربر سرویس سفارش را فراخوانی می کند و درخواست ثبت سفارش را ارسال می نمایند سفارش ساخته شده و همزمان با ثبت اطلاعات سفارش ، دستور ارسال پیام به کاربر نیز در قالب یک Message در جدول Outbox ثبت می گردد و پیام "سفارش با موفقیت ثبت شد" به کاربر نمایش داده می شود .یک سرویس خودکار پیام را از جدول خوانده و به Message Broker ارسال می نماید .سرویس پیامک ، Message را از Broker دریافت نموده و به خریدار پیام ارسال می کند .