مفاهیم توسعه نرم افزار به سبک Microservice
چرا معماری میکروسرویس؟
امروزه با افزایش رسانه های اجتماعی، اینترنت پرسرعت و ... تمایل به استفاده از اپلیکیشن ها روز به روز بیشتر شده است. در نتیجه این تغییرات رفتاری، برنامه های کاربردی یکپارچه(monolithic ) نیاز به بروز شدن بر اساس حجم زیادی از تغییرات دارند.
بیشتر بیزینسها با ویژگی جدیدی روبرو هستند که باید به برنامه هاشون اضافه شوند،اما از طرفی، حجم داده هایی که باید پردازش شوند بسیار افزایش می یایند و در بسیاری از موارد در برنامه های monolithic به دلیل معایب آنها مانند سرعت پایین توسعه، استقرار کندتر، زیرا به سختی از روش چابک (agile methodology ) پشتیبانی می کند که ایده اصلی واکنش به تغییرات سریع در صنعت نرم افزار است.
اگر میخواهید یک پروژه نرمافزاری برای یک بیزینس بزرگ یا پیچیده ایجاد کنید ، بهتر است با معماری میکروسرویس شروع کنید.(در مورد پروژههای startup یا آن پروژههایی که در مرحله تامین مالی هستند صدق نمیکنه، چون اونا مجبورن به محدودیتهای بازار نگاه کنن)
بنابراین، یکی از راه حلها برای افزایش انعطافپذیری برنامه، مقیاسپذیری و بسیاری از موارد دیگر، پیروی از یک معماری انعطافپذیر مانند معماری مبتنی بر میکروسرویس است.
چرا به نقشه راه نیاز دارید؟
همانطور که من درک می کنم بسیاری از توسعه دهندگان می خواهند بدانند چگونه باید این سفر را شروع کنند، بدیهی است که هزاران منبع وجود دارد که می توان از آنها استفاده کرد، اما مشکل پراکندگی منابع است. تصمیم گرفتم این سفر را با تعریف یک نقشه راه برای این منحنی یادگیری واضح تر کنم.
این نقشه راه چگونه کار می کند؟
یک معماری مبتنی بر میکروسرویس دارای چندین واحد جدا است که با هم کار می کنند تا درخواست های منابع مختلف را دریافت و پردازش کنند. برخی از قسمتهای این مجموعه میتوانند واحدهای plug-in باشند، به این معنی که در صورت نیاز میتوانید یک واحد جدید را وصل کنید یا یک واحد را از برق جدا بکشید، ولی نباید در کار کلی برنامه اختلال ایجاد کند.
به عنوان مثال، اگر تصمیم به پیادهسازی معماری میکروسرویس گرفتهاید، باید با موارد مختلفی در چرخه حیات یک برنامه کاربردی مانند ماندگاری(persistence)، لاگ کردن (logging)، نظارت(monitoring)، تعادل بار(load balancing)، کش (caching )و غیره آشنا باشید، علاوه بر این باید بدانید که کدام ابزار برای برنامه های شما مناسب تر هستند.
خب، در این مقاله قراره قراره با این مفاهیم آشنا بشیم، سپس تعدادی از بهترین ابزارها را برای این موارد نوشته شده رو معرفی می کنم.
توجه کنید که برای ابزارها فقط دو یا سه ابزار را ذکر کردم، البته ابزارهای بسیار دیگری هم داریم که معیار انتخاب این ابزارها محبوبیت(popularity)، کارایی، متن باز بودن(open-source) و همچنین فراوانی به روز رسانی است.
مجدداً توجه داشته باشید که ما سرویسهای cloud-based نیز داریم که خارج از محدوده این مقاله مورد بحث قرار می گیرند.
من از نمودار بالا به عنوان نمونه نمودار معماری, استفاده کرده ام زیرا این نمودار ,بیشتر اجزای معماری میکروسرویس را در بر می گیرد و همچنین به عنوان یک مدل استاندارد شناخته شده است، البته می دانم که این نمودار نمودار چندان جامعی نیست، اما سعی کرده ام. برای اینکه این مقاله تا حد امکان ساده باشد، شاید در آینده مقاله را اصلاح کنم و نسخه جدیدی از آن بنویسم. من فکر می کنم بهترین طرز فکر در مورد توضیح هر مفهوم، همیشه باید از الگوی KISS پیروی کند.
مفاهیمی که در این مقاله توضیح داده شده اند عبارتند از:
- Docker
- Container orchestration
- Docker container management
- API gateway
- Load Balancing
- Service discovery
- Event Bus
- Logging
- Monitoring And Alerting
- Distributed tracing
- Data Persistence
- Caching
- Cloud Provider
.: داکر (Docker) :.
Docker یک پلت فرم منبع بازه که برنامه شما رو به همراه کتابخانه ها و وابستگی هاش کانتینری(بسته بندی) میکنه است که برنامه شما برای اجرا در محیط های مختلف به آن نیاز دارد. با کمک Docker، تیم های توسعه قادر به بسته بندی برنامه ها در کانتینرها هستند.
چرا: در واقع، داکر یکی از ابزارهای کانتینریزه کردن برنامه ها است،یعنی شما می توانید کانتینرهایی را بدون استفاده از داکر هم ایجاد کنید، مزایای واقعی داکر این است که این فرآیند را آسان تر، ایمن تر و بسیار ساده تر می کند.
ابزار: Docker
.: ارکستراسیون کانتینری (Container Orchestration) :.
پس از اینکه برنامه خود را کانتینری کردید، برای انجام برخی عملیات دستی و خودکار مانند مقیاس افقی به ابزارهایی برای مدیریت برنامه های کاربردی کانتینری شده نیاز دارید.
چرا: این ابزارها برخی از خدمات را برای مدیریت برنامه شما ارائه می دهند، مانند load-balancing خودکار، همیشه در دسترس بودن service را تضمین می کنند. این نوع سرویس با تعریف چندین گره مدیر انجام می شود و در صورت بروز هر گونه خرابی در یک مدیر گره، مدیران دیگر می توانند خدمات اپلیکیشن را در دسترس نگه دارند.
ابزارها: Kubernetes , K8s , Docker Swarm
.: ابزار مدیریت کانتینر (Docker Container Management) :.
مدیریت محیط Docker، مدیریت پیکربندی(configuration )، و ایجاد محیط امن(environment security) و غیره.
این موارد را میتوان توسط ابزار مدیریت کانتینر داکر متمرکز و خودکار کرد.
چرا: یک ابزار مدیریت کانتینر Docker یک ابزار مبتنی بر رابط کاربری گرافیکی را برای کاربران فراهم می کند و آنها مجبور نیستند با CLI که برای همه کاربران راحت نیست سروکار داشته باشند. این ابزارها به توسعه دهندگان یک رابط کاربری غنی برای ساخت و انتشار تصاویر خود می دهند، همچنین با ارائه یک رابط کاربری ساده، انجام برخی از وظایف عملیاتی مانند مقیاس بندی خدمات به صورت افقی را بسیار آسان تر می کنند.
ابزارها: Portainer، DockStation، Kitematic، Rancher
.: دروازه ورود API (API Gateway) :.
یک API Gateway را می توان به عنوان یک ابزار مدیریت API در نظر گرفت که به عنوان یک میان افزار(middleware ) بین خدمات برنامه شما و مشتریان مختلف کار می کند. یک API Gateway می تواند بسیاری از موارد را مدیریت کند مانند:
مسیریابی(Routing ): یک دروازه تمام درخواست های API را دریافت کرده و آنها را به سرویس های مقصد ارسال می کند.
لاگ کردن (Logging ): شما می توانید تمام درخواست ها را در یک مکان ثبت کنید.
مجوز (Authorization): بررسی کنید که آیا شما به عنوان یک کاربر واجد شرایط دسترسی به این سرویس هستید یا خیر، در غیر این صورت درخواست می تواند اتصال کوتاه داشته باشد
پروفایل عملکرد(Performance profiling): می توانید زمان اجرای هر درخواست را تخمین بزنید و گلوگاه های برنامه خود را بررسی کنید.
کش کردن(Caching): با مدیریت کش خود در سطح دروازه، ترافیک زیادی را در سرویس های خود حذف خواهید کرد.
در واقع، به عنوان یک پروکسی معکوس(reverse proxy) کار می کند، و کلاینت ها فقط باید در مورد دروازه شما بدانند، و خدمات برنامه را می توان از بیرون پنهان کرد.
چرا: بدون API Gateway ، ممکن است لازم باشد در هر سرویس برخی از موارد متقابل(cross-cutting) را انجام دهید، به عنوان مثال، اگر میخواهید درخواست و پاسخ برای سرویسها را لاگ کنید. علاوه بر این، اگر برنامه شما شامل چندین سرویس است، مشتری شما باید از آدرس هر سرویس اطلاع داشته باشد و در صورت تغییر آدرس سرویس، چندین مکان باید بروز شود.
ابزارها: Kong, Ocelot
.: تعادل بار (Load Balancing):.
یکی از مهمترین دلایلی که ما معماری میکروسرویس را انتخاب کردهایم مقیاسپذیری است، به این معنی که با اجرای نمونههای بیشتری از سرویسهایمان میتوانیم به درخواستهای بیشتری رسیدگی کنیم، اما سوال اینجاست که کدام نمونه باید درخواستها را دریافت کند یا مشتریان از کجا میدانند کدام یک نمونه خدمات باید به درخواست رسیدگی کند؟
پاسخ به این سوالات Load Balancing است. Load Balancing به معنای به اشتراک گذاری ترافیک درخواستهای ورودی بین یک نمونه سرویس است.
چرا: برای اینکه خدمات مستقل خود را مقیاس کنید، باید چندین نمونه از خدمات را اجرا کنید. با یک load balancer بار، مشتریان نیازی به دانستن نمونه های مناسبی از خدمات ندارند.
ابزارها: Traefik، NGINX، Seesaw
.: کشف خدمات(Service Discovery) :.
از آنجایی که خدمات برنامه شما بیشتر و بیشتر می شود، سرویس ها باید آدرس های نمونه سرویس یکدیگر را بشناسند، اما در برنامه های کاربردی بزرگ با سرویس های زیاد، این امر قابل رسیدگی نیست. بنابراین ما به سرویس اکتشاف نیاز داریم که مسئول ارائه آدرس های تمام اجزا در برنامه شما باشد، آنها به راحتی می توانند درخواستی را به سرویس کشف سرویس ارسال کنند و آدرس نمونه سرویس های موجود را دریافت کنند.
چرا: هنگامی که می توانید چندین سرویس را در برنامه خود داشته باشید، Service Discovery یکی از ضروریات برنامه شما است. سرویس های برنامه شما نیازی به دانستن آدرس هر نمونه سرویس ندارند، به این معنی است که کشف سرویس این راه را برای شما هموار می کند.
ابزارها: Consul, Zookeeper, Eureka, etcd and Keepalived
.: Event Bus :.
در الگوی معماری میکروسرویس، شما از دو نوع ارتباط مختلف استفاده میکنید، ارتباط sync و ارتباط Async.
ارتباط sync به این معنی است که سرویس ها از طریق تماس HTTP یا تماس GRPC با یکدیگر تماس می گیرند. ارتباط Async یعنی سرویسها از طریق یک message bus یا یک event bus با یکدیگر تعامل دارند، به این معنی که هیچ ارتباط مستقیمی بین سرویسها وجود ندارد.
در حالی که معماری شما می تواند از هر دو سبک ارتباطی به طور همزمان استفاده کند، به عنوان مثال در یک نمونه فروشگاه آنلاین، می توانید هر زمان که سفارشی ثبت شد، پیامی ارسال کنید و سرویس هایی که در یک کانال خاص مشترک شده اند (subscriber)، پیام را دریافت خواهند کرد. اما گاهی اوقات ممکن است نیاز به پرس و جوی real-time داشته باشید، برای مثال، باید مقدار یک مورد را بدانید، ممکن است از تماس GRPC یا HTTP بین سرویسها برای دریافت پاسخ استفاده کنید.
چرا: اگر میخواهید یک برنامه مقیاسپذیر با چندین سرویس داشته باشید، یکی از اصولی که باید رعایت کنید ایجاد سرویسهای مستقل(loosely coupled) است که از طریق یک event bus با یکدیگر تعامل دارند. همچنین، اگر نیاز به ایجاد اپلیکیشنی دارید که بتواند سرویس جدیدی را برای دریافت یک سری پیام خاص وصل کند، باید از یکevent bus استفاده کنید.
ابزارها: RabbitMQ, Kafka
.: لاگ کردن (Logging) :.
هنگام استفاده از الگوی معماری میکروسرویس، بهتر است services logمتمرکز داشته باشید. این لاگها میتوانند در اشکالزدایی یک مشکل یا جمعآوری گزارشها بر اساس انواع آنها برای کاربردهای تحلیلی استفاده شوند.
چرا: در صورت نیاز به اشکال زدایی یک درخواست، اگر گزارش های خدمات را در یک مکان جمع آوری نکنید، ممکن است با مشکل مواجه شوید. همچنین میتوانید گزارشهای مربوط به یک درخواست خاص را با یک شناسه همبستگی منحصربفرد مرتبط کنید. این بدان معناست که همه گزارشهای مربوط به سرویسهای مختلف مربوط به یک درخواست با این شناسه همبستگی قابل دسترسی خواهند بود.
ابزارها: Elastic Logstash
.: نظارت و هشدار (Monitoring And Alerting) :.
در معماری میکروسرویس، اگر میخواهید یک برنامه یا سرویس قابل اعتماد داشته باشید، باید عملکرد، بازدهی، ارتباطات و هر جنبه دیگری از برنامه خود را برای دستیابی به یک برنامه کاربردی نظارت کنید.
چرا: شما باید بر عملکرد کلی و سلامت خدمات نظارت داشته باشید، همچنین باید بازدهی گلوگاه ها را نظارت کنید و برنامه ای برای رفع آنها تهیه کنید. با تعریف هشدارهای اولیه برای خدمات خود در نقاط بحرانی، تجربه کاربر را با کاهش زمان توقف سرویس خود بهینه کنید. بر مصرف کلی منابع service، زمانی که تحت بار سنگین و غیره هستند کاملا زیرنظر داشته باشید.
ابزارها: Prometheus, Kibana, Grafana
.: ردیابی توزیع شده (Distributed Tracing) :.
Debugging همیشه یکی از دغدغه های توسعه دهندگان است، همانطور که همه شما trace یا debug در برنامه های monolithic را دارید. این بسیار ساده و آسان است، اما وقتی صحبت از معماری میکروسرویس میشود، زیرا ممکن است یک درخواست از طریق سرویسهای مختلف ارسال شود، که trace و debug را دشوار میکند زیرا پایگاه کد در یک مکان نیست، بنابراین ابزار ردیابی توزیعشده در اینجا میتواند مفید باشد.
چرا : بدون ابزار ردیابی توزیع شده، ردیابی درخواست شما از طریق سرویس های مختلف خسته کننده یا غیرممکن است. با استفاده از این ابزارها می توانید به راحتی درخواست ها و رویدادها را با کمک داشتن یک رابط کاربری غنی برای نمایش جریان درخواست ردیابی کنید.
ابزارها: OpenTelemetry, Jeager, Zipkin
.: Data Persistence :.
در اکثر سیستمها، ما به دادههای ماندگار نیاز داریم، زیرا به دادهها برای فرآیندهای بیشتر یا گزارشدهی و غیره نیاز داریم تا بتوانیم دادهها را حفظ کنیم، به ابزاری برای نوشتن دادههای برنامههای کاربردی خود در فایل فیزیکی با ساختار متفاوت نیاز داریم.
چرا: در برنامه های monolithic ، ما یک یا دو نوع persistence مختلف داشتیم و بیشتر برنامه های یکپارچه از پایگاه داده های رابطه ای مانند SQL Server، Oracel، MySQL استفاده می کنند. اما در معماری میکروسرویس باید از الگوی «پایگاه داده به ازای هر سرویس» پیروی کنیم، یعنی دادههای پایدار هر میکروسرویس را برای آن سرویس خصوصی نگه داریم و فقط از طریق API آن قابل دسترسی باشد.
خب، شما باید پایگاههای داده متفاوتی برای کاربردها و سناریوهای مختلف داشته باشید. برای مثال یک سرویس گزارش ممکن است از پایگاههای داده NoSQL مانند ElasticSearch یا MongoDB استفاده کند، زیرا از ساختار پایه سند استفاده میکنند، به این معنی که ساختار دادههای ماندگار در این پایگاههای داده با پایگاههای داده رابطهای متفاوت است. که برای سرویس هایی با سرعت خواندن یا واکشی داده های بالا مناسب هستند.
از طرف دیگر ممکن است به پایگاههای اطلاعاتی رابطهای مانند Oracle یا SQL SERVER در برخی از میکروسرویسها نیاز داشته باشید یا ممکن است به پایگاههای دادهای نیاز داشته باشید که ساختار گراف یا ساختار key-value را پشتیبانی میکنند.
بنابراین، در معماری Microservice با توجه به مأموریت سرویس، به انواع مختلفی از پایگاه داده نیاز خواهید داشت.
ابزارها:
پایگاه داده های رابطه ای یا RDBMS : PostgreSQL، MySQL، SQL SERVRE، Oracle
پایگاه داده NoSQL: MongoDB، Cassandra، Elasticsearch
.: Caching (حافظه پنهان ) :.
Caching تاخیر در ارتباط سرویس به سرویس معماری های میکروسرویس را کاهش می دهد. کش یک لایه ذخیره سازی داده با سرعت بالا است که زیر مجموعه ای از داده ها را ذخیره می کند. وقتی دادهها از Caching درخواست میشوند، سریعتر از زمانی که به مکان ذخیرهسازی اولیه دادهها دسترسی داشته باشید، تحویل داده میشوند.
در معماری میکروسرویس استراتژیهای زیادی وجود دارد که میتوان کش را به این روشها پیادهسازی کرد. مانند
1- حافظه نهان جاسازی شده Embedded Cache (توزیع شده و غیر توزیع شده)
2- کش کلاینت-سرور (توزیع شده)
3- کش پروکسی معکوس Reverse Proxy Cache (سایدکار)
به منظور کاهش latecny، کش را می توان در لایه های مختلف پیاده سازی کرد. این بدان معناست که شما زمان پاسخگویی بالاتری خواهید داشت. علاوه بر این، می توانید کش توزیع شده را نیز پیاده سازی کنید که برای چندین میکروسرویس قابل دسترسی است و گاهی اوقات به عنوان یک مکان نگهدار برای منابع مشترک در نظر گرفته می شود، که کاربردهای متفاوتی دارند، مانند
محدود کردن نرخ (Rate-limiting ): رایجترین دلیل برای محدود کردن نرخ، بهبود در دسترس بودن سرویسهای مبتنی بر API با اجتناب از گرسنگی منابع است.
ابزارها : Redis (REmote DIctionary Server), Apache Ignite, Hazelcast IMDG
.: Cloud Provider:.
ارائهدهنده خدمات ابری یک شرکت شخص ثالث است که یک پلتفرم، زیرساخت، برنامه، یا خدمات ذخیرهسازی مبتنی بر ابر ارائه میدهد. دقیقاً مانند یک مالک خانه که برای خدماتی مانند برق یا گاز هزینه می کند، شرکت ها معمولاً باید فقط برای مقدار خدمات ابری که استفاده می کنند، بر اساس نیازهای کسب و کار بپردازند.[Microsoft]
مهم ترین دسته ها برای ارائه دهندگان ابر
1- نرم افزار به عنوان سرویس (SaaS).
2-پلتفرم به عنوان سرویس (PaaS).
3- زیرساخت به عنوان یک سرویس (IaaS).
یکی از مزایای استفاده از خدمات رایانش ابری این است که شرکتها میتوانند از هزینههای اولیه و پیچیدگی مالکیت و نگهداری زیرساختهای فناوری اطلاعات خود اجتناب کنند و در عوض به سادگی برای چیزی که استفاده میکنند، در هنگام استفاده از آن هزینه بپردازند. امروزه، به جای داشتن زیرساخت های محاسباتی یا مراکز داده، شرکت ها می توانند به هر چیزی از برنامه ها گرفته تا ذخیره سازی دسترسی داشته باشند.
ابزارها: Amazon Web Services (AWS) , Microsoft Azure, Google Cloud, Alibaba Cloud