اگه قسمت ۳ رو نخوندید اینجا پیداش میکنید:
هرچیزی که تاحالا پیاده کرده بودم یه اپلیکیشن Monolith بود. یعنی همه چیز داشت تو یه اپلیکیشن هندل میشد. از Auth برای ثبت نام و فعال کردن کاربر بگیر تا ساخت پروژه جدید و Board ها و Task ها و File ها و ... ولی من میدونستم یه چیزی وجود داره به اسم Microservice ها که میاد یه ایده دیگه رو مطرح میکنه. ایده ای که میتونه به Scale کردن پروژه کمک کنه.
میدونم البته که من الان یه اپلیکیشن خیلی خیلی خیلی ساده دارم. اصلا نیازی نیست که بخوام اونو Microservice کنم. مخصوصا اگه Guideline های این Microservice ها رو بری بخونی متوجه میشی که پیاده سازی درست مفهوم Microservice خیلی خیلی خیلی خیلی سخت و پیچیده هست. ولی خب دیگه، قشنگی کار هم همینه. اصلا یادگیری همینجا شکل میگیره.
کنجکاوی بود که منو داشت هل میداد به جلو. هی میگفتم خب بذار اینکارم بکنم، بذار اون یکی کارم بکنم، بذار اینم بهش اضافه کنم. فقط میخواستم تجربه کنم. یعنی هدفم از اینکه برم سراغ Microservice ها این نبود که مشکل پرفورمنس خورده بودم، فقط میخواستم یاد بگیرم اینکار چطور انجام میشه.
ولی قبل اینکه بهش برسیم بذارید تعریف کنم که چی شد اصلا رسیدم به اینجا و چی شد که اصلا به خودم گفتم این چه غلطی بود من کردم 😂

داستان به جایی رسید که میخواستم اپلیکیشین رو Deploy کنم. برای همین سرچ کردم ببینم چه ابزار هایی دارم. خب میدونستم که AWS هست و میتونم ازش استفاده کنم، ولی گفتم یه چرخی بزنم. خیلی آپشن های مختلفی پیدا کردم که خیلی هاش اصلا بدون کانفیگ فقط لینک git رو میدادی و میرفت خودش دیپلوی میکرد و همه چی با GUI هندل میشد. قیمتی هم نداشتن و حتی بعضیاش رایگان بودن.
ولی من پیش خودم فکر کردم "حالا که تا اینجا اومدیم، ببینیم رو AWS چطوری میشه انجامش داد". این شد که یه سرچی کردم دیدم سرویسی که بهم میده اسمش EC2 هست. در حقیقت یه VPS میسازه با یه SSH Key که بهش وصل بشی و همه چی رو خودت دستی هندل کنی و بذاری بالا. یه کانفیگ پایه که داشت حالت micro بود اگه اشتباه نکنم که یه منابع حداقلی میداد.
خب روال کار تا اینجا به چه شکل بود؟ من باید وصل میشدم به سرور و بعد نصب git و بقیه چیزا کد رو میگرفتم و اونجا یه وب سرور میذاشتم که اپلیکیشن رو بیاره بالا و از اون به بعد روی اون IP قابل دسترس میشد. این ولی خب روالی بود که شاید ۸-۹ سال پیش باهاش کار میکردن 😁 حالا دیگه Docker خیلی کارو ساده تر میکرد.
یه داکرفایل برای پروژه نوشتم، توش ستاپ کلی رو انجام دادم و حالا نیاز بود که یه سرویس دیگه هم بیاد و این رو serve کنه که خب انتخابم Nginx بود. پس در واقع اپلیکیشنم میشد یه image و اون وب سرور هم میشد یه image دیگه. خب اینجا راه حل استفاده از docker compose بود که بیاد اول یه nginx بیاره بالا و بعد اپلیکیشن رو بیاره بالا. این وسط میموند دیتابیس که اونم شد یه قسمت دیگه از اون docker compose فایلی که داشتم.
خلاصه اش کنم، بعد کلی بدبختی و سرچ و AI و ... رو سیستم خودم تونستم پروژه رو کامل با داکر بیارم بالا. فقط یه درد دل ریز بکنم اونم این که من پاااااره شدم. البته لذت بردم از اینکه پاره شدم ها 🤣 ولی واقعا به یه مواردی برخورد میکردم که واقعا بعضی جاها میخواستم بگم آقا ولش کن اصلا. اما خداییش کلی چیز یاد گرفتم.
اما هنوز به سرور نرسیده بود. بعد اینکه رو سیستم خودم با داکر همه چی کار کرد گفتم ایول حالا دیگه با خیال رااااحت میتونم برم رو اون EC2 که ساخته بودم و فقط داکر رو اجرا کنم و تمااام.
ولی خب دیگه 😅 حتما فهمیدید که یه جای کار مشکل داشت.
من اینکارو انجام دادم و رفتم روی vps و شروع کردم داکر رو میزان کردن که وسط کار موقع ستاپ کردن پروژه هی گیر میکرد و بعد یه مدتی هم timeout میداد و میترکید. خدایا مشکل چی بود... مگه نه اینکه میگن داکر مشکل Works on my machine رو حل میکنه 😅 یکم که بررسی کردم دیدم که بله، کد و کانفیگ و ... مشکلی ندارن. مشکل جای دیگه است. در واقع منابع اون instance من محدود تر از این بود که بخواد چندتا image رو باهم بیاره بالا بدون مشکل. و راه حل چی بود؟ پول! 😁
باید منابع EC2 رو میاوردم بالاتر. مخصوصا Ram بیشتر. خب این پلنش هم Pay as you use هست دیگه، گفتم عیبی نداره در عوض چیز یاد میگیرم. خلاصه ردیفش کردم. بعد دیگه داکر اجرا شد و اومد بالا و لاگ ها همه چیز رو خوب نشون میدادن تا اینکه اومدم از طریق postman به سرور یه درخواست بزنم ببینم کار میکنه یا نه. هرکاری میکردم کار نمیکرد. بازم نمیخوام طولانی بشه، فهمیدم کانفیگ هایی که من رو سیستم خودم انجام داده بودم کاملا درست نبودن. نیاز بود تغییراتی بکنن. خلاصه کلی کلنجار رفتم و بالاخره اولین response از سرور دریافت شد و شادی و خوشحالی فضای اتاق رو گرفت 😂
اون وسطا یه شیطنتی هم کردم یه دامین هم خریدم که با IP نخوام بهش درخواست بزنم، یه SSL هم براش باید میزان میکردم که اونم ردیف شد (البته شما راحت بخونید، ولی بر من سخت گذشت 😅)
چیزایی که به واسطه این تجربه یاد گرفتم:
کانفیگ کردن Docker و درک بهتر از Dockerfile
کانفیگ کردن محیط dev ام با کمک Docker compose
اجرای پروژه روی AWS و EC2
کانفیگ Nginx به شکلی که رو سیستم خودم و سرور درست کار کنه
کانفیگ دامین و SSL و خرت و پرتای مربوط بهش و آپدیت Nginx و سرویس های خرید دامین
کار کردن با AWS پول میخواد 😂
پس تا اینجا من یه اپلیکیشینی داشتم که داشت خیلی خوشگل کار میکرد، حالا رو یه سرور بود، میشد بهش درخواست بزنی و همه چی خوب بود. ولی بازم یه چیزی کم بود. هر بار که میخواستم آپدیت کنم پروژه رو باید میرفتم توی اون VPS و آخرین کد ها رو از Git میگرفتم و میزدم که داکر اجرا بشه. یعنی عملا من اینجا قسمت CI/CD رو نداشتم. که جلوتر میرسیم بهش.
قبلش یادتونه اون ماجرای decrypt و encrypt شدن id ها رو؟ میخواستم روال کارشو بهینه تر کنم. نه که بهینه نبود قبلش، ولی بازم گفتم بذار یه چیز دیگه هم امتحان کنم. تصمیم گرفتم اون آیدی ها رو توی Redis ذخیره کنم. البته سربار اجرایی نداشت قبلش هم. شاید حتی اصلا چیز اشتباهی بود که بخوام از Redis برای اون مقادیر استفاده کنم. کلا یه موضوع خیلی چالش بر انگیز تو دنیای نرم افزار همین موضوع Caching هست. چون فقط این نیست که شما یه مقداری رو بذاری رو یه دیتابیسی شبیه Redis.
بحث این پیش میاد که چه زمانی اون دیتا ها باید invalid بشن، با چه سیاستی از cache استفاده کنی و چجوری کلا باهاش کار کنی، موضوع مهمی برای من نبود البته، من میخواستم فقط تجربه اش کنم. برای همین اومدم هر id رو عدد و رشته اش رو تو Redis ذخیره کردم و زمانی که میخواستم GET ها رو هندل کنم از اونجا میخوندم. کار غلطی بود الان که بهش فکر میکنم ولی خب دیگه، تجربه است. خیلی استفاده های بهتری هم از Redis میشه کرد. بعد تر که بیشتر راجع بهش خوندم فهمیدم خیلی کار های دیگه هم میشه باهاش کرد.
از این بگذریم، خواستم اشاره کنم که فقط اینم اون وسطا اومد. برگردیم سراغ همون موضوع CI/CD.
راه حلش ساده بود ولی پیاده سازیش سخت 😂 صادقانه بگم قبلا درگیر اینچیزا نمیکردم خودم رو. تا جای ممکن ازشون فاصله میگرفتم. مخصوصا که اینکارارو یه بار انجام میدادیم و دیگه تا نیازمندی جدید دیگه ای نبود نمیرفتیم سمتش. اونم چیزی نبود جز Gitlab CI.
اگه مطالب من رو خونده باشید تا اینجا، میبینید، مسیر طوری ادامه پیدا میکرد که هرجا که میرفتم یهو احساس نیاز میکردم یه کاری کنم کارم ساده تر شه، یه کاری کنم که هم یاد بگیرم هم تجربه. خیلی چیز ها رو از اول نمیدونستم که لازم دارم. اپلیکیشی ساده ای که از اول با هدف یادگیری Go شروعش کرده بودم داشت منو میبرد سمت اینکه خیلی چیز های دیگه هم یاد بگیرم.
به نظرم اگه مخاطب من که شما باشی، میبینی که من از اول راه این مسیر رو آروم آروم آروم اومدم جلو و هی نیاز جدید بوجود میومد (یا بوجودش میاوردم 😂) که براش مجبور شدم یه مسیر جدید رو شروع کنم.
خب از اونجا که من عموما تو پروژه ها و شرکت های مختلف سیستمی که استفاده کرده بودم همون Gitlab بود انتخابم هم شد همین Gitlab CI وگرنه میدونم که تو خیلی جاها از Github Actions برای Github استفاده میکنن که خب اون یه داستان دیگه است که من بلد نیستم.
در واقع Gitlab CI یه شکلی از Docker هست (یا دست کم من اینطوری ازش فهمیدم) که میاد یه سری کار رو به کمک یه سری script با یه سری trigger انجام میده. مثلا بهش میگی بعد اینکه کد push شد روی فلان برنچ بعدش بیا این stage رو اجرا کن، بعدش فلان stage و... مثال دنیای فرانت اش میشه مثلا بعد اینکه کد push شد روی برنچ main بیاد lint کنه بعد تست ها رو انجام بده، بعد مثلا یه trigger دستی داشته باشه که بگیم کد رو بذار رو پروداکشن یا staging و ...
خب من مشکلم چی بود؟ این بود که باید هر بار دستی میرفتم رو vps و کد رو میگرفتم و داکر رو اجرا میکردم. مجدد بعد کلی تحقیق و کمک های فراوان از AI تونستم یه فایل gitlab ci بنویسم که بعد از زمانی که کد روی برنج main میومد بالا، وصل شه به سرور، بره داخل directory مورد نظر و یه بار git pull کنه و بعد داکر رو اجرا کنه.
حالا این مشکل هم حل شده بود. الان دیگه من یه سیستمی داشتم که روی کامپیوتر خودم توسعه میدادم و هر زمان که رو برنچ main کد رو میفرستادم در اصل روی سرور هم کدم میرفت و اجرا میشد.
ولی من اینجا گفتم خب چه عالی حالا برم سراغ یه پروژه دیگه؟
نه! گفتم حالا که انقدر Docker رو یاد گرفتم چرا نرم سر وقت اینکه هر کدوم از اجزای سیستم رو یه سرویس مستقل کنم و با compose اینا رو به هم وصل نکنم؟ یعنی چی؟ یعنی هرچی ساختم، هر API ای که داشتم حالا باید سرویس مستقل خودش میشد.
سرویس مستقل یه تعریفی داره. کلا معماری Microservice یه سری نکته داره که باید از قبل دونست. این یعنی هر سرویس باید کااااملا مستقل باشه. اینکه میگم کاملا یعنی کااامل. برای درک بهتر یکی از دوستانم این سایت رو معرفی کرد. تقریبا کل Guideline هاش اینجا هست. کلی هم شکل داره که موضوع رو بهتر توضیح میده. درکش با AI و یه سری prompt خوب تازه بهتر هم میشه.
این سرویس ها باید باهم صحبت میکردن، حالا از طریق REST Api یا روش های دیگه. من فکر میکردم پیاده سازیش نباید خیلی کار سختی باشه ولی....
اینجا بود که من بدبختیم شروع شد.
تو قسمت آخر میگم که این داستان Microservice ها با من چه ها که نکرد. با مفاهیمی مثل gRPC و معماری Event Driven و DDD بیشتر آشنا شدم. چیزایی مثل Nats و kafka رو دیدم. از scaling بیشتر یاد گرفتم. حتی یه ناخونکی به K8s زدم. توی پست آخر راجع به منابع ام هم میگم. کلی کتاب معرفی میکنم که خیلی خوب بودن. البته صادقانه من همه شون رو هنوز نخوندم ولی معرفی میکنم. از تاثیر AI روی این مسیر هم بیشتر صحبت میکنم. خلاصه سرویس های مختلف رو کانفیگ گردم و به کلی چالش برخوردم که هنوزم البته توش موندم 😁 که در موردش بیشتر میگم.
قسمت آخر: