لینک ویدئو: https://www.youtube.com/watch?v=xVKJvUHCanQ
سخنران: Henrik Bærbak Christensen
خلاصه:
این ویدئو درباره energy efficiency است که در آن تاکتیکهایی برای مصرف بهینه انرژی پیشنهاد شد. اگر بخواهیم برای پرسش و پاسخ در فضای کنفرانس به جای حالت شفاهی یک برنامه بنویسیم، عملا انرژی بسیار زیادی را هدر دادیم.
برای اینکه معماری ما energy efficiencyداشته باشد، باید فیزیک بدانیم. انرژی میزان کار انجام شده است. سختافزار انژی مصرف میکند تا نرمافزار بتواند کار خود را انجام بدهد. برای مثال در کامپیوترهای gaming، CPUبه علت مصرف انرژی زیاد داغ میکند. برای اینکه بتوانیم خنکش کنیم، باید از فن استفاده کنیم که خودش انرژی مصرف میکند!
برای اینکه بتوانیم طراحی خوبی داشته باشیم که مصرف انژی کمتری داشته باشد، باید از فریمورکهای متناسب با green architectureاستفاده کنیم. این فریمورکها شامل فرایندها و تاکتیکها هستند. فرایندها نحوه طراحی را مشخص میکنند که در ادامه به معرفی آنها پرداخته شده است.
فرایندهای طراحی معماری سبز:
1) You need to measure
برای اینکه بتوانیم معماریها را مقایسه کنیم، لازم است آزمایش کنیم. در واقع نیاز به اندازهگیری میزان مصرف انژی داریم. برای اینکه بتوانیم اندازهگیری کنیم، یک راه استفاده از برنامههای دیگر است.
2) اولویتبندی
باید بتوانیم منابع فکری کمتری استفاده کینم و همچنین زمان برنامه نویسی را هم مدیریت کنیم.
3) سومین مورد افزایش آگاهی است که از طریق تعامل با افراد حاصل میشود.
تاکتیکهای معماری سبز: هفت دسته اصلی از تاکتیکهای وجود دارد تا بتوانیم به معماری برسیم که مصرف انرژی آن بهینه باشد.
1) اگر چیزی را استفاده نمیکنیم باید خاموش کنیم. (Shut down when idle)
در معماری میکروسرویس بحث scale downو scale up وجود دارد. اگر این scaling انجام نشود، میکروسرویسها خیلی انرژی مصرف میکنند. این تاکتیک بیشتر زمانی استفاده میشود که میخواهیم scalingانجام دهیم.
2) Avoid unnecessary resources
برای درک بهتر این موضوع، میتوانیم مثال سفر رفتن را در نظر بگیریم. برای مسافرت دو روزه نباید چمدان را به اندازه یک هفته پر کنیم. در نرمافزار هم همین اصل برقرار است. باید سعی کنیم payloadرا کمینه کنیم. مثلا برای ارسال در شبکه، اطلاعات بیهوده نفرستیم.
3) Bulk fetch data
مثلا اگر به فروشگاه برویم و چیزی را فراموش کنیم، مجددا باید برگردیم و خرید کنیم. این درباره ترافیک شبکه هم صادق است. اسم این روش batch method است. به جای اینکه هر بار یک بخش از دیتا را بگیریم، در یک bulkبزرگ دیتاها را دریافت کنیم. (27 درصد صرفه جویی در انرژی در سمت سرور)
4) Fetch data from proximity(مشابه caching)
5) Utilize an efficient technology
در سال 2017 مقایسه بین مصرف انرژی زبانها برنامه نویسی انجام شد که زبان C از همه بهتر بود و زبان Python امتیاز خوبی نداشت.
همچنین باید از پایگاههای داده بهینه استفاده کنیم. مثلا استفاده از Redis مصرف انرژی را 31 درصد کاهش میدهد.
6) Utilize your resource efficiency
7) Accept lower fidelity
اگر برای ارسال یک عکس، کیفیت آن پایین بیاید راحتتر منتقل میشود. پس میتوانیم به جای استفاده از یک تجربه خاص، حالت عادی را استفاده کنیم تا مصرف انرژی کاهش یابد. یکی از راهها در این زمینه کاهش loggingاست.
یک راههای دیگر هم feature creepاست. شاید در برخی از موارد استفاده از همه جزئیات لازم نباشد.
لینک ویدئو: https://youtu.be/Idkz_rOS-ug?si=5Q_TlUxdv2g_RzVS
سخنران: Randy Shoup
خلاصه:
در این ویئدو به چهار حوزه پرداخته شده که شامل Architecture Evolution، Service Architecture، ارتباطات event-driven و ترکیب رویداد و سرویس هستند.
1) موضوع اول: Architecture Evolution
سه مرحله برای رشد هر شرکت وجود دارد. مرحله اول starting است که در آن تیم کوچک است و معماری مونولیتیک دارد. (در هیچ نرمافزار موفقی از ایتدا معماری میکروسرویس استفاده نشده است)
مرحله دوم scaling است که در آن چند تیم وجود دارد و سرعت و مقیاس پذیری در اضافه کردن نیازمندیها دارد. همچنین معماری آن به جای مونولیتیک، میکروسرویس است. مرحله سوم نیز optimizing است که در آن تعداد تیمها کاهش یافته و به جای دستیابی به سرعت و مقیاسپذیری هدف کارایی بیشتر است.
اگر برنامههای موفق مانند eBay، Twitter و آمازون را در نظر بگیریم در ابتدا معماری آنها به صورت مونولیتیک بوده و سپس به میکرورسرویس تغییر کرده است. با توجه به این مثالها، میتوان گفت که الگویی در تغییر معماری وجود دارد. هیچ نرمافزاری از همان ابتدا با میکروسرویس کار خود را شروع نکرده است.
2) موضوع دوم: Service Architecture
در هر سامانه در حال رشد، چند تیم وجود دارد که باید بتوانند به صورت مداوم تغییرات را مستقل از بقیه اعمال کنند. معماری این سیستم به ازای هر دامنه دارای یک تیم است که مسئول توسعه و نگهداری سرویسهای آن است. ارتباط با سرویسها نیز فقط از طریق واسطی است که ارائه دادند.
برای مثال اگر سامانه فروش لباس را در نظر بگیریم که فقط یک پایگاه داده دارد، در صورت کندی DB، کل سامانه از کار میافتد. راهحل این است که DB به صورت مونولیتیک نباشد و decoupled شود.
مراحل ایجاد این DB با ایجاد سرویس برای هر جدول در این پایگاه داده است. برای مثال اگر جدول کلاینت را در نظر بگیریم، سرویس استفاده از آن را میسازیم و در اختیار سایر سرویسها که به این اطلاعات نیاز دارند، قرار میدهیم. در ادامه باید این جدول را از DBمشترک خارج کرده و به شکل خصوصی برای همان سرویس قرار بدهیم. این کار باعث ایجاد service boundary میشود.
3) ارتباطات event-driven
وقتی استیت برای کاربر، آیتم یا ... تغییر کند، یک رویداد منتشر خواهد شد که بخشی از سیستم به آن واکنش نشان میدهد.
4) ترکیب سرویس و رویداد
هر دادهای که در سیستم است، فقط یک سرویس مالک آن است. اما علاوه بر مالک داده، سرویسهای زیادی هستند که به آن اطلاعات نیاز دارند. در این صورت لازم است که سرویس مالک به آنها یک کپی read-onlyبدهد.
در ادامه ویدئو، به بررسی برخی از چالشها و ارائه راهحل برای آنها در رابطه با رویدادها و داشتن DBهای خصوصی برای هر سرویس پرداخته شد.
- در صورت تغییر استیت، رویداد تولید میشود. دو راه حل برای این کار وجود دارد. راه اول change data capture است. در این حالت تغییر در DBنوشته شده و سپس تبدیل به رویداد میشود. راه دوم transactional outboxاست که در همان ابتدا تغییر و رویداد متناظر با آن در یک DB ذخیره میشوند.
- چالش دوم در رابطه با دادههای اشتراکی است. دو رویکرد برای مدیریت این دادهها وجود دارد. راه اول synchronous lookup است. در این رویکرد از سرویس مسئول آن DBسوال کرده و به صورت بلادرنگ پاسخ دریافت کند. راه دوم asynchronous events and local cache است. در این رویکرد، سرویسی که اطلاعات را میخواهد آنها را به صورت کش شده ذخیره میکند.
- چالش بعدی در رابطه با join جداول از DBهای مختلف است. راه اول join in client application است که خیلی ساده بوده ولی در عمل فشار و تاخیر زیادی دارد. راه دوم سرویسی است که materializing the view انجام میدهد.
- چالش دیگر، transactionها هستند. در DBهای مونولیتیک ایجاد یک تراکنش روی چند موجودیت بسیار راحت است برای برای حالت توزیع شده باید راهحل دیگری استفاده کرد. برای این کار باید تراکنش را به صورت جریانی از کارها (workflow) که به آن saga گفته میشود، در نظر بگیریم. در واقع یک زنجیره از آپدیتها داریم که هر کدام رویداد ورودی بعدی را تولید میکنند. برای roll back نیز باید در جهت عکس رویدادها را تولید کنیم.
این رویکرد در بسیاری از سیستمها وجود دارد. برای مثال یک تراکنش بانکی، فرایند توسعه و ... را میتوان به صورت یک workflowدر نظر گرفت. در این workflow علاوه بر استیت نهایی، استیتهای میانی هم وجود دارد.
لینک ویدئو: https://youtu.be/izLg4NkJQO4?si=OQzPaxNWo1NNVH8b
سخنران: James Lewis
خلاصه:
بحث team topology درباره سازماندهی تیمها و ساختار آنهاست. در اوایل ویدئو نقل قولی از یکی از افراد در آمازون گفته شد:
“The bigger we get, the easier it becomes to get bigger”
هر قدر تیمها بیشتر شده و مقیاس شوند، ساخت محصولات بیشتر راحتتر خواهد بود. هدف team topology و این سازماندهی بهینه کردن جریان رسیدن به ارزش است.
چهار نوع تیم از دیدگاه team topologyوجود دارد. اولی stream-aligned است که محصول را مستقیما به مشتری تحویل میدهد. سایر انواع تیم نیز شامل enabling team، complicated subsystem و platform team هستند.
پیچیدگی معماری
فرد بروکس در کتاب خود (The Mythical Man Month) گفته که اضافه کردن نیروی انسانی به پروژهها میتواند تحویل آن را به خاطر سربار ارتباط افراد به تاخیر بیندازد. اما در آمازون این طور نبوده و با دو برابر شدن اندازه سازمان درآمد دو برابر میشود و تاخیری در پروژهها ایجاد نمیشود. علت این اتفاق این است که در آمازون، ارتباطات از طریق واسط مشخصی است و تعداد افراد تیمها کم است به طوریکه همه آنها با داشتن دو پیتزا سیر میشوند. آمازون برای بهبود جریان ارزش و تحویل سریع محصول به مشتری سه اصل team isolation، limiting interaction to nearby team و scale Dunbar’s numberاست.
سیستمهای complex adaptive
در ابتدای این بخش مثالی از پستانداران زده شد. از نظر بیولوژی با اینکه اندازه موش و فیل متفاوت است اما هر دوی آنها دارای فشار خون و ضربان قلب یکسان هستند. آنچه این دو موجود (و سایر پستانداران) را از هم متمایز میکند تفاوت در متابولیسم (سوختوساز) آنهاست. هر قدر پستاندار بزرگتر باشد، میزان سوختوساز آن کمتر است. در اینجا قانونی تحت عنوان scaling rule وجود دارد که به همین مسئله اشاره میکند. با افزایش دو برابری اندازه پستاندار، سوختوساز آن حدود 0.75 برابر میشود. همین اصل برای سازمانها هم برقرار است. یعنی با دو برابر کردن اندازه سازمان (تعداد افراد آن) درآمد دو برابر نمیشود بلکه بین 75 تا 85 درصد افزایش مییابد. این نوع از scaling را sub-linear scaling مینامند.
علت این اتفاق چیست؟
سیستمهای complex adaptive دارای چهار مشخصه خودمشابهتی، خودسازماندهی، پیچیدگی و emergence هستند. این سیستمها با در نظر گرفتن سه اصل قابل سادهسازی هستند. اصل اول در نظر داشتن سلسله مراتب است. اصل دوم invariant terminating unit و اصل سوم نیز optimizationاست.
علت دو برابر نشدن درآمد با دو برابر شدن اندازه سازمان، ساختار سلسله مراتبی است. هر قدر این ساختار عمق بیشتری داشته باشد، جریانهای اطلاعاتی کندتر بوده و در نتیجه درآمد افزایش خطی با اندازه سازمان نخواهد داشت. پس میتوان نتیجه گرفت که سازمانهای سلسله مراتبی رشد sub-linear در درآمد دارند و در نتیحه نرخ سوختوساز آنها کمتر است.
اما مدلی دیگری برای مقیاسبندی وجود دارد که super-linearنام دارد. در این مدل با دو برابر شدن x، مقدار yبیش از دو برابر میشود. این نوع از scaling در ساختار social networkها وجود دارد. مثالی از این ساختار در Spotify و thoughtWorks است.
پس به صورت خلاصه:
- ساختار سلسله مراتبی که economic of scaling (less than you think) است
- ساختار social network که returns to scale (more than you think) است
پس میتوان نتیجه گرفت که آمازون از ساختار social networkاستفاده میکند که توانسته درآمد خود را بیشتر کند.
لینک ویدئو: https://youtu.be/Ysn6eInApYM?si=U1boPLoY1IWeXPOz
سخنران: Dave Farley
خلاصه:
مانیتفست سیستمهای reactive یک رویکرد جالب برای معماری نرمافزار است. سیستم reactive یک سیستم توزیع شده است که تعدادی مشخصه کابردی دارد. از نظر مانیفست reactive این سیستمها به صورت زیر تعریف میشوند:
“These systems are more robust, more resilient, more flexible and better positioned to meet modern demands.”
سیستم reactive باید دارای ویژگی باشد:
1) باید responsive باشد. یعنی در زمان مشخص پاسخ بدهد.
2) باید resilient باشد. یعنی در شرایطی که failureرخ داده است باید responsive بماند.
3) این سیستم elastic است. در بار کاری مختلف باز هم responsiveمیماند.
4) همچنین message driven است. یعنی سیستم reactiveمبتنی بر async message passing است. همچنین بیانگر loosely coupled بودن سیستمهای reactiveاست.
برای درک بهتر این ساختار در ویدئو مثالی آورده شده است. اگر سیستم سفارش کتاب را در نظر بگیریم که از دو بخش store و warehouseتشکیل شده باشد، تمام تعاملات از طریق پیامهای async است. این ساختار نسبت به حالت sync سریعتر است (برای دریافت پاسخ صبر نمیکند) و همچنین responsive است.
به طور کلی در این ساختار هنگامی که پیام دریافت میشود، پردازش انجام شده، استیت برنامه تغییر میکند و سپس پیام دیگری به عنوان خروجی داده میشود. تنها فرضی هم که برای این سیستمها وجود دارد ارسال پیام است و اینکه بالاخره به دست گیرنده میرسد.
لینک ویدئو: https://www.youtube.com/watch?v=GBTdnfD6s5Q
سخنران: Sam Newman and Martin Fowler
خلاصه:
در این ویدئو کتاب «Monolith to Microservices» که توسط Sam Newman نوشته شده، معرفی شد و پاسخ به تعدادی از چالشها در همین زمینه داده شد. در ادامه مرور کوتاهی از مباحث مطرح شده آمده است.
- چه زمانی باید از میکروسرویس استفاده کنیم؟
طبق دیدگاه نیومن، استفاده از میکروسرویس یک تصمیم آگاهانه است که منجر به پیادهسازی در یک سبک خاص شده و خروجی مورد انتظاری را به ما میدهد. در واقع معیاری که برای انتخاب این سبک وجود دارد با توجه به چیزهایی است که برای ما به همراه خواهد داد. معماری میکروسرویس به ما گزینههای زیادی در راستای scale-up میدهد، منجر به امکان استقرار مستقل از هم میشود و با محدود کردن حوزه اثرگذاری و آسیب ناشی از failureمنجر به تولید نرمافزار پایدارتری میشود. طبق گفته جیمز لوئیس استفاده از میکروسرویس هزینههایی دارد.
“Microservices architecture buy you options”
- میکروسرویس نباید گزینه پیشفرض در تولید یک نرمافزار باشد مگر اینکه دلیل خوبی برای انتخاب آن داشته باشیم.
- سه تا از اصلیترین دلایلی که میتواند منجر به انتخاب معماری میکروسرویس شوند شامل نیاز به استقرار مستقل، ایزوله کردن دادهها و پردازش آنها و نیاز به خودمختاری سازمانی هستند. با استفاده از استقرار مستقل به zero downtimeهم دست پیدا میکنیم. در واقع این نیاز برای برخی از برنامهها مانند SaaSضروری است.
- برای جلوگیری از distributed monolithic چا کار باید کرد؟
این مشکل زمانی پیش میآید که با هدف ایجاد معماری میکروسرویس کار را شروع کردیم ولی در عمل برای استقرار یک میکروسرویس به دیگری نیاز است که آن هم به میکروسرویس دیگر برای استقرار خود نیاز دارد و ... در واقع independent deployability برقرار نیست.
دو راه حل اصلی نیومن معرفی کرده است:
نکته مهم در طراحی نیز توجه به information hiding یا پنهانسازی اطلاعات است. در میکروسرویس هر قدر اطلاعات بیشتر مخفی شده باشند، امکان تغییرات داخلی بیشتر است.
- چرا independent deployability به عنوان اولین دلیل مطرح شد؟ در حالی که بسیار از نرمافزارها هستند که به صورت مونولیتیک بوده و حتی فرایند استقرار دارند که خودکار است.
مثالهای زیادی در این زمینه وجود دارد و داشتن فرایند استقرار مداوم برای معماری مونولیتیک هم ممکن است. اما معماری میکروسرویس تاثیر تغییرات در هر انتشار را محدودتر میکند. در واقع محیطی ایمن برای اعمال تغییرات ایجاد میکند. در واقع استقرار در مونولیتیک هم قابل انجام است اما بسیار زمانبر است در حالی که معماری میکروسرویس این کار را سریعتر و کارامدتر انجام میدهد.
چالش دوم درباره افزایش اندازه تیمهاست. هر قدر تعداد افراد تیم بیشتر باشد، مدیری و هماهنگی استقرار پیچیدهتر خواهد بود.
- مورد دیگر، مدیریت دادههاست. در جداسازی بخشها باید بتوانیم دادهها را مدیریت کنیم. جداسازی DBهای رابطهای به خاطر ماهیت آنها ناممکن است زیرا امکان جداسازی روباط را نداریم. پس شاید بهتر باشد از همان ابتدا طراحی را به صورت جداگانه انجام بدهیم و schemaها را جداگانه طراحی کنیم. (حتی اگر DB یکپارچه باشد)
این مطلب، بخشی از تمرینهای درس معماری نرمافزار در دانشگاه شهیدبهشتی است.