ایجاد پروژه مایکروسرویس

در این آموزش قرار است که دو مایکروسرویس را توسعه بدهیم و با استفاده از Service Bus ای به نام RabbitMQ بین آنها ارتباط برقرار کنیم.

Service Bus چیست؟

یک سرویس است که به آن می توان Message فرستاد. این Message ها می توانند از نوع Command یا Event باشند. Service bus دارای یک یا چند SubScriber است که آنها می توانند نوع خاصی از Message ها را برای سرویس های خاصی SubScribe کنند. وقتی یک Message خاص برای یک سرویس خاص Subscribe می شود، تنها آن سرویس می تواند از آن استفاده کند.

فرض کنید که ما یک Message یا Command برای ایجاد User داریم. و آن را به Service bus می فرستیم. از طرفی یک User Service وجود دارد که پیام هایی از جنس ایجاد یا مدیریت User را SubScribe کرده است. پس موقعی که User Service متوجه شود که Message ای از نوع ایجاد User به سمت Service Bus فرستاده شده است از آن پیام استفاده می کند و User را ایجاد می نماید. حال User Service یک Message دیگر مثلا از نوع Event تولید می کند و مقدار آن به عنوان مثال این است: User ایجاد شد و غیره . . .

پس Message ای که از نوع Command باشد، قرار است کاری انجام دهد و Message ای که از نوع Event باشد خبر از آن می دهد که کاری انجام شده است.

RabbitMQ چیست؟

یکی از معروف ترین Service bus هاست و از آن به عنوان یک Message broker یاد می شود. برای نصب و استفاده از RabbitMQ سه راه وجود دارد.

  1. نصب RabbitMQ از سایت https://rabbitmq.com
  2. نصب Docker مخصوص RabbitMQ از سایت https://hub.docker.com/_/rabbitmq
  3. و استفاده از سرویس موجود در سایت https://cloudamqp.com

 

نصب RabbitMQ

ابتدا Docker را نصب کنید و در آن Sign Up کنید. سپس Powershell را به صورت Run as administrator اجرا کرده و دستور زیر را تایپ کنید:

docker pull rabbitmq

یا

docker pull rabbitmq:3.9.0-rc.1-management-alpine

با دستور زیر RabbitMQ را اجرا کنید.

docker run -p 5672:5672 rabbitmq

یا

docker run –rm -it –hostname my-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management

چند نکته

در این قسمت یک پروژه ایجاد می کنیم که سه لایه خواهد داشت:

  • Common از جنس Class Library
  • Gateway از جنس Console
  • IdentityService از جنس Console

 

لایه ی Common مسئول تعریف Command ها و Event ها و کلاس های Helper خواهد بود.

وظیفه ی لایه ی Gateway آماده سازی Command و ارسال آن به Service Bus است. همچنین وظیفه ی دریافت Event از Service Bus را نیز بر عهده دارد.

لایه ی  Identity Service مسئول دریافت Command از Service Bus است. این لایه Command را مصرف می کند (دریافت کرده و روی آن پردازش مورد نیاز را انجام می دهد) سپس یک Event تولید می کند و آن را به Service Bus می فرستد.

لایه ی Gateway چون قبلا این Event را Subscribe کرده بود به راحتی آن را از Service Bus دریافت می کند و آن را مصرف می کند.

در این پروژه یک Command به نام CreateUser تعریف می کنیم. سپس در پروژه ی Identity Service آن را Subscribe کرده و در پروژه ی Gateway آن را Push یا Publish می کنیم، یعنی آن را به Service Bus می فرستیم. سپس پروژه ی Identity Service آن را دریافت کرده و روی آن پردازش انجام می دهد. (به عنوان مثال User را ایجاد می کند.) سپس یک Event تولید می کند و دوباره آن را به Service Bus می فرستد. پروژه ی Gateway این Event را دریافت می کند و می فهمد که User ایجاد شده است یا خیر.

در این آموزش ما از یک Nuget به نام RabbitMQ.Client استفاده می کنیم که وظیفه ی برقراری ارتباط با Service Bus که همان RabbitMQ است را بر عهده خواهد داشت.

در این آموزش سعی بر آن شده که مطالب به زبان بسیار ساده آموزش داده شود. برای همین در بعضی جاها امکان دارد که اصول پایه ای SOLID رعایت نشده باشد. طبیعی است که رعایت این اصول ضروری است اما بهتر است بعد از اینکه به مفاهیم پایه ای مایکروسرویس مسلط شدید از آن اصول استفاده کنید در غیر این صورت خود را دچار پیچیدگی های بیهوده کرده اید. به عنوان مثال امکان دارد که یک متد دو وظیفه را انجام دهد و با این کار اصل تک وظیفه ای SOLID را نقض کند. (Single Responsibility Principle)

 

ایجاد پروژه Common

یک Solution به نام Gateway Console می سازیم و در آن یک پروژه از جنس Class Library به نام Common  می سازیم. سپس دو پوشه به نام های Commands و Events در آنها ایجاد می کنیم.

در پوشه ی Commands یک اینترفیس به نام ICommands می سازیم که کد آن به مانند زیر خواهد بود.

این اینترفیس هیچ متدی نخواهد داشت و به اصطلاح به آن Marker Interface می گویند. پیام هایی که این اینترفیس را پیاده سازی کنند در دسته بندی Command ها قرار می گیرند. بعدا یک Marker interface  مخصوص Event ها نیز خواهیم ساخت.

سپس یک کلاس Command در همین پوشه می سازیم که نامش CreateUser خواهد بود.

این پیام شامل دو Property است و هدف از آن این است که هر کسی که قرار است این Command را مصرف کند باید از این دو Property برای ثبت User استفاده کند.

در پوشه ی Events یک اینترفیس به نام IEvent ایجاد می کنیم.

یک کلاس Event به نام UserCreated به مانند زیر می نویسیم.

به اسامی کلاس های Event و Command دقت کنید. چون Command قرار است کاری را انجام دهد نام کلاسش CreateUser است. در حالی که نام Event را UserCreated گذاشته ایم چون کار انجام شده و Event صرفا پیامی است که بعد از پردازش Command ایجاد شده است.

یک کلاس Helper در پروژه ی Common ایجاد می کنیم که شامل دو متد خواهد بود:

  • تبدیل Object به ByteArray
  • تبدیل ByteArray به Object

از این کلاس در قسمت های دیگر برنامه استفاده خواهیم کرد. کدهای این کلاس به مانند زیر است.

ایجاد و ارسال Command

یک پروژه از جنس Console به نام GatewayConsole می سازیم و یک کلاس به نام PublishCommandMessage در آن ایجاد می کنیم که کدهایش به مانند زیر است.

در قسمت ConnectionFactory آدرس Host ای که RabbitMQ در آن قرار دارد را وارد می کنیم. به صورت پیشفرض پورت آن 5672 است. در صورت تغییر شماره ی پورت، می توان در متد ConnectionFactory آن را اعمال کرد این متد قابلیت دریافت Username و Password مخصوص RabbitMQ را نیز دارد. سپس در کلاس Program کد زیر را وارد می کنیم.

در اینجا یک نمونه از کلاس PublishCommandMessage می سازیم و یک Message از جنس ICommand به آن ارسال می کنیم. سپس این Message توسط این کلاس به ServiceBus فرستاده می شود. بعد از اینکه مایکروسرویس IdentityService  این Message را دریافت کرد و کارش را انجام داد، یک Event به ServiceBus می فرستد. پروژه ی GatewayConsole باید از قبل جنس Event را Subscribe کرده باشد تا بتواند از آن استفاده کند. بدین منظور در کلاس Program از کاربر می خواهیم که دکمه ای را بفشارد تا برنامه بتواند پیامهای از جنس این Event خاص (به نام UserCreated) را Subscribe کند و آن را استفاده کند.

اما این کلاس را بعدا پیاده سازی می کنیم.

حال باید پروژه ی IdentityService  را بسازیم و یک کلاس به نام SubscribeCommandMessage را به مانند زیر در آن بنویسیم.


متد Consumer_Received به مانند زیر است:

و متد Save این کلاس به مانند زیر است:

ایجاد و ارسال Event

کلاس بالا بعد از دریافت Command از ServiceBus آن را در یک فایل متنی ذخیره می کند. سپس در نام User یک تغییر کوچک ایجاد کرده و آن را در قالب پیامی از جنس Event به ServiceBus می فرستد.

کلاس PublishEventMessage به مانند زیر است.

کلاس Program نیز به مانند زیر است.

حال باید کلاس SubscribeEventMessage را در پروژه ی GatewayConsole بنویسیم.

و متد Save به مانند زیر است.

این کلاس بعد از اینکه Event را از ServiceBus دریافت کرد آن را در یک فایل متنی ذخیره می کند. به درایو C دقت کنید. دو فایل متنی به نام های Logs و Logs2 داریم. محتویات آنها مانند هم است با این تفاوت که در فایل Logs2 رشته ی Mr به ابتدای نام اضافه شده است.

نوشته شده توسط mrbitmap علیرضا علی رمضانی

مقالات مرتبط

جدیدترین مقالات

فهرست