آشنایی با میکروسرویس

از آنجا که میکرو سرویس براساس بیزینس مدل و Business Domain ایجاد می شود، مشکلات معماری های چندلایه سنتی و گره خورده به هم را ندارد. با کمک میکروسرویس میتوانیم از تکنولوژی های جدید اخیر نیز براساس کاربرد و عملکرد هر سرویس بصورت مجزا بهره ببریم. ما در این روش معماری مشکلات افتادن در دام های معماری سرویس گرا SOA را نیز نداریم. معماری میکرو سرویس طراحی Design، توسعه Development، استقرار Deployment و تست Test نرم افزار را شامل میشود.

سال های زیادی ما تلاش میکردیم که روش های بهتری برای تولید نرم افزارهایمان پیدا کنیم، تلاش میکردیم از تکنولوژی هایی که جدیدتر بودند استفاده کنیم، از روش هایی که شرکت های بزرگ و پیشرو برای تولید و طراحی نرم افزار استفاده میکردند، الگو میگرفتیم. سعی میکردیم تولید نرم افزار را به گونه ای انجام دهیم که هم برای ما به صرف باشد هم برنامه نویسان ما راضی باشند و هم مشتریان از ما راضیتر باشند و بتوانیم تغییرات درخواستی مشتریمان را در کمترین زمان و با کمترین هزینه انجام دهیم.

آقای اریک اوانس Eric Evans یه کتاب معروفی داره به اسم Domain Driven Design که این کتاب به ما کمک میکنه تا بتوانیم دنیای واقعی اطرافمان را بهتر در کدهای نرم افزاری نمایان کنیم و با این معرفی این سیستم فکری به مدل سازی بهتر سیستم های نرم افزارهای کمک کرد. مفهوم تحویل مستمر Continuous Delivery  به ما نشان داد که چگونه موثرتر و کاراتر میتوانیم فرآیند استقرار Deployment را داشته باشیم و فرآیند لانچ محصول میتواند چقدر مفیدتر و بهتر اتفاق بیفتد و هر تغییری و هر Check In ای در نرم افزار میتواند خود یک نسخه و یک Deploy باشد.فهم بهتر ما از اینکه دنیای وب و اینترنت چگونه کار میکنند منجر شد که بتوانیم ارتباط بین ماشین های مختلف را برقرار کنیم. معرفی روش معماری شش ضلعی Hexagonal Architecture به ا فهماند که از روش معماری چندلایه باید دوری کنیم چرا که این روش ها باعث میشوند اعمال تغییرات درخواستی در سمت بیزینس در نرم افزار بسیار دشوار شود. پلتفرم های مجازی سازی به ما این امکان را دادند که منابع ماشین هایمان را در لحظه مانیتور کرده و  هرچقدر بخواهیم اضافه کنیم. با اتوماتیک سازی زیرساخت Infrustructure Automation میتوانستیم این ماشین های مجازی را Scale up کنیم. در کنار اینها شرکت های مانند گوگل و آمازون نشان دادند که چگونه تیم های کوچک میتوانند روی هر بخش از نرم افزار کار کنند و نیازی نیست که کل نرم افزار را بدانند و حتی شرکت نتفلیکس روشی برای Scale Up سیستم های نرم افزاری و ماشینی ارائه کرده است که در 10 سال قبل این روش ها و این قابلیت ها قابل تصور حتی نبود.

معماری تریپل دی Domain-Drive-Design، Continuous Delivery تحویل مستمر، مجازی سازی در لحظه On Deman Virtualization، اتوماتیک سازی زیرساخت Infrustructure Automation، تیم های برنامه نویسی کوچک و خودمختار و مجزا، Scale up لحظه ای سیستم ها، همه اینها یعنی ظهور مفهوم جدیدی به نام معماری میکروسرویس Miroservice Architecture. میکروسرویس از دنیای همین تکنولوژی هایی که سالها قبل کشف کردیم ظهور کرد و خلق شد. این مفاهیم و کاربردها براساس تجربه شرکت ها ایجاد شدند، این یعنی میکروسرویس نیز از قبل وجود داشته و کاربردی بوده است. من مهدی محمدی در این نوشته تلاش میکنم که تمامی این مفاهیم را در کنار هم قرار دهم و تصویری یکپارچه از میکروسرویس برای شما ارائه کنم.

بسیاری از شرکت ها امروزه به این نتیجه رسیده اند که با استفاده از میکروسرویس و خرد کردن سرویس ها و نرم افزار به اجزای کوچک میتوانند نرم افزار را سریعتر و کم هزینه تر تولید کرده و تحویل دهند و از تکنولوژی های جدید در نرم افزارها استفاده کنند. میکروسرویس بصورت چشمگیری دست ما را در تصمیم گیری های بیزینسی بار میگذارد و به مشترین ما این فرصت را میدهد تا هر تغییری را لازم دارند در سریعترین زمان و کمترین هزینه برایشان انجام دهیم.

 

میکروسرویس چیست؟

بطور کلی میکروسرویس ها، سرویس های ریز small و خود مختاری autonoumus هستند که با همدیگر در ارتباط هستند.

 

یک میکروسرویس چقدر باید میکرو و کوچک باشد؟ Small Services

در اولین بخش این تعریف در مورد ریز و کوچک بودن هر سرویس صحبت میکنم. تمرکز روی کوچک بودن هر سرویس و درست انجام دادن یک کار کوچک نقطه تمرکز هر سرویسی باید باشد. همانطور که میدانید مخزن کدنویسی Codebase برای هر نرم افزار روز به روز بزرگتر میشود،چرا که ویژگی های Features جدید به نرم افزار همواره در حال اضافه شدن است و همین باعث میشود انجام تغییرات در طول زمان روی نرم افزار دشوارتر شود، چرا که مخزن کد بزرگتر است و پیدا کردن جاهایی که باید تغییر داده شوند دشوارتر میشود. درست است که ما نرم افزارها را بصورت ماژولار مینویسیم و برای هر تغییری آن ماژول مربوطه را اصلاح میکنیم ولی واقعا در طول زمان حفظ مرز این ماژول ها دشوار است و معمولا بعد مدتی این مرزبندی ها کمی در هم قاطی میشوند. مثلا کدی که مربوط به یک فانکشن Function است بعد مدتی در جاهای مختلف هم پخش میشود و همین فرآیند دیباگ و توسعه و نگهداری را دشوارتر میکند.

در سیستم های مونولیتیک Monolithic یا همان معماری یکپارچه ما با تقسیم بندی نرم افزار به ماژول ها Modular Programming یا استفاده از Abstraction ها سعی میکنیم این نظم را در کدهایمان برقرار کنیم. در واقع انسجام Cohensive چیزی است که ما در اینجا با این روش ها میخواهیم برقرار کنیم و همین Choension در معماری میکروسرویس هم امری بسیار مهم است. یعنی گروه بندی و بخش بندی کدهای نرم افزار که این موضوع توسط آقای مارتین رابرتز Robert C.Martin به عنوان اصل Single Responsibility Principle قاعده مسئولیت منفرد بیان شده است: چیزهایی که بخاطر یک تغییری مشابه قرار است با هم تغییر کنند با هم دریکجا قرار بده و چیزهایی که به دلایل مختلف و متفاوت ممکن است جدا از هم تغییر کنند از هم جدا قرار بده.

میکروسرویس از همین رویکرد برای سرویس های جدا از هم استفاده میکند. ما محدوده و مرزبندی Boundaries سرویس های نرم افزار را براساس محدوده و Boundary های بیزینسی بنا میکنیم و این باعث میشود کدهای ما براساس نیازمندها و فانکشن های بیزینس تعریف شده و مشخص باشند و با تمرکز هر سرویس روی مرزبندی مشخصاین وسوسه بزرگتر شدن سرویس و متعاقبلا مشکلات بعدی آن را از بین میبرد.

سوالی که من معمولا از من میپرسند اینه که وقتی میگی یه سرویس باید کوچک باشد یعنی دقیقا چقدر کوچک باشد؟ خوب براساس سطرهای کدنویسی نمیشه اینو گفت،چرا که هر کاری تو هر زبان برنامه نویسی به روش های مختلف و با تعداد سطرهای کد و حجم کد متفاوتی ایجاد میشه، پی این ملاک خوبی نیست که براساس سطرهای کد در این مورد اندازه گیری کنیم. یا اینکه هر کدی ممکنه یه سری وابستگی Dependency داشته باشه که کدهای یک سرویس با اون کار میکنند و خود این وابستگی ها هم کدی هستند که به سرویس اضافه میشن. یا اینکه بعضی ماژول ها ممکنه کلا پیچیده باشند و کدهای بیشتری نیاز داشته باشند.

آقای جان ایو Jon Eaves میگه سرویس باید در 2 هفته قابل کدنویسی باشه و معیار زمان رو برای کوچکتر بودن سرویس در نظر میگیره. من در مورد سرویس میگم که درسته باید سرویس کوچک باشه ولی از استانداردی هم نباید کوچکتر باشه و خیلی زیاد ریز باشه، من در یک سمینار پرسیدم کیا سیستم های نرم افزاری دارند که به نظرشون خیلی بزرگه و باید به بخش های ریزتر تقسیم بشه؟ تقریبا همه حاضرین دستشونو بردند بالا و این نشون میده که به نظر ما درک درستی از سیستم ها و سرویس های خیلی بزرگ داریم، پس اگر سرویسی رو حس میکنیم که خیلی بزرگ نیست پس میتونه اندازه درستی برای سرویس ما باشه.

یکی دیگه از فاکتورهایی که میتونیم برای تشخیص کوچک بودن سرویس در نظر بگیریم ساختار تیم هست. یعنی اینکه این سرویس چقدر با Team Structure همراستا و Align شده؟ اگه مخزن کد برای یک سرویس اونقدری بزرگ شده که توسط یک تیم کوچک قابل انجام نیست پس باید سرویس رو ریزتر کنیم.

وقتی صحبت در مورد small بودن یک service میشه در نظر بگیرین که: هرچقدر شما سرویس ها را کوچکتر میکنید، هم مزایا و هم معایب مربوط به معماری میکروسرویس را بیشتر میکنید. هرچقدر کوچکتر میشوید مزایای مربوط به وابستگی متقابل بیشتر میشود ولی در عوض مدیریت کلی ریز سرویس هم مشکلات خودش را دارد. پس باید درک درستی از میزان اندازه و اندازه کوچکی هر سرویس پیدا کنید.

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

 

یک میکروسرویس باید خودمختار باشد Autonomous Service

میکروسرویس ها باید موجودیت های مجزا Separate Entity باشند. چرا که هر سرویسی باید قابلیت اینکه بصورت جدا Deploy بشه یا به عنوان پلتفرمی با کاربرد سرویس Platform AS A Service: PAAS استفاده بشه رو در نظر بگیریم. یا اینکه ممکنه سیستم عاملی که این سرویس روش اجرا میشه کلا متفاوت باشه. در معماری میکرو سرویس ما همواره تلاش میکنیم که چندین تا از سرویس ها رو روی یک ماشین قرار ندیم و Pack شون نکنیم. درسته این جداسازی در این حد سختگیرانه ممکنه کمی سختی داشته باشه و واسه ما سربار Overhead ایجاد کنه اما سادگی حاصل از اینطور مجزا کردن باعث میشه ما بتونیم خیلی راحتتر و آسونتر سیستم توزیع شده رو مدیریت کنیم و البته فناوری های جدید خیلی میتونن برای این شکل از استقرار Deploy به ما کمک کنند.

تمام ارتباطات بین سرویس ها از طریق تماس های شبکه ای Network Calls هست تا جدایی نرم افزاری بین سرویس ها به درستی اعمال شوند و از خطرات اتصال فشرده جلوگیری شود.

سرویس ها باید بتونن به تنهایی تغییرات در اونها اعمال بشه بدون اینکه نیاز باشه سرویس دیگری تغییر کنه و بتونن به تنهایی Deploy بشن بدون اینکه در سرویس های دیگری چه مصرف کننده این سرویس و چه گیرنده این سرویس نیاز باشه دست ببریم. ما باید دقیقا بدونیم که سرویس های ما چه مواردی را باید از سرویس های دیگر افشا کنند و چ مواردی را باید پنهان کنند. اگر اشتراک بیش از حد وجود داشته باشد سرویس های مصرف کننده و خدمت گیرنده در هم درگیر میشوند و این خودمختاری سرویس را کمتر میکند و وقتی سرویس رو تغییر میدیم مجبور میشیم تو سرویس های دیگه هم دست ببریم و این اشتباه است.

هر سرویس ما Api های خودش Application Programming Interface خودش را ارائه میدهد و در معرض سرویس های دیگر قرار میدهد و سرویس ها از طریق این API ها با هم ارتباط برقرار میکنند. همچنین ما باید به این فکر کنیم که هر سرویسی با چه تکنولوژی باید نوشته شود و این سرویس ها تکنولوژی های متفاوت دارند که همین باعث میشه سرویس ها نتونن ارتباط غیر API ای با هم داشته باشند.

اگر سرویس ها از هم جدا نباشند همه چیز خراب میشود. همواره به این سوال طلایی پاسخ بدین: آیا من میتونم یک سرویس را به تنهایی تغییر بدم و به تنهایی روی سرور قرارش بدم Deploy کنم؟ اگر پاسختون به این سوال خیر بود، پس شما میکروسرویس خوبی ندارید و از مزایای این معماری نمیتونید استفاده کنید. برای جداسازی مناسب بین سرویس ها شما باید مدلسازی هر سرویس از روی بیزینس را به درستی انجام بدید و API های مناسبی را در نظر بگیرید.

 

مزایای اصلی تکنولوژی میکروسرویس Microservice Key Benefits

مزایای معماری میکروسرویس بسیار زیاد و گسترده هستند. بسیاری از این مزایا همان مزایایی هستند که در سیستم های توزیع شده Distributed Systems وجود داشتند. میکروسرویس در عین اینکه این مزایا را دارند بلکه در سطحی بالاتر به این مزایا خواهند رسید و همچنین از مزایای معماری سرویس گرا نیز Service Oriented Architecture:SOA نیز بهره میبرند. در زیر به برخی از این مزایای اصلی معماری سرویس گرا خواهم پرداخت.

 

مزیت ناهمگنی فناوری ها Technology Heterogenity در میکروسرویس ها

وقتی سیستمی متشکل از سرویس های جدا از هم و مستقل ولی در ارتباط با یکدیگر داریم، میتوانیم برای هر سرویس تکنولوژی های مجزایی انتخاب و استفاده کنیم.این امکان به ما این فرصت رو میده که برای هر کاری ابزار مناسبش رو در یک پروژه استفاده کنیم. یعنی مجبور نیستیم یک پلتفرم یا یک ابزار رو برای پروژه انتخاب کنیم بلکه برای هر کاری در نرم افزار و پروژه مان ابزار متناسب آن را انتخاب کنیم. اگر یک بخش از پروژه ما نیاز داشته باشد که پرفورمنس بهتری را داشته باشد میتوانیم ابزارهای فقط آن بخش را عوض کنیم. همچنین ممکن است نیاز داشته باشیم براساس تغییرات در ذخیره سازی دیتاها بخشی از نرم افزار فقط تغییر کند و با استفاده از این قابلیت میتوانیم نوع دیتا بیس هر سرویس و بخش را جدا انتخاب کنیم. ممکنت است نیاز باشد نوع ذخیره سازی اطلاعات در بخشی بصورت Document-Oriented یعنی همان مدل Nosql باشد و در بخشی دیگر بصورت Graph-Oriented باشد.

همچنین با استفاده از میکروسرویس تغییرات تکنولوژی در پروژه خیلی سریعتر و آسانتر انجام میشود. در مدل Monolithic اگر بخوایم دیتابیس یا پلتفرم یا زبان برنامه نویسی نرم افزار را تغییر دهیم، باید کل پروژه و حجم زیادی از کد را تغییر دهیم ولی در مدل میکروسرویس میتوان ابتدا بخشی را تغییر داد و پرفورمنس جدید را اندازه گیری کرد و این باعث میشود ریسک تغییرات را به شدت کاهش دهیم.

البته ابنم باید در نظر داشت استفاده از تکنولوژی های زیاد برای خودش مشکلاتی را دارد. بسیاری از شرکت ها در مورد Stack مورد استفاده خود و زبان های برنامه نویسی یکسری محدودیت هایی را در نظر میگیرند. مثلا Netflix و Twitter از تکنولوژی Java و JVM که قابل توسعه تر و Sale up تر هستند استفاده میکنند ولی همین باعث میشود واسه کسایی که غیرجاوا کار میکنند این مشکل باشد. پس این بستگی به توانایی شرکت دارد که چقدر بتواند پذیرایی تکنولوژی های جدید و متفاوت باشد و از این مزیت میکروسرویس بهره مند شود.

 

مزیت تاب آوری Resilience در میکروسرویس ها

در تاب آوری Resilience مهمترین اصلا جداره و فاصله است. یعنی اینکه اگر بخشی از سیستم دچار خطا و توقف شود آیا سایر بخش های سیستم فاصله مناسب با این سرویس دارد که بتوانند خودشان به کارشان ادامه دهند و کل سیستم از کار نیفتد؟ در واقع در میکروسرویس محدوده هر سرویس همان فاصله مورد نظر ما در بحث Resilience است. در معماری مونولیتیک اگر یک بخشی از نرم افزار از کار بیفتد قطعا عمکرد کل سیستم متوقف میشود. در معماری Monolithic ما میتواین نرم افزار را روی چندین ماشین مستقر کنیم تا اگر ماشینی از کار افتاد ماشین دیگر کار کند ولی موضوع این است اینکار پرهزینه است ولی با معماری میکروسرویس ما میتواینم سرویس هایی بسازیم که براساس آنها از کار افتادگی کمتر شود.البته ماشین ها و شبکه ها همواره مستعد از کار افتادن هستند و ما باید با درک درست از اتفاقاتی که میتواند رخ دهد سرویس هایمان و ارتباطات بین آنها را طراحی کنیم.

 

مزیت توسعه پذیری Scaling در میکروسرویس ها

در یک سیستم مونولیتیک یکپارچه ما باید همه چیز را با هم توسعه دهیم و Scale کنیم. ولی با میکروسرویس ما میتوانیم هر سرویس یا بخشی را که میخواهیم Scale کنیم بصورت جدا اینکار را انجام دهیم.وقتی نرم افزار ما یکپارچه است ما مجبوریم اگر تعداد کاربران یا بازدیدهای یک بخش زیاد شد کل سیستم را ارتقا دهیم ولی اگر سیستم به سرویس های کوچکتر تقسیم شود و هر سرویس را روی یک ماشین مجازی قرار داده باشیم میتوانیم براساس میزان استفاده از آن سرویس بهش منابع تخصیص بدیم و Scale ش کنیم. و این باعث میشه بتوانیم هزینه های سخت افزاری را کنترل کرده و کمتر کنیم.

 

مزیت راحتی در اسقرار Ease of Deployment در میکروسرویس ها

در سیستم های یکپارچه وقتی ما یک خط ار نرم افزار و کد را تغییر میدهیم همه چندین میلیون سطر برنامه باید دوباره آپلود و Deploy بشن و این باعث ریسک بسیار زیاد در Deploy میشه. در عمل اینطور آپلودها که High-Risk و Large-Impact هستند به دلیل ترسی که ایجاد میکنند به ندرت اتفاق میفتند. این بدان معناست که ما تغییرات کوچک را آپلود نمیکنیم و صبر میکنیم تغییراتی که انجام دادیم زیاد بشوند تا یکجا اونهارو آپلود کنیم و بعدش تست کنیم. و این باعث میشود که بازهم موقع آپلود یکپارچه خطر و ریسک اپلود تغییرات زیاد باشه و اینکه ما تغییرات رو معطل هر Release کردیم.

با استفاده از میکروسرویس ولی ما میتواینم هر سرویس را مستقل از کل نرم افزار Deploy کنیم. همین باعث میشه ما بتونیم دیپلوی های سریعتر داشته باشیم و سریعتر نسخه بدیم و وقتی مشکلی ایجاد شد سریعا رفع کرده و فقط همون سرویس را آپلود کنیم و حتی اگر آپلود مشکل داری داشتیم Rollback سریعتری داشته باشیم. همچنین این کمک میکنه ما ویژگی های جدید به نرم افزارمان را بصورت سریعتر تحویل بدیم. همین دلیل محکمیه که چرا شرکت هایی مثل آمازون و تویتر و نتفلیکس از این معماری میکروسرویس استفاده میکنند.

 

مزیت همراستایی با سازمان Organizational Alignment در میکروسرویس ها

ما خیلی از مشکلاتی که از تیم های بزرگ و مخزن کد عظیم ایجاد میشه رو تجربه کردیم ولی وقتی هر تیم کوچکی روی یک سرویس تمرکز کنه هم این مشکلات از بین میروند و هم خلاقیت تیم ها و افراد روی توسعه نرم افزار بیشتر میشه. میکروسرویس به ما این امکان میده که معماری و روش پیاده سازی نرم افزار را براساس ساختار سازمانیمون بچینیم. حتی ما میتوانیم افرادی که روی هر سرویس کار میکنند را براساس مالکیت سرویس بین افراد تغییر بدیم.

 

مزیت ترکیب پذیری Composability در میکروسرویس ها

یکی از مزایای خیلی اصلی که ما در معماری سرویس گرا SOA و سیستم های توزیع شده Distributed System ها داشتیم امکان استفاده مجدد از کدها از فانکشن ها بود. در مدل میکروسرویس ما در واقع این امکان را داریم که Functionalities های ما رای اهداف مختلف و در جاهای مختلف مصرف شود. مخصوصا وقتی نرم افزاری داریم که قراره هم روی وب و هم اپلیکیشن های موبایل و هم نرم افزار دسکتاپ به مشتریان ما سرویس بده، این قابلیت خیلی به کار میاد. در واقع سازمان ها دارن به این سمت میرن که سرویس های خودشون را روی Channel های مختلف ارائه بدن تا Customer Engagement بالاتر بره و برای رسیدن به این هدف باید نرم افزار معماری را داشته باشه که این قابلیت رو فراهم کنه.

 

مزیت بهینه بودن برای جایگزینی Optmizing for Replacability در میکروسرویس ها

اگر شما در یک سازمان متوسط و یا بزرگ کار میکنید احتمالا با نرم افزارهای کهنه و قدیمی و خیلی بد نوشته شده برخورد میکنید که هیچ کسی جرات نداره بهشون دست بزنه. نرم افزارهایی که فقط روی سخت افزار خاصی که واسه 25 سال پیش هست میتونن اجرا بشن و به زبان برنامه نویسی خیلی قدیمی نوشته شدند. خوب چرا این نرم افزارها جایگزین نمیشن؟ پاسخش مشخصه : چون خیلی بزرگ و عظیم هستند و جایگزین کردنشون خیلی پر ریسک هست. ولی اگر ساختار میکروسرویسی باشد جایگزین کردن یک سرویس کوچک یا کلا حذف کردن یک سرویس کار خیلی سختی نیست. حتی وقتی لازم باشه اعضای تیم میتونن یک سرویس رو کلا بزارن کنار و کدشو از نو بنویسن و اینکار بیشتر از 1-2 هفته زمان نخواهد بود و کار خیلی راحتیه و نکته مهم اینه وقتی یک سرویسی هست که کلا چند صد سطر کد داره، برنامه نویس ها روش خیلی تعصبی ندارن و به راحتی جایگزینش میکنند.

 

مقایسه میکروسرویس با معماری سرویس گرا Microservice Architecture vs SOA

معماری سرویس گرا Service Oriented Architecture یا همان SOA یک مدل معماری است که در آن چندین سرویس مجزا سعی میکنند یک قابلیت نهایی را ارائه کنند. این سرویس ها کاملا از هم مجزا هستند و حتی سیستم عاملشون هم میتونه فرق کنه و یا روی یک سیستم عامل پراسس های جدایی برای هر سرویس وجود خواهد داشت. ارتباط بین این سرویس ها از طریق لایه شبکه و API ها انجام میشه. معماری سرویس گرا به عنوان رویکردی برای حل مشکلات معماری یکپارچه Monolithic ایجاد شد. این معماری تونست قابلیت استفاده مجدد Reusability رو به شدت افزایش بده و حتی چندین کانال مختلف از نرم افزار میتونساتند از یک سرویس همزمان استفاده کنند. این روش معماری نگهداری و تغییرات در نرم افزار رو کاملا راحتتر کرد حتی این قابلیت رو داد که یک سرویس را بدون ایجاد تغییرات زیاد و جدی در سرویس های دیگر بتوانیم کاملا تغییر بدیم یا جایگزین کنیم. نفس SOA ذاتا ایده خیلی خوبی است با این وجود علیرغم تلاش های بسیار نحوه درست اجرای معماری سرویس گرا خیلی مشخص نیست.

بیشتر مشکلاتی که در این مدل معماری وجود داره نبود تعریف درستی از پروتکل های ارتباطی یا Middleware ها و یا عدم راهنمایی در مورد جزییات سرویس یا راهنمای نادرست در مورد انتخاب مکان تقسیم بندی سیستم به سرویس ها می باشد. بیشتر قراردادهایی که حول SOA وجود دارد کمکی به شما نیمکند که بدانید یک سیستم بزرگ را چگونه به بخش های کوچک تقسیم کند. ولی میکروسرویس این مشکلات را حل کرده است. در واقع میتوان معماری میکروسرویس را یک نمونه و پلتفرم مشخص برای معماری SOA دانست. البته علاوه بر مدل SOA دو تا مدل برای تقسیم سیستم به بخش های کوچک وجود دارد که یکیش مدل Shared Libraries هست که میاد یه سری سرویس های کوچک و کتابخانه ابتدا مینوسیم و بعدش نرم افزار ما از این کتابخونه ها استفاده میکنه و مدل دیگر برنامه نویسی Modular هست که خود پلتفرم برنامه نویسی مثلا بصورت MVC میاد پروژه رو ماژولار میکنه که البته هیچکدام از این دو روش اولین قابلیت میکروسرویس را که همان استفاده از چندین تکنولوژی هست رو به ما نمیدهند و نمیتونند جایگزین معماری میکروسرویس باشند.

البته در نظر بگیرید معماری میکروسرویس یک نهار رایگان یا یه عصای جادویی محسوب نمیشه و مشکلات و پیچیدگی های خاص خودش رو داره. این مدل معماری مدل کدنویسی و معماری و حتی استقرار و تست متفاوتی رو داره و اگر شما از معماری مونولیتیک دارین به سمت میکروسرویس میاین احتمالا کلی پیچیدگی هست که باید یاد بگیرین و حلشون کنید.

 

میکروسرویس یک معماری تکاملی

همانطور که تا به اینجا متوجه شدیم میکروسرویس به ما انتخاب های زیادی میدهد و فرصت های تصمیم گیری زیادی را نیز فراهم میکند. اینکه چقدر تکنولوژی مختلف در یک نرم افزار باید استفاده کنیم؟ یا اینکه چگونه اعضای تیم را روی هر بخش پروژه تقسیم کنیم و یا اینکه سرویس ها را چگونه تقسیم کنیم؟ خوب حالا سوال اینجاست که ما چگونه باید این تصمیم ها را بگیریم؟یا تصمیم ها را تغییر دهیم. نقش معمار نرم افزار در این مدل هم دانستن نحوه گرفت این تصمیم ها و هم تغییرات مناسب دادن روی این تصمیم ها است. در این بخش میخواهم کمی بیشتر در مورد نقش شخص معمار نرم افزار Software Architect در این مدل معماری میکرو سرویس صحبت کنم.

 

مقایسه نادرست عنوان معمار نرم افزار با سایر رشته ها

معمار نرم افزار نقش بسیار مهمی و شغل بسیار حساسی دارد، اوکسی است که براساس دانش تکنیکال و دید فنی، مسئولیت تحویل نیازهای مشتری را براساس آنچه مشتری نیاز دارد، خواهد داشت. یک جمله معروفی میگه: "من مطمئن نیستم این کلمه ای که شما استفاده میکنی، دقیقا همون منظوری رو که شما بهش فکر کنی برسونه" این یعنی گاها مشتری منظورشو نمیتونه درست و دقیق بیان کنه و این وظیفه معمار نرم افزاره که در نهایت بتونه بفهمه نیاز مشتری چیه و این نیاز در ساختار فنی نرم افزار چگونه قابل پیاده سازی و تحویل است؟در بسیاری موارد معمار نرم افزار با یک تیم باید کار کنه. در مواردی معمار باید دید فنی و ساختار فنی که باید پیاده سازی بشه رو ترسیم کنه یا اینکه با چندین تیم مختلف در نقاط مختلف دنیا کار کنه یا اینکه حتی لازم باشه با کل یک سازمان در ارتباط باشه. معمار نرم افزار نقشی است که بیشتر از هر نقشی در معرض انتقاد قرار میتونه بگیره، چرا که معمار نرم افزار نقش و تاثیر اصلی را روی کیفیت نرم افزار دارد و همینطور تاثیر زیادی روی اعضای تیم نرم افزار و در نتیجه کل سازمان خواهد داشت. ولی ما هنوز هم میبینیم که گاها این نقش اشتباه تعریف میشود. چرا؟

صنعت نرم افزار یک صنعت جوان است. این چیزیه که گاها فراموش میکنیم. و ما حدود 70 سال است نرم افزارهایی میسازیم که روی چیزهایی به اسم رایانه اجرا میشوند. و هنوز هم ما از حرفه ها و دانش های دیگر برای بیان کاری که میکنیم استفاده میکنیم. ما در واقع پزشک یا مهندس نیستیم از آنور ما لوله کش یا برقکار هم نیستیم. در عوض ما یه جایی در این میان قرار داریم که هم باید کار تئوری کنیم و هم عملی و این باعث میشود که هنوز جامعه ما و حرفه ما را به درستی درک نمیکند و حتی خود ما هم نمیتوانیم به درستی درک کنیم جای ما کجاست؟

به همین دلیل ما از حرفه ها و تخصص های دیگه برای توصیف خودمان کمک میگیریم، ما خودمونو مهندس نرم افزار یا معمار خطاب میکنیم. ولی آیا واقعا ما اینها هستیم؟ معمارها و مهندساها نظرم و انضباط خاصی دارند که ما باید فقط رویای آن را ببینیم و اهمیت شغل آنها در جامعه به درستی تعریف شده و شناخته شده است. یادمه یه روز با یکی از دوستام که معمار نرم افزار هستند دقیقا روز قبل گرفتن مجوزش صحبت میکردم. او بهم میگفت اگه من از فردا برای شما کاری انجام بدم که به مشکی بخوری، من از لحاظ حقوقی دچار مشکل میشم و حتی ممکنه مجوز من باطل بشه. این رشته های مهندسی سالها درس میخونن تا این مجوز هارو دریافت کنند. مثلا شاید یک معمار باید 7 سال درس بخونه تا بتونه همچین مجوزی بگیره، مجوزی که پشتش هزاران سال تخصص و دانش معماری جهان وجود داره. ولی در مورد ما و رشته آی تی چطور؟ برای همین هم ما میایم از عناوین رشته های دیگه استفاده میکنیم تا خودمونو معرفی کنیم. ولی اینکار مضره چون وقتی میگیم ما معمار هستیم یا مهندس هستیم یعنی یه استانداردهایی مثلا بقیه معمارا و مهندسا برای کارهای ما براساس هزاران سال تجربه ودانش وجود داره در حالیکه آی تی جدیدتر از اونیه که بشه همچین ادعاهایی در موردش کرد.

من نمیگم پل ها و ساختمون ها خراب نمیشن و نمیریزن ولی تعداد دفعاتی که یه پل یا ساختمون میریزه خیلی کمتر از تعداد دفعاتیه که یه نرم افزار ممکنه کرش کنه. پس مقایسه رشته و دانش ما با مهندسیت واقعا غیرمنصفانه ست. یا اینکه اگر یه مهندس ساختمان در وسط راه متوجه بشه که پلی که ساخته مثلا 50 متر اشتباه شده باید با کلی سیمان و بتن و تغییرات واقعی این مشکلو حل کنه در حالیکه در دنیای نرم افزار ما براساس نساز مشتریمون بصورت تکاملی و کم کن نرم افزار رو براش میسازیم و تغییر میدیم و اصلاحش میکنیم. قوانین مهندسی پشتشون قوانین دنیای فیزیک و دنیای واقعی وجود داره ولی در نرم افزار همچین قوانینی وجود نداره.

از اونور واژه "معمار" که خیلی خطرناکتره. معمار یعنی کسی که یه چیزیو طراحی میکنه و نقشه شو میکشه و توقع داره همینطوری اجرا بشه. کار یک معمار ایجاد تعادل بین یک کار هنری، یک کار مهندسی، یک کار نظارتی همراه با رعایت سایر دیدگاه هاست که گاها مهندس سازه هم با اعمال قوانین فیزیک نکاتی را مشخص میکند که باید رعایت شود. در حوزه آی تی ولی داشتن همچین دیدگاه هایی باعث اتفاقا وحشتناکی میشود. دیاگرام پشت دیاگرام، صفحه های پی در پی داکیومنت معماری همگی سعی دارند یک نرم افزار خیلی کامل و ایده آل را بسازند بدون اینکه به مشکلات آینده پروژه و اجرا فکر کنند. اینکه پیاده سازی این طرح چقدر دشواره یا اینکه این واقعا کاربردی خواهد بود یا اصلا به درد مشتری میخوره؟ وقتی ما خودمونو با مهندسان و معمارها مقایسه میکنیم در واقع ممکنه با این رویکرد به هر کسی آسیب برسونیم. البته به هر حال کار ما با کلمه معمار و معماری در حال حاضر گره خورده. پس بهترین کاری که الان میتونیم بکنیم اینه که واژه معماری رو براساس حرفه خودمون تعریف کنیم.

 

یک تعریف تکاملی برای معماری نرم افزار: معمار شهر

نیازمندی های نرم افزار خیلی با سرعت بیشتری نسبت به ساختمان ها و تغییرات آنها تغییر میکنند، همانطور که ابزارها و تکنولوژی های ما هم خیلی سریعتر نسبت به سایر رشته ها تغییر میکنند. چیزایی که ما تولید میکنیم خیلی ثابت و قطعی نیستند. ما حتی بعد از اولین تحویل به مشتری تازه تغییرات و کار اصلیمون شروع میشه و روند تکامل نرم افزار شروع میشه. ما در حرفه خودمون پذیرفتیم که بعد از اینکه نرم افزار را به مشتری تحویل دادیم تازه روند تکامل نرم افزار شروع میشه و ما باید نرم افزار را براساس نظر مشتری تغییر بدیم و بهتر کنیم.

ما باید با این تغییرات و تکامل سازگاری نشون بدیم و پاسخگو باشیم. پس معمار نرم افزار باید بیشتر از اینکه بخواد یه چیزیو خیلی دقیق و کامل طراحی کنه و توقع داشته باشه همون اجرا بشه، باید به دنبال طراحی فریم ورک درستی باشه که نیازهای مشتری روی اون بستر قابل انجام باشه. ما بیشتر از اینکه معمار یک پروژه یا ساختمان باشیم شاید در حوزه آی تی معمار یک شهر هستیم که چارچوب های این شهر رو تعریف میکنیم، استانداردهای ساخت و ساز را تعریف میکنیم و اجازه میدیم داخل اون شهر براساس سلیقه مشتری و استانداردهایی که تعریف کردیم، ساختمان و پل و زیرگذر ساخته بشه مثل بازی سیم سیتی. معمار شهر باید با یک نگاه کلی به شهر نگاه کنه و چارچوب و Layout ای رو تعریف کنه که براساس اون شهروندان بتونن بهتر زندگی کنند و حتی باید به توسعه های آتی شهر هم فکر کنیم. مثلا مشخص کنیم کجای شهر مرکز صنعتی باید باشه و کجاش مرکز اقامتی و زندگی. و بعدش اجازه بدیم دیگران (برنامه نویسان و مشتری نرم افزار) داخل این شهر هر چیزی خواستند بسازند. مثلا اگر میخوان کارخونه بسازند، بسازند ولی یه سری محدودیت ها و قوانینی (همان استانداردها) وجود داره . کارخونه فقط میتونه در بخش صنعتی شهر ساخته بشه.

همینطور معمار نرم افزار باید وقت زیادیو صرف کنه و به این فکر کنه که آدما چطوری میتونن و باید از یک مرکز و بخش به مرکز و بخش دیگه ای بروند.یک شهر ممکنه براثر خوادث مختلف مثل ساخت و ساز یا بارون و سیل و طوفان همیشه در حال تغییر باشه و معمار این شهر باید این مواردو پیش بینی و کنترل کنه.این شهر هم باید برای ساکنینش که ازش استفاده میکنه هم برای کسایی که دارن توش کار میکنند مثل برنامه نویسها باید جای شاد و مناسبی باشه و در کنارش قوانین کلی شهر باید رعایت بشه.

 

بخش بندی شهر Zoning

خوب با همین تعریف معمار شهر برای معمار نرم افزار حالا میخوایم بگیم بخش های این شهر چی هستند؟ در واقع بخش های هر شهر محدوده سرویس ها در معماری نرم افزار هستند یا در واقع همین سرویس های خرد شده همین بخش ها و Zone های شهر ما هستند. به عنوان معمار نرم افزار ما بیشتر باید نگران ارتباط بین این بخش های شهری، محدوده های آنها و نوع ارتباط آنها با هم باشیم و کمتر نیازه که نگران داخل هر بخش یا zone باشیم که چه اتفاقی میفته.

ما به عنوان معمار نرم افزار بهتره بیشتر نگران ارتباط و تعامل بین این سرویس ها باشیم و به این فکر کنیم که سلامت و امنیت کلی این شهر و این سیستم رو تامین کنیم. اینکه در مورد داخل هر بخش و سرویس قراره چطوری عمل کنیم خیلی متفاوت میتونه باشه. بعضی شرکت ها برای همه سرویس هاشون یه استاندارد کلی برای تیم هاشون تعریف میکنند و بعضی شرکت ها اصلا کاری ندارند و هر سرویس داخل خودش تعریف میشه و عمل میکنه و کلا خیلی داخل این بخش ها دغدغه معمار نرم افزار نیست ولی ارتباط و تعامل بین سرویس ها خیلی مهمه و هر خطا و مشکلی در اینجا باعث کلی مشکل خواهد شد.

البته که داخل هر سرویس تا یه حدی مهمه. مثلا اگر شما 10 تا سرویس داشته باشین و هر سرویس قراره باشه از یه زبان برنامه نویسی استفاده کنه یا یه دیتابیس متفاوتو انتخاب کنه اونوقت چیکار باید کرد؟استخدام اینهمه برنامه نویس ونحوه Scale up کردن دیتابیس و ... مشکلات این حالت هستند. باید این مسائل با هماهنگی و تعامل تیمی و شرکتی تصمیم گیری بشه ولی شما به عنوان معمار باید موافق انتخاب تکنولوژی و روش کار متفاوت داخل هر سرویس باشید یعنی خودمختاری سرویس یک اصل در این مدل معماری است.

یه عنوان مثال شرکت نتفلیکس اومده دیتابیسشو Cassandra استفاده میکنه برای اکثر سرویس ها و با اینکه میتونه برای بعضی سرویس ها از ابزار دیتابیس مناسبتی استفاده کنه ولی معتقده اینکه دولوپرهاش کاساندرا رو خوب بلد باشن و باهاش کار کنند بهتر میتونه هر وقت خواست Scale کنه و اینطوری انتخاب کرده.

ولی بین سرویس ها جاییه که ممکنه مشکل ایجاد بشه و اینجا قوانین خیلی مهم هستند. مثلا اگه یه سرویس بگه من میخوام از روش ارتباطی Rest روی بستر Http استفاده کنم و یکی دیگه بگه من میخوام از Protocol Buffer استفاده کنم و اون یکی بیاد بخواد از JAVA RMI استفاده کنه اونوقت مدیریت این ارتباط  موقع یکپارچه سازی مثل یه کابوس خواهد بود، چرا که هر مصرف کننده سرویس مجبوره کلی روش ارتباطی رو بلد باشه تا وقتی با هر سرویس حرف میزنه با زبان ارتباطی اون سرویس ارتباط برقرار کنه. واسه همینه که خیلی مهمه ما یه قوانین برای این ارتباط پایبند باشیم.در واقع میگیم هرچیزیکه بیرون باکس ها (اشکال معماری در دیاگرام) اتفاق میفته دقیقا باید براساس قوانین ما باشه ولی ما خیلی دخالتی به درون باکس ها نداریم.

 

معمار کد The Coding Architect

سرگرم کننده و مفرح بودن کار کردن و برنامه نویسی برای اعضای تیم پروژه خیلی بستگی به تصمیمات معمار نرم افزار داره. وقتی شما معمار نرم افزار هستید خیلی سودبخش و ارزشمنده که با اعضای تیم ارتباز داشته باشین. اینکه اولش سند معماریو تحویل بدین وگاها به سوالاتشون پاسخ بدین هم یک راهه ولی راه درستی نیست. معمار نرم افزار باید در فرآیند کدنویسی کنار اعضای تیمش باشه و کمکشون کنه و در واقع معماری کد رو انجام بده و روش نظارت داشته باشه.

 

یک رویکرد اصولی و اساسی

"قوانین برای اطاعت احمقان و برای هدایت خردمندان نوشته میشوند"

زمان طراحی یک سیستم، اتخاذ تصمیمات همگی براساس "داد و ستد Trade-off" هستند و در معماری میکروسرویس ما کلی Trade off داریم. مثلا موقع انتخاب یک پلتفرم برنامه نویسی که به ما امکانات زیادی رو میده ولی ما تجربه زیادی روش نداریم در واقع داریم Trade-Off میکنیم. یه چیزی رو میدیم یه چیز دیگه میگیریم. از یه چیزی چشم پوشی میکنیم یا یه چیز دیگه به دست بیاریم. هیچ چیزی نمیتونه ایده آل کامل باشه و همه چی در معماری نرم افزار Trade-Off هست. اینکه توی پروژه دو تا زبان برنامه نویسی باشه یا سه تا؟ دیتابیسمون چیا باشن؟ اینها همش تصمیم گیری ها در طراحی سیستم هستند که با tarde-off اتفاق میفتند. اگه برای گرفتن تصمیمی اطلاعات کافی و کامل داشته باشیم که خوب همه چی آسونه ولی وقتی اطلاعاتمون کافی نیست چی؟ برای همین باید ساختار تصمیم گیری Decesion Making رو به مراحلی اصولی براساس قواعدی مشخص تقسیم بندی کنیم که در ادامه به برخی از اونها اشاره میکنم.

 

اهداف استراتژیک و حیاتی Strategic Goals

صیصثی

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


مشاوره با من مهدی محمدی

هر سوالی دارید یا درخواست جلسه مشاوره دارید، خوشحال خواهم شد که با هم در ارتباط باشیم