رویکرد پیشنهادی برای ارسال / دریافت ایونت در معماری Event Driven

در معماری Event Driven بخش مهمی از ارتباط بین سرویس ها از طریق Message و در بستر Message Broker می باشد .این Message ها ممکن است Event یا Command باشند .ایونت ها از وقوع اتفاقی در گذشته خبر می دهند و کامندها برای اجرای دستور خاصی می باشند .معمولا ایونت ها به صورت Broadcast ارسال می شوند (یک فرستنده و نامحدود گیرنده) و کامندها به صورت Direct (یک فرستنده و یک گیرنده مشخص) ارسال می شوند .این مطلب در مورد ایونت هاست و راهکاری برای کاهش برخی از مشکلات این نوع پیام ارائه می دهد .مثال :برای ارسال ایونت ، یک مثال ساده می تواند این باشد که در یک ساختار میکروسرویس ، یکی از سرویس ها سرویس User می باشد و سایر سرویس ها بخشی از اطلاعات کاربران را با هدف کاهش وابستگی نزد خود نگه می دارند مثلا سرویس Comment اسم ، تصویر و آی دی کاربر را در دیتابیس خود نگه می دارد که هنگام نمایش لیست کامنت ها اسم کاربر را نیز نمایش دهد بدون اینکه نیاز به ارسال درخواست به سرویس User باشد .در این مثال هر زمانی که کاربر جدیدی ثبت می شود یا نام کاربری تغییر می کند سرویس User یک ایونت برای سایر سرویس ها ارسال می کند که اطلاعات یوزر را بروزرسانی کنند .برخی از مشکلاتی که ممکن است در این روش وجود داشته باشد :عدم تطابق ترتیب دریافت ایونت ها با ترتیب ارسال آنها : با وجود اینکه ساختار Message Broker ها براساس صف (و طبیعتا رعایت ترتیب) می باشد اما بعضی مسائل مانند خواندن همزمان چند پیام از روی صف ممکن است ترتیب پردازش ایونت ها رو تغییر دهد .جاافتادن یک ایونت در سرویس گیرنده : در رویکرد Event Driven هیچ زمانی به صورت 100% نمی توان مطمئن بود که پیام های ارسالی توسط سرویس های دیگر دریافت و پردازش شود . حال اگر یک پیام پردازش نشود و پیام های بعدی مربوط به آن Object (مثلا یک کاربر خاص در مثال ما) پردازش شود ممکن است برای همیشه دیتای مربوطه ناقص بماندتنوع زیاد ایونت های ارسالی : اگر ایونت های ارسالی مربوط به یک object پیچیده با تعداد Property های زیاد باشد احتمالا تنوع ایونت های ارسالی بسیار زیاد خواهد بود به عنوان مثال اگر برای تغییرات یک Product بخواهیم ایونت ارسال کنیم برخی از نوع ایونت ها شامل تغییر نام و مشخصات / تغییر قیمت / تغییر تصاویر و.. خواهند بود .نیاز به راهکار موازی برای اطمینان : اگر هنگام نیاز به اون موجودیت در سرویس گیرنده ایونت ، با یک آی دی خاص موجودیت بافت نشود مجبوریم یه api call به سرویس فرستنده ایونت بزنیم و از وجود/عدم وجود اون آی دی مطمئن شویم .راهکار پیشنهادی :برای حل این مشکل می توان به ازای هر Type یک ایونت شامل id و UpdateTime داشت و سرویس های دریافت کننده ، صرفا یک Consumer دارند که به محض دریافت این ایونت ، اطلاعات فعلی را از سرویس اصلی دریافت کرده و پردازش مورد نیاز را انجام می دهند .در مثال بالا ، سرویس User در زمان ایجاد کاربر جدید ، بروزرسانی اطلاعات کاربر و حذف کاربر ایونتی را ارسال خواهد کرد با نام UserChanged و شامل آی دی کاربر و زمان وقوع اتفاق .هر سرویس دیگری (مانند سرویس کامنت) هنگام دریافت این ایونت ، Api سرویس User را صدا زده و کلیه اطلاعات کاربر را دریافت خواهد کرد و دیتای خود را بروزرسانی می کند .چالش این راهکار ، نیاز به Api Call در زمان پردازش ایونت هاست که به دلایل زیر مشکلی ایجاد نمی کند :کاهش Performance : معمولا سرویس های میکروسرویس آمادگی پاسخدهی به تعداد زیادی Query دارند بنابرین اضافه شدن یک Api Call به ازای هر ایونت / سرویس ، هزینه خاصی را به سرویس فرستند تحمیل نمی کند .وابستگی سرویس ها : اگر در زمان پردازش ایونت ، سرویس فرستنده به هر دلیلی امکان ارائه دیتا نداشت با استفاده از رویکردهای retry در Consumer ها پردازش پیام به زمان دیگری موکول خواهد شد .