بررسی مکانیزم ارسال پیام (Messaging) در معماری مایکروسرویس ها

در این قسمت از آموزش معماری مایکروسرویس ها از وبسایت پرووید در رابطه با موضوع ارسال پیام و یا messaging صحبت خواهیم کرد. در معماری‌های monolithic و نرم‌افزارهایی که بر اساس این معماری ایجاد می‌گردند، قابلیت‌های مختلف برنامه که بر اساس component ها و یا فرآیندهای مختلف پیاده سازی می گردند، توسط فراخوان‌های توابع و یا اصطلاحاً function call ها و یا حتی method call های سطح زبان برنامه نویسی فراخوانی می گردند. این موضوع در معماری‌های سرویس گرا و یا service oriented architecture به روشی کاملاً loosely coupled تر تبدیل شد. لطفاً در رابطه با مفهوم loosely coupled بودن قسمت های مختلف برنامه از بررسی مفاهیم Cohesion و Coupling در توسعه نرم افزار استفاده کنید. در معماری‌های مبتنی بر سرویس ها از service level messaging و یا ارسال پیام در سطح سرویس استفاده می گردد. این پیام ها اصولاً بر اساس SOAP و سوار بر پروتکل هایی از قبیل؛ HTTP و JMS پیاده سازی می گردند. در ادامه کمی بیشتر در رابطه با انواع مختلف پیام ها صحبت خواهیم کرد.پیام‌رسانی همزمان (synchronous messaging) با استفاده از REST و gRPC و GraphQL و Thriftبه منظور پیاده‌سازی synchronous messaging و یا ارسال پیام ها به صورت همزمان در معماری مایکروسرویس ها از REST که مخفف representational state transfer می باشد استفاده می‌کنیم. در رابطه با پیاده‌سازی RESTful API ها توصیه می کنیم از بسته ی آموزش ویدئویی طراحی و پیاده سازی RESTful API در ASP.NET Core 3 و بسته ی آموزش ویدئویی پیاده سازی مباحث پیشرفته RESTful API در ASP.NET Core 3 استفاده کنید. ضمناً منظور از synchronous messaging شرایطی است که در آن client پس از ارسال یک request توقع دارد که response مربوطه را در یک مدت زمان مشخص دریافت کرده و قبل از دریافت کردن response مورد نظر خود، کار دیگری انجام نمی‌دهد.همانطور که گفتیم برای پیاده سازی synchronous messaging، عموماً در معماری مایکروسرویس ها از REST استفاده می شود. دلیل این موضوع سبک ارسال پیام ساده REST و پیاده سازی آن بر روی پروتکل HTTP و مکانیزم ارسال request و response ها می باشد. علاوه بر این؛ مفهوم resource ها در RESTful API ها نیز کار ارسال پیام در معماری مایکروسرویس ها را ساده تر از قبل خواهد کرد. بنابراین امروزه بسیاری از مایکروسرویس ها از HTTP و resource ها به منظور پیاده‌سازی بحث ارسال و دریافت پیام استفاده می‌کنند. تصویر زیر استفاده کردن از REST در مایکروسرویس ها را نشان می‌دهد.علاوه بر REST، گزینه دیگری که در معماری مایکروسرویس ها، رفته رفته محبوبیت خاصی را کسب کرده است gRPC می باشد. gRPC یک تکنولوژی ارتباط بین فرایندی و یا اصطلاحاً inter-process communication است و به عنوان جایگزینی برای سرویس‌های RESTful مورد استفاده قرار می گیرد. علاوه بر این؛ با استفاده از gRPC به سادگی می توانید برنامه هایی که به صورت توزیع شده و ناهمجنس پیاده سازی گردیده اند را مورد استفاده قرار داده و به آنها متصل شده و حتی آنها را debug کنید. این کار به سادگی انجام می‌پذیرد و تمامی کار شبیه به انجام کار به صورت local است. علیرغم اتفاقی که در REST می افتد، به سادگی با استفاده از gRPC می توانیم service contract را با استفاده از زبان interface definition language مربوط به gRPC که مبتنی بر protocol buffer می‌باشد تعریف کنیم و پس از انجام این کار، service و کد client مورد نظر را بر اساس زبان برنامه نویسی مطلوب خود تولید نمایید.گزینه بعدی استفاده کردن از GraphQL می باشد. GraphQL امروزه رفته‌رفته محبوبیت بیشتری را در شرایطی که service contract مشخصی وجود ندارد، کسب کرده است. در واقع GraphQL یک زبان query گرفتن از API ها و البته یک runtime برای پاسخ دادن به آن query ها بر اساس آن داده‌های موجود می باشد. از نقطه نظر عملکرد، GraphQL نسبت به دیگر پروتکل های ارتباط client و server کمی متفاوت عمل می‌کند. این تفاوت بیشتر در این قضیه پیاده سازی شده است که با استفاده از GraphQL به سادگی می توان گفت که داده های موجود می بایست در چه قالب و یا فرمتی در دسترس قرار بگیرند و یا اینکه به چه شکل دریافت گردند.علاوه بر این گزینه‌ها، گزینه بعدی استفاده کردن از Thrift می باشد. از این تکنولوژی زمانی استفاده می شود که شما بتوانید interface مربوط به معماری مایکروسرویس خود را تعریف کنید. از Thrift به عنوان یک جایگزین برای ارسال و دریافت پیام ها با استفاده از REST و پروتکل HTTP استفاده می‌کنیم. بسیاری از سبک های ارسال و دریافت request و response های synchronous، بیشتر برای service ها و client هایی مناسب هستند که به صورت تعاملی کار می‌کنند و نیاز دارند که به صورت realtime داده هایی را دریافت کنند و این کار را با استفاده از یک API انجام بدهند.ارسال پیام های ناهمزمان (asynchronous messaging) با استفاده از Kafka، NATS، AMQP، STOMP، MQTTعلاوه بر ارسال پیام ها به صورت synchronous، مکانیزم دیگر ارتباط سرویس ها با یکدیگر، ارسال پیام ها به صورت asynchronous و اصطلاحاً مبتنی بر رویداد و یا event driven می باشد. با مکانیزم asynchronous messaging و event driven بودن آن، یک client منتظر دریافت یک response از سرور نمی ماند. برای چنین سناریوهایی، معماری مایکروسرویس ها می توانند از پروتکل های ارسال پیام از قبیل، Kafka، NATS، AMQP، STOMP و MQTT استفاده کنند. علیرغم اتفاقی که در بسیاری از پروتکل های ارسال پیام سنتی رخ می‌دهد، تکنولوژی های Kafka و NATS یک زیرساخت ساده برای ارسال پیام های توزیع شده را در اختیار ما قرار می‌دهند که برای ساختن معماری مایکروسرویس ها به مراتب مناسب تر می باشند.در چنین شرایطی اصطلاحاً producer ها و consumer های مربوط به پیام‌ها، تمامی business logic را در اختیار خواهند داشت و این در حالی است که broker هیچگونه business logic خاصی را در دسترس نخواهد داشت.قالب پیام ها: JSON، XML، Thrift، ProtoBuf و Avroیکی دیگر از عوامل بسیار مهم در روند موفقیت پیاده سازی معماری مایکروسرویس ها، استفاده کردن از قالب و فرمتی مناسب برای پیام های ارسالی و دریافتی می‌باشد. اپلیکیشن ها و نرم افزارهای سنتی monolithic از قالب های binary پیچیده استفاده می‌کردند و این درحالی است که معماری های سرویس گرا و نرم افزارهای مبتنی بر وب سرویس ها از پیام‌های متنی مبتنی بر فرمت های پیچیده از قبیل؛ SOAP و XSD استفاده می‌کنند.بسیاری از نرم افزارهای مبتنی بر معماری مایکروسرویس ها از قالب های مبتنی بر text از قبیل؛ JSON و XML که سوار بر HTTP REST API می باشند، استفاده می‌کنند. در رابطه با xml می توانید از آموزش ویدئویی پرس و جو داده ها با LINQ to XML در سی شارپ استفاده کنید. علاوه بر این؛ در رابطه با REST API ها می توانید از بسته ی آموزش ویدئویی پیاده سازی مباحث پیشرفته RESTful API در ASP.NET Core 3 استفاده کنید.در شرایطی که نیاز به فرمت های binary داریم، معماری مایکروسرویس ها می توانند از فرمت هایی از قبیل؛ Thrift و ProtoBuf و Avro استفاده نمایند.تعریف کردن service contract و یا interface ها: OpenAPI/Swagger، gRPC IDL، GraphQL schema و Thrift IDبعد از پیاده سازی یک قابلیت و نیازمندی تجاری، به عنوان یک service می بایست که service contract را تعریف و آن را publish کنید. در نرم افزارهای monolithic سنتی، قابلیت هایی برای انجام چنین کاری وجود نداشت. اما در فضای معماری سرویس گرا و استفاده از وب سرویس ها اغلب از WSDL به منظور تعریف کردن service contract استفاده می‌شود. اما مشکلی که WSDL دارد این است که به عنوان یک راهکار ایدهآل برای تعریف کردن contract در معماری مایکروسرویس ها نمی توان از آن استفاده کرد. دلیل این موضوع این است که WSDL نمی‌تواند REST را به عنوان یک موضوع مهم پیاده سازی کند.از آنجایی که ما معماری مایکروسرویس را سوار بر سبک معماری REST پیاده سازی می کنیم، می‌توانیم از تکنیک‌های تعریف کردن REST API به منظور تعریف کردن contract در معماری مایکروسرویس ها استفاده نماییم. بنابراین مایکروسرویس ها از زبان های استاندارد تعریف REST API از قبیل؛ Swagger و RAML به منظور تعریف کردن service contract استفاده می‌کنند.برای دیگر پیاده‌سازی معماری‌های مایکروسرویس ها که بر اساس HTTP REST ایجاد نشده اند می‌توانیم از IDL استفاده کنیم. با استفاده از GraphQL نیز می توانیم service schema را تعریف کنیم. در این راستا GraphQL و schema مربوط به آن توسط client ها مورد استفاده قرار می گیرند تا بتوانند API های مبتنی بر GraphQL را query بزنند.