<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های علی کاویانی</title>
        <link>https://virgool.io/feed/@ali.kaviani</link>
        <description>مهندس ارشد توسعه نرم افزار مجموعه صباایده، فیلیمو، آپارات | Staff Engineer @Sabaidea,</description>
        <language>fa</language>
        <pubDate>2026-06-07 15:08:33</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/41674/avatar/avatar.png?height=120&amp;width=120</url>
            <title>علی کاویانی</title>
            <link>https://virgool.io/@ali.kaviani</link>
        </image>

                    <item>
                <title>الگوهای معماری میکروسرویس بخش دوم : الگوهای جداسازی</title>
                <link>https://aparat.design/microservice-patterns-part-2-tdfbhohughw8</link>
                <description>از بخش اول الگوهای معماری میکروسرویس خیلی وقت گذشته و الوعده وفا! در پست قبلی در مورد کلیات الگوهای معماری میکروسرویس صحبت کردیم و به تفصیل به الگوهای بانک‌های اطلاعاتی پرداختیم، در بخش دوم این سری از مقالات به سراغ الگوهای جداسازی می‌رویم: https://aparat.design/microservice-patterns-part-1-xfktsz2zal3q الگوهای جداسازی الگوهای مورد استفاده برای جداسازی میکروسرویس‌ها یا به زبان دیگر، شکستن یک مونولیت به چندین میکروسرویس، عموماً براساس نوع تصمیم‌گیری دسته‌بندی می‌شوند. الگوهای زیر جزو موارد پرکاربرد در این زمینه هستند:جداسازی بر اساس قابلیت های کسب و کاریجداسازی بر اساس زیر دامنهجداسازی بر اساس تراکنشجداسازی به روش Stranglerهمان‌طور که در مقاله قبل دیدیم در معماری میکروسرویس تمام تلاش ما به استفاده از اصل مسئولیت‌پذیری یکتا برای طراحی میکروسرویس‌هایی است که تا جای ممکن به یک‌دیگر وابستگی نداشته‌باشند و ما را به هدف نهایی که افزایش سرعت توسعه و Delivery محصول است نزدیک کنند.مثلث موفقیتمعماری میکروسرویس این کار را به دو روش انجام می‌دهد:تست‌کردن بخش‌های مختلف، کد را ساده  و در نتیجه امکان توسعه اجزای مختلف را به‌صورت مستقل فراهم می‌کند.تیم‌های مهندسی را ساختاربندی می‌کند یعنی تیم به صورت مجموعه‌ای از تیم‌های کوچک ۶ تا ۱۰ نفره‌ی مستقل، که هر کدام مسئولیت توسعه و نگهداری یکی از سرویس‌ها هستند، تقسیم می‌شوند.توجه: این مزایا به صرف تصمیم‌گیری برای استفاده از میکروسرویس به وجود نمی‌آیند و این امر نیازمند جداسازی نرم‌افزار به سرویس‌های کوچک‌تر وظیفه‌محور است، یک سرویس، باید آن‌قدر کوچک باشد که یک تیم کوچک برای توسعه و تست آن کفایت کند.یک راهبرد مفید در این زمینه استفاده از اصل مسئولیت واحد(Single Responsibility) از موضوع کلی‌تر Object Oriented Design است، در این اصل، گفته می‌شود: رای رسیدن به یک طراحی خوب، نیاز داریم که هر کلاس تنها و تنها یک هدف و وظیفه را در برنامه ایفا کند. کار تمام روش‌های(Methods) کلاس باید در راستای رسیدن به آن هدف باشد و استفاده از هر روشی با وظایف منحرف از هدف اصلی اشتباه است؛ این امر باعث درهم‌تنیدگی وظایف در برنامه و بنابراین پیچیدگی کد و در نتیجه کم‌کردن Reusability یا قابلیت استفاده مجدد از کدها می‌شود، همچنین هر روش کلاس باید تنها و تنها یک وظیفه را ایفا کند.جداسازی سرویس‌ها نیز باید به گونه‌ای باشد که تغییرات مورد نیاز تنها یک سرویس را تحت تاثیر قرار دهد. چون پیاده‌سازی امکاناتی که بتواند چند سرویس را تحت تاثیر قرار دهد، نیازمند هماهنگی بین چند تیم است که باعث کند شدن روال توسعه می‌شود.یکی از دیگر اصول مفید OOD برای جداسازی میکروسرویس ها اصل Common Closure Principle است. این اصل بیان میکند: کلاس‌هایی که به دلایل مشابهی نیاز به تغییر دارند باید در یک پیکچ قرار گیرند.به‌طور مثال فرض کنید دو کلاس بخش‌های متفاوتی از یک قاعده کاری (بیزینسی) را پیاده‌سازی می‌کنند. اگر این قاعده کاری تغییر کند، هدف ما این است که تغییرات مورد نیاز کد در کمترین تعداد پکیج‌ها لازم باشد(‌به‌صورت ایده‌آل تنها یک پکیج).این دیدگاه در زمان طراحی سرویس‌ها خیلی کمک‌کننده است؛ چون به ما کمک می‌کند مطمئن شویم هر تغییری تا جای ممکن فقط یک سرویس را تحت‌تاثیر قرار دهد.صورت مساله؛ چگونه یک نرم‌افزار را به چند سرویس کوچک‌تر تقسیم کنیم؟چگونه یک نرم افزار را به چند سرویس کوچکتر تقسیم کنیم ؟نیازمندی ها :معماری نهایی باید پایدار باشد.سرویس‌ها باید به هم پیوسته باشند. به عبارت دیگر هر سرویس باید مجموعه‌ای از توابع به‌شدت مرتبط باشد.هر سرویس باید از اصل CCP (Common Closure Principle) تبعیت کند، یعنی بخش‌هایی که باید باهم تغییر کنند داخل یک سرویس قرار بگیرند تا در صورت نیاز به تغییر، تنها یک سرویس تحت‌تاثیر قرار گیرد.سرویس‌ها باید کمترین وابستگی را به هم داشته باشند. هر سرویس به عنوان یک API پیاده‌سازی می‌شود و هرگونه تغییر در پیاده‌سازی داخلی نباید سرویس‌گیرندگان را تحت‌تاثیر خود قرار دهد.هر سرویس باید قابل تست باشد.هر سرویس باید به اندازه‌ای کوچک باشد که توسط یک تیم &quot;دو پیتزایی&quot; قابل پیاده‌سازی و نگهداری باشد.هر تیمی که مسئولیت یک یا چند سرویس را برعهده دارد باید خودکفا باشد. تیم باید با کمترین نیاز به هماهنگی با دیگر تیم‌ها، توانایی توسعه و پیاده‌سازی سرویس خود را داشته باشد.راهکار اول : جداسازی بر اساس قابلیت های کسب و کارییکی از پایه‌ای‌ترین راه‌ها برای طراحی سرویس‌ها، تعریف‌کردن آن‌ها براساس قابلیت‌های کسب و کاری سیستم است.تعریف قابلیت‌های کسب‌و‌کاری معمولاً بر پایه یک هدف انجام می‌شود. برای مثال:۱. سیستم مدیریت سفارشات، مسئولیت سفارش‌های کاربران را برعهده دارد.۲. سیستم مدیریت مشتریان، مسئولیت مدیریت کاربران را برعهده دارد.قابلیت‌های کسب و کاری اغلب به صورت وراثتی، چندلایه دسته‌بندی می‌شوند.در مثال یک نرم‌افزار سازمانی enterprise:ممکن است دارای دسته‌بندی‌های بالادستی به شرح زیر باشد:توسعه محصولتحویل محصولخلق نیازیا در مثال فروشگاه آنلاین:بخش‌های کسب و کار یک فروشگاه آنلاین می‌تواند شامل موارد زبر باشد:مدیریت محصولاتمدیریت انبارمدیریت سفارشاتمدیریت تحویل کالاو ...در این نمونه معماری میکروسرویس‌ها نیز می‌تواند معادل هر یک از این قابلیت‌ها باشد.جداسازی سرویس ها بر اساس قابلیت های کسب و کارمزایای این الگو :معماری سرویس‌ها پایدار است، زیرا قابلیت‌های کسب و کار معمولا این‌گونه هستند.تیم‌های پیاده‌سازی علاوه‌بر اینکه خودکار و مستقل هستند، براساس ارزش‌های کسب و کار و نه براساس امکانات فنی مورد نیاز، دسته‌بندی می‌شوند.سرویس‌ها چسبندگی لازم را دارند و کمتر به هم وابسته هستند.مشکلات این الگو :طراحی نرم‌افزار کاملاً به مدل کسب و کار وابسته است.این روش نیازمند شناخت عمیق از قابلیت‌های کسب و کار است و انجام این کار، امری مشکل خواهد‌بود.راهکار دوم، الگوی جداسازی براساس زیردامنه‌ها سرویس‌های خود را با استفاده از زیردامنه‌های الگوی Domain-Driven-Design(DDD) جدا کنید. در اینجا DDD به حوزه و دامنه‌ای اصلی و فرعی فعالیت نرم افزار اشاره می‌کند، به‌گونه‌ای که دامنه، متشکل از چندین زیردامنه است و هرکدام از این زیر دامنه‌ها معادل یکی از بخش‌های آن کسب و کار هستند.زیردامنه‌ها می‌توانند به صورت زیر دسته‌بندی شوند:هسته: وجه تمایز کسب و کار، از دیگر کسب و کارها به‌شمار می‌رود که به نوعی با‌ارزش‌ترین بخش آن نرم‌افزار است.پشتیبان‌ها: بخش‌هایی که برای سرویس‌دهی هسته مورد نیاز هستند، اما بخش مختص به کسب و کار شما نیستند (مثلاً بخش Automatioc Marketing)‌. این بخش‌ها می‌توانند به صورت داخلی پیاده‌سازی و یا برون‌سپاری شوند.بخش‌های عمومی: این بخش‌ها مخصوص کسب و کار نیستند و به‌ صورت ایده‌آل توسط نرم‌افزارها یا سرویس‌های آماده پیاده‌سازی می‌شوند، مانند ارسال پیامک.مثالی از یک سرویس ارایه محتوای ویدیويی:برای مثال به صورت خلاصه زیردامنه‌های یک سرویس UGC مبتنی‌بر ویدیو، مانند آپارات را در نظر بگیرید که می‌تواند شامل بخش‌های زیر باشد:زیردامنه کاتالوگ محتوازیردامنه مدیریت محتوا (آپلود، نظارت و انتشار)زیردامنه کاربرانزیردامنه ریکامندیشن (recommendation)زیردامنه جستجوزیردامنه نظرات کاربراننمونه دامنه های یک سرویس ویدیوئی ( ارتباطات واقعی متفاوت از تصویر فوق هستند ) در این مثال زیردامنه مدیریت محتوای ویدیویی بسته به نیاز به دو میکرسرویس کوچک‌تر برای آپلود ویدیو و مدیریت و ممیزی محتوا، تقسیم‌بندی شده است.مزایای این الگو:معماری سرویس‌ها پایدار هست، زیرا زیردامنه‌های نرم‌افزار معمولا این‌گونه هستند.تیم‌های پیاده‌سازی علاوه‌بر اینکه خودکار و مستقل هستند، براساس ارزش‌های کسب و کار و نه براساس امکانات فنی مورد نیاز، دسته‌بندی می‌شوند.سرویس‌ها چسبندگی لازم را دارند و کمتر به هم وابسته هستند.مشکلات این الگو:این الگو اتعداد میکروسرویس‌ها افزایش می‌دهد و در نتیجه عملیات service discovery (کشف خدمات) و پکپارچه‌سازی سیستم مشکل‌تر می‌شود.شناخت زیردامنه‌ها کار مشکلی است زیرا به شناخت عمیقی از کلیت کسب و کار نیاز دارد.راهکار سوم، جداسازی براساس تراکنش‌هادر یک سیستم توزیع‌یافته، نرم‌افزار معمولاً نیاز دارد چندین میکروسرویس را برای انجام یک تراکنش کسب و کاری فراخوانی کند. زمانی که شما سرویس‌ها را براساس تراکنش‌ها جدا می‌کنید، چندین تراکنش در سیستم وجود دارد. یکی از عوامل دخیل در تراکنش‌های توزیع‌شده وجود هماهنگ‌کننده transaction است. در این حالت یک تراکنش توزیع‌شده در دو مرحله انجام می‌شود.فاز آماده‌سازی: طی این مرحله همه شرکت‌کننده‌های تراکنش، آماده انجام تغییرات می‌شوند و به هماهنگ‌کننده اطلاع می‌دهند که آماده تکمیل تراکنش هستند.فاز انجام یا لغو تراکنش: طی این مرحله هماهنگ‌کننده دستور انجام یا لغو تراکنش را برای همه شرکت‌کننده‌های تراکنش ارسال می‌کند.یکی از بزرگ‌ترین مشکلات روال 2PC ، کُندی زیاد آن‌ها در مقایسه با زمان لازم برای انجام همان کار در قالب یک میکروسرویس است. این هماهنگی حتی زمانی که همه سرویس‌ها داخل یک شبکه داخلی باشند می‌تواند باعث کندی بسیار زیاد سیستم شود.برای جلوگیری از تأخیر در پاسخ‌دهی و مشکلات two-phase commit می‌توان سرویس‌ها را براساس تراکنش‌های بین آن‌ها دسته‌بندی کرد. این راهکار زمانی که مدت زمان پاسخ‌دهی برای شما اهمیت دارد و یا ترکیب چند ماژول (سرویس) با هم منجر به ساخت یک مونولیت جدید نمی‌شود، می‌تواند مورد استفاده قرار‌گیرد.مزایای این الگو:کاهش مدت زمان پاسخگویی به کاربرازبین بردن نگرانی بابت ثبات داده‌ها یا Data consistencyافزایش دسترسی‌پذیری نرم‌افزارمشکلات این الگو:چندین ماژول می‌توانند باهم دسته‌بندی شوند که این امر می‌تواند منجر به تولید یک مونولیت کوچک شود.هزینه و پیچیدگی به دلیل پیاده‌سازی چندین قابلیت در یک میکرسرویس به جای جداسازی آن‌ها به چندین میکروسرویس مستقل، افزایش می‌یابد .تعداد میکروسرویس‌های تراکنش‌محور با افزایش مدل‌های کسب و کار و وابستگی آن‌ها به هم افزایش می‌یابد.راهکار چهارم : جداسازی به روش Stranglerسه روشی که در بالا بررسی کردیم، بیشتر زمانی استفاده می‌شوند که شما یک نرم‌افزار Greenfield را از ابتدا می‌نویسید یا بازنویسی می‌کنید https://virgool.io/d/aphyynrugws3 (نرم‌افزار Greenfield به این‌صورت است که از پیش، نیازمند اجرای زیرساخت یا اعمال محدودیت نباشید).باید بگم صرف‌نظر از اینکه واقعاً جداکردن یک پروژه از ابتدا به‌صورت میکروسرویس درست است یا نه؟ در ۸۰ درصد مواقع شما با نرم‌افزارهای BrownField که نرم افزارهای مونولیتیک بزرگ و قدیمی‌اند (Legacy codebase) سر و کار دارید.در این زمان است که روش Strangler به کمک شما می‌آیند. در این روش:دو نرم‌افزار را که به‌صورت همزمان، هر دو روی یک مجموعه آدرس هستند را ایجاد خواهد کرد. یکی کدبیس (Code Base) قدیمی و دیگری پروژه‌ای جدید.با گذشت زمان نرم‌افزارهای (میکروسرویس‌های) جدید به تدریج جایگزین نرم‌افزار قبلی می‌شوند تا زمانی که بتوانید نرم افزار قدیمی را خاموش کنید.مراحل این کار شامل  سه مرحله تبدیل، همزمانی و از رده خارج کردن کدبیس قبلی است.مرحله تبدیل: یک مجموعه سرویس جدید با رویه‌های مدرن‌تر ایجاد می‌کنیم.مرحله همزمانی: نرم‌افزار موجود را برای مدتی به حال خود می‌گذاریم و همزمان با تکمیل‌شدن بخش‌های مختلف نرم‌افزار جدید، ترافیک بیشتری را به سرویس‌های جدید منتقل می‌کنیم.مرحله از رده خارج کردن: ویژگی جدیدی که پیاده‌سازی شده را از سرویس قدیمی حذف می‌کنیم.مزایای این الگو:ریسک را در زمان تبدیل پروژه کاهش میدهد.سرویس قدیمی در زمان تبدیل و ریفکتور کردن به سرویس جدید به کار خود ادامه می‌دهد.امکان اضافه کردن امکانات جدید را در زمان تبدیل کد فراهم می سازد.مشکلات این الگو:مدیریت مسیردهی و شبکه در زمان توسعه توجه زیادی را می طلبد.ممکن است در مسیر انتقال سرویس‌ها به پروژه جدید درگیر مشکلات هماهنگ‌سازی سرویس‌ها شوید و مجبور خواهید شد راهکار بازگشت به پروژه قدیمی را برای هر سرویس در نظر بگیرید.به هر حال مشکلات در هر مرحله از کار ممکن است به وجود بیاید و شما باید قادر باشید در صورت نیاز به سرعت و بدون دردسر هر سرویسی را از پروژه قدیمی دریافت کنید.</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Sat, 14 Aug 2021 18:09:04 +0430</pubDate>
            </item>
                    <item>
                <title>الگوهای معماری میکروسرویس  بخش اول: بانک اطلاعاتی</title>
                <link>https://aparat.design/microservice-patterns-part-1-xfktsz2zal3q</link>
                <description>استفاده از میکروسرویس‌ها بسته به شرایط می‌تواند تاثیرات مثبتی بر کسب‌و‌کار شما داشته‌باشد،‌ اما دانستن نحوه برخورد با این معماری و الگوهای مورد استفاده در آن از اهمیت بالایی برخوردار است. قبل از هر چیزی مروری از مقاله قبلی را در چند سطر بخوانید.اهداف و اصول معماری میکروسرویس‌ها:کاهش هزینه‌ها: هزینه‌های کلی طراحی، پیاده‌سازی و نگهداری سرویس‌های فناور محور کاهش‌ میابد.افزایش سرعت انتشار: سرعت انتشار امکانات جدید از ایده تا انتشار افزایش میابد.بالابردن سطح اطمینان: این معماری باعث بهینه‌کردن قابلیت اطمینان در شبکه سرویس‌های شما می‌شود.دسترس‌پذیری بهتر: دسترسی به سرویس‌های شما ساده‌تر می‌شود.اصول بنیادین معماری میکروسرویس‌ها:توسعه‌پذیری(Scalability‌)دسترسی‌پذیری(Availability)انعطاف‌پذیری(Resiliency‌)استقلالمدیریت غیر متمرکزایزوله سازی در مقابل خطاپراویژنینگ‌(Provisioning) خودکارانتشار پیوسته از طریق ساز‌و‌کار DevOpsالگوهای طراحی در حوزه میکروسرویس‌ها:معماری میکروسرویس علاوه بر مزایای گفته‌شده و راهکارهایی که برای شما فراهم می‌کند، چالش‌ها و مشکلاتی را نیز با خود به همراه دارد، اما باید بدانید که این چالش‌های فنی مانند بسیاری از مشکلات در این حوزه، با انتخاب الگوهای طراحی صحیح و متناسب با صورت مسئله، قابل رفع‌شدن هستند.این الگوها به 5 دسته اصلی تقسیم می‌شوند:الگوهای بانک اطلاعاتیالگوهای جداسازی(Decomposition)الگوهای یکپارچگی(Integration)الگوهای مشاهده‌پذیری‌(Observability)الگوهای مشکلات چند‌جانبه(Cross Cutting Concerns ) آخه من اینو چی بگم به فارسی؟! :دیDesign Patterns for Microservice با توجه به مقدمه‌ای‌ که برایتان شرح دادم، قصد دارم در یک مجموعه مقالات سریالی، هر بار به سراغ یکی از این 5 دسته الگوهای طراحی بروم و مزایا و معایب هر کدام را بررسی کنم، این مقاله نیز به عنوان اولین قسمت از این سری مقالات به حساب می‌آید که تصمیم گرفتم در ابتدا از حوزه بانک اطلاعاتی شروع کنم زیرا که در مورد این حوزه بحث‌ها و گفتگو‌های زیادی وجود دارد.الگوهای بانک اطلاعاتیالگوهای مورد استفاده در بانک‌های اطلاعاتی در میکروسرویس‌ها یکی از موضوعات پر بحث و جدل درباره نحوه جداسازی میکروسرویس‌ها است. باید گفت، الگوهای زیر جز موارد پر‌استفاده هستند:بانک اطلاعاتی جدا به ازای هر سرویسبانک اطلاعاتی مشترکالگوی Sagaالگوی API Compositionالگوی Event Sourcingالگوی CQRSزمانی که درباره معماری بانک اطلاعاتی در میکروسرویس‌ها صحبت می‌شود، باید موارد زیر را گوشه ذهن خود داشته‌باشیم:سرویس‌ها باید تا جای ممکن به همدیگر وابستگی نداشته‌باشند تا بتوانند به صورت جداگانه توسعه پیدا کنند، بارگذاری شوند و تغییر اندازه دهند.برخی از تراکنش‌های مرتبط به کسب‌و‌کار ممکن است نیاز به دریافت اطلاعات از سرویس‌های متعدد داشته‌باشند.بانک‌های اطلاعاتی در برخی از موارد باید در چند نقطه تکراری، نگهداری و یا به اشتراک گذاشته‌شوند.سرویس‌های مختلف، نیازهای مختلفی در حوزه بانک‌های اطلاعاتی دارند.بانک اطلاعاتی جدا به ازای هر سرویسدر این الگو، میکروسرویس اطلاعات مربوط به خود را مدیریت می‌کند. با استفاده از این الگو اطمینان حاصل خواهید‌کرد که، میکروسرویس‌های دیگر اجازه دسترسی مستقیم به بانک اطلاعات سرویس دیگری را ندارند. ارتباط و یا انتقال اطلاعات از طریق API‌های تعیین‌شده از سمت هر سرویس قابل دسترسی‌ است. پیاده سازی این الگو از چیزی که به نظر میاد پیچیده‌تر است، زیرا نرم‌افزارها معمولا خیلی خوب مرز‌بندی نشده‌اند و برای پیاده‌سازی لاجیک خود، به اطلاعات میکروسرویس‌های دیگر نیازمند هستند، در نتیجه منجر به ارتباطات پیچیده بین میکروسرویس‌های مختلف می‌شود.Database per service اگر موفق شوید این الگو را به خوبی پیاده‌سازی کنید،‌ می‌توانید از بزرگترین مزیت آن که همان وابستگی بسیار کم بین میکروسرویس‌ها است، استفاده کنید و نرم افزار خود را از گیر‌افتادن در impact analysis خلاص کنید. موفق بودن این الگو به شدت به تعریف موثر حوزه بانک داده در نرم‌افزار شما وابسته‌است. این کار برای یک نرم‌افزار یا یک سیستم جدید و در حال طراحی، کار ساده‌تری است ولی برای یک معماری مونولیتیک، جدا‌سازی پیچیدگی موجود می‌تواند مشکل ساز باشد!همچنین چالش‌های دیگری نیز در این معماری وجود دارد، که می‌توان به آن اشاره کرد:پیاده‌سازی Business Transaction هایی که چندین میکروسرویس را درگیر می‌کنند و یا پیاده‌سازی query هایی که اطلاعات را از دو یا سه میکروسرویس مختلف دریافت می‌کنند.نکته مفید دیگری در این حالت وجود دارد:نکته مفید امکان اسکیل‌کردن ساده نرم‌افزار و استفاده از بانک‌های مختص به هریک از میکروسرویس‌ها است به طور مثال؛ در میکرسرویس جستجو می‌توانید از ElasticSearch و در میکروسرویس مدیریت کاربران، از قدرت یک دیتابیس RDBM استفاده کنید.بانک اطلاعاتی مشترکاستفاده از یک بانک اطلاعاتی اشتراکی، در زمانی که برای تیم شما چالش‌های پیاده‌سازی بانک اطلاعاتی به ازای هر سرویس، زیادی پیچیده و مشکل ساز شود، گزینه مناسبی است. رویکرد این الگو مانند الگوی قبلی سعی در رفع مشکلات بالا دارد، با این تفاوت که از راه حل ساده‌گیرانه‌تری مانند استفاده از بانک اطلاعاتی مشترک استفاده می‌کند.در اکثر مواقع استفاده از این الگو برای توسعه‌دهنده‌ها کم‌خطرتر است، چون روش مورد استفاده کاملا مشابه روش‌های مرسوم آن‌ها مانند ACID Transaction برای حفظ یکپارچگی اطلاعات است.در این روش اگرچه از بیشتر منافع ذکر‌شده برای میکروسرویس‌ها بهره‌مند می‌شوید، اما توسعه‌دهنده‌ها که در تیم‌های مختلف فعالیت می‌کنند باید تغییرات مورد نظر خود در بانک را با یکدیگر هماهنگ کنند. همچنین به دلیل استفاده چندین سرویس به صورت هم‌زمان از یک بانک اطلاعاتی، امکان وقوع خطاهای ناسازگاری‌های runtime نیز وجود دارد.به طور کلی روش بانک اطلاعاتی مشرک در بلند مدت بیشتر از اینکه مفید باشد برای شما دردسر ایجاد می‌کند.الگوی Sagaالگوی Saga راهکاری برای پیاده‌سازی Business Transaction بین چندین میکروسرویس است. یک Saga به طور ساده زنجیره‌ای از تراکنش‌های محلی است. به ازای هر کدام از این تراکنش‌ها که در یک Saga اتفاق می‌افتد، سرویسی که آن تراکنش را انجام ‌می‌دهد یک event منتشر‌ می‌کند. تراکنش بعدی بر اساس خروجی تراکنش قبلی اتفاق‌می‌افتد و اگر یکی از تراکنش‌های موجود در این زنجیره به خطا بخورد، Saga یکسری از تراکنش‌های اصلاح‌کننده را می‌دهد تا تغییراتی که به واسطه تراکنش‌های قبلی ایجاد‌شده را برگرداند.در الگوی Saga از دو روش برای مدیریت مراحل استفاده می‌شود:روش Choreography : هر کدام از تراکنش‌ها محلی، یک Domain Event را ایجاد می‌کند که باعث ایجاد تراکنش‌های محلی در دیگر سرویس‌ها می‌شود.روش Orchestration : یک ارکستراتور به شرکت‌کنندگان(میکروسرویس‌ها) می‌گوید که چه تراکنشی را باید انجام دهند. روش ChoreographyChoreography-Based Saga در مثال فوق مراحل زیر طی می‌شوند:۱. سرویس &#x60;Order Service‍&#x60; درخواستی را از POST /orders دریافت و یک order را در حالت Pending ایجاد‌می‌کند.۲. سپس یک event از نوع Order Created ایجاد می‌شود.۳. در سوی دیگر سرویس Customer Service به event از نوع Order Created گوش می‌دهد و هنگامی که این درخواست را دریافت می‌کند سعی خواهد کرد به اندازه هزینه سفارش از اعتبار مشتری به صورت رزرو‌شده نگهداری‌کند.۴. در مرحله بعد نتیجه تلاش خود را به صورت یک event ارسال می‌کند.۵. مدیریت‌کننده event سرویس Order Service در این مرحله event بالا را دریافت و بر اساس اینکه آیا مشتری اعتبار دارد یا خیر؟ سفارش را تایید و یا رد می‌کند.روش OrchestrationOrchestration-Based Saga در مثال فوق مراحل زیر طی می‌شود:۱. سرویس &#x60;Order Service‍&#x60; درخواستی را از POST /orders دریافت می‌کند و یک Saga Orchestrator از نوع Create Order می‌سازد.۲. این ارکستریتور یک سفارش در حالت pending ایجاد ‌می‌کند.۳. سپس یک دستور Reserve Credit را از طریق Message broker برای Customer Service ارسال‌ می‌کند.۴. در این مرحله Customer Service پاسخ این درخواست را برای ارکستریتور ارسال‌ می‌کند.۵. ارکستریتور براساس اینکه پاسخ سرویس مشتریان چه بوده‌است، سفارش را تایید و یا رد می‌کند.همانطور که می‌بینید، این روش به شدت با روش سنتی ایجاد Transaction در بانک اطلاعاتی متفاوت است. این روش پیچیدگی‌های زیادی را به سیستم اضافه می‌کند، اگر چه این الگو برای حل مشکلات خاص خیلی قدرتمند است ولی به دلیل پیچیدگی‌های بسیاری که دارند فقط در موارد خاص استفاده‌ می‌شوند.الگوی API Compositionاین الگو، راهکاری برای مدیریت Queryهای پیچیده در معماری میکروسرویس‌ها است. در این الگو، یک API Composer، سرویس‌های دیگر را صدا می‌زند و اطلاعات مورد نیاز را براساس ترتیب مورد نیاز دریافت‌می‌کند و پس از دریافت این اطلاعات، آن‌ها را با یکدیگر به صورت in-memory ترکیب و نتیجه را به مصرف کننده API ارایه‌می‌کند.پر واضح است که مشکل این روش هزینه ترکیب اطلاعات به صورت in-memory برای Dataset‌های بزرگ است.الگوی CQRSالگوی CQRS یا Command Query Responsibility Segregation(جدا‌سازی مسئولیت کوئری) تلاش می‌کند مشکل الگوی API Composition را که بالاتر توضیح دادم، رفع کند. در این الگو، یک برنامه به Domain Event‌های ایجاد‌شده توسط همه میکروسرویس‌ها گوش می‌دهد و بر اساس آن یک View را بروز‌رسانی و یا اطلاعات جدید را از میکرسرویس‌های مورد نظر دریافت‌‌می‌کند. با استفاده از این روش شما می‌توانید ترکیب‌های سنگین از query‌ها را انجام‌دهید و حتی در صورت نیاز خود این سرویس query را scale-up کنید تا همیشه این اطلاعات را برای شما آماده ‌داشته‌باشد.CQRSمزایای الگوی CQRS:امکان ایجاد چندین denormalized view را ایجاد میکند که به راحتی قابل scale کردن هستندباعث بهبود قاعده SoC یا Separation of concerns میشود.مشکلات الگوی CQRS:پیچیدگی اجرا را بیشتر می‌کند.دیتابیس مورد استفاده برای View یا بخش Query به جای آنکه همیشه بروز و consistent باشد، بعضی وقت‌ها consistent است.باعث ایجاد کدهای تکراری در سیستم می‌شود.الگوی Event Sourcingروش Event Sourcing سعی می‌کند مشکل بروزرسانی بانک اطلاعاتی به صورت Atomic و انتشار Event مرتبط با آن را حل کند. در این روش شما وضعیت نهایی یک رکورد را ذخیره و یا با جمع کردن مجموعه تغییراتی که از ابتدا روی این رکورد اتفاق افتاده‌است، شرایط نهایی رکورد را محاسبه می‌کنید. هر زمانی که یک رکورد جدید ایجاد شود و یا یک رکورد موجود به روز شود یک Event ساخته‌می‌شود. در این معماری از یک Event store برای ذخیره‌سازی این event‌ها استفاده می‌شود.Event-Sourcingمزایای الگوی Event Sourcing:یکی از مشکلات اساسی معماری event-driven را برطرف می‌کند و به شما این امکان را می‌دهد که هر وقت تغییری اتفاق می‌افتد یک event منتشر کنید.از آنجا که اتفاقات را به جای آخرین وضعیت ذخیره می‌کند، مشکلات object‑relational impedance mismatch را کمتر می‌کند.این روش audit log صد در صد مطمئنی را برای هرکدام از entity‌ها فراهم می‌کند.امکان ایجاد queryهای موقتی بر اساس وضعیت یک entity در هر بازه زمانی دلخواه ایجاد می‌کند. برای مثال وضعیت اعتبار این کاربر ۱ سال پیش چطور بوده‌است؟مشکلات الگوی Event Sourcing:این روش مدلی متفاوت از روش معمول برنامه‌نویسی در بانک‌های اطلاعاتی را دارد و مدت زمان خاص خود را برای آشنایی با آن می‌طلبد.گرفتن Query از Event-Store برای تعیین وضعیت یک رکورد به صورت مکرر، کار پیچیده و غیر کارآمدی است، در‌نتیجه نرم‌افزار باید حتما از روش CQRS در کنار معماری خود استفاده کند که این به معنی کنار آمدن با داده‌هایی است که بعضی وقت‌ها consistent هستند.</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Tue, 06 Oct 2020 15:20:14 +0330</pubDate>
            </item>
                    <item>
                <title>میکروسرویس یا مونولیت(خوب، بد، چُخ)</title>
                <link>https://aparat.design/microsevice-or-monolithic-aphyynrugws3</link>
                <description>تا حالا شده که ویدیوی یک کنفرانس معتبر را ببیند که موضوع آن درباره این باشد که چقدر میکروسرویس‌ها خوب هستند و چطور شرکت‌های بزرگ مشکلات را به وسیله میکروسرویس‌هایی که به صورت کانتینری اجرا شده، حل کردند، بعد با خودتان فکر کنید چرا ما این کار را نکنیم؟واقعیت این است که در مهندسی نرم‌افزار هیچ راه حل طلایی‌ای وجود ندارد! میکروسرویس‌ها به صورت جادویی تمام مشکلات scaling را حل نمی‌کنند و حتی بعضی وقت‌ها مشکلات جدیدی را هم به وجود می‌آورند و من با اینکه به میکروسرویس‌ها به دلیل پیچیدگی کمتر و راه‌گشا بودنشان بسیار علاقه‌مندم و دلم نمی‌خواهد این معماری بکوبم اما معتقدم علاوه بر کارآمد بودن باید هزینه‌های اجرای میکروسرویس را در شرایط واقعی بدانیم و سعی کردم در این مقاله به آن بپردازم.معماری میکروسرویسدر معماری میکروسرویس، به صورت کلی شما Domain Model پروژه را به سرویس‌های کوچکتری که کمتر به هم وابسته هستند و می‌توانند مستقل از هم دیپلوی و اسکیل بشوند تقسیم می‌کنید. هرکدام از این سرویس‌ها به تنهایی یک نرم‌افزار با معماری مخصوص به خودشان هستند.سرویس‌ها در مواردی اندپوینت‌های REST را فراهم می‌کنند که می‌تواند توسط یک API Gateway به کار گرفته‌شوند یا سرویس‌ها ممکن است از طریق یک سیستم پیام‌رسان با یکدیگر صحبت کنند. بعضی از این سرویس‌ها دارای رابط کاربری وب هستند و برخی از آن‌ها فقط و فقط یک API ارائه می‌دهند.در معماری میکروسرویس محور، هر سرویس مسئول مدیریت اطلاعات خود است و ایده‌آل‌ گرایانه نباید ساختار بانک اطلاعاتی خود را با دیگر سرویس‌ها به اشتراک قرار دهد. این معماری فراهم کردن کلاینت‌های موبایل و دسکتاپ را که می‌توانند مستقل و بسته به نیاز Scale بشوند را ساده می‌کند.برای ساخت میکروسرویس‌ها الگوهای مختلفی وجود دارد، هر الگوی انتخاب شده، مسئول انتخاب روش ارتباط که سرویس‌ها با یکدیگر و  تجمیع اطلاعات می‌شود.کریس ریچاردسون این لگو‌ها را در مقاله زیر به خوبی توضیح داده‌است که پیشنهاد می‌کنم آن را مطالعه کنید. https://microservices.io/patterns/microservices.html خوب چیزی که در ادامه می‌خواهم به آن بپردازم این است که منافع و مشکلات معماری میکروسرویس‌ها را ببینید تا بدانید که چه زمانی باید به سراغ آن‌ها برویم و چه زمانی باید از آن‌ها فرار کنیم!منافع رایج در معماری میکروسرویسبه صورت کلی، میکروسرویس‌ها بسته به اینکه چطور پیاده سازی شوند منافع زیر را در سه دسته ایجاد می‌کنند و یا حداقل این طور ادعا دارند که می‌توانند ایجاد کنند:وابستگی کماسکیل پذیری عالیدوره های توسعه و انتشار سریعتروابستگی کمکامپوننت‌ها در معماری میکروسرویس‌ها از معماری‌های سنتی، کمتر به هم وابستگی دارند. این سیستم‌ها از معماری‌های پیام محور‌(Message-Driven) و یا اتفاق محور‌(Event-Driven) برای ایجاد ارتباط بین این کامپوننت‌های استفاده می‌کنند که منجر به ایزوله شدن کامپوننت‌های سیستم، تست کردن راحت‌تر و اجرای سریع‌تر آن‌ها می‌شوند. این سیستم‌ها همچنین منافع دیگری را ایجاد می‌کنند، به طور مثال، وجود یک باگ  Memory Leak در یک میکروسرویس ایزوله شده، منجر به خرابی کل اپلیکیشن و یا افتادن کل سرویس نمی شود.در یک کلام معماری میکروسرویس باعث کاهش تعداد Single point of failure در سیستم خواهد شد.باید بگویم که کامپوننت‌ها با وابستگی کم، به نسبت یک سیستم مونولیتیک خیلی سریعتر اجرا می‌شوند و در نتیجه با اجرای موازی اجزاي سیستم، می‌توان سرعت استارت را برای سیستم‌های بزرگ‌تر بالا برد. همچنین به دلیل این وابستگی کم، هر کدام از سرویس‌ها می‌توانند انتخاب کنند که از هر دیتابیس و یا دیتا استوری که برای حوزه کار خود مناسب‌تر هستند، استفاده کنند که همانطور که می‌دانید در خیلی مواقع در یک سیستم مونولیتیک توافق می‌شود که فقط از یک نوع دیتابیس استفاده شود. برای مثال در یک سرویس با مقدار زیادی از داده‌های بدون ساختار می‌توانید از یک بانک اطلاعات NoSQL استفاده کنید در حالی که یک سرویس دیگر که با داده‌های ساختارمند و Transaction سر و کار دارد می‌تواند سراغ بانک‌های اطلاعاتی RDBMS برود.دوره های توسعه و انتشار سریعتردر یک معماری میکروسرویس که خوب پیاده سازی شده‌باشد:دوره‌های توسعه نرم‌افزار سریع‌تر  و زمان آماده سازی یک ویژگی جدید و یا تغییر ویژگی‌های موجود خیلی کوتاه‌تر می‌شود. یک سیستم با دومین پیچیده به راحتی می‌تواند با تقسیم به سرویس‌های قابل مدیریت و قابل فهم در طولانی مدت بهتر قابل مدیریت باشد.بکارگیری تکنولوژی‌های جدیدتر ساده‌تر است، اجزای سیستم می‌تواند جداگانه به صورت مرحله به مرحله بروزرسانی شوند و در نتیجه می‌توان در هرکدام از این کامپوننت‌ها از stack مختص به خود استفاده کنند.همچنین این امکان وجود خواهد داشت که هریک از این میکروسرویس‌ها از زبان‌های مختص به خود استفاده کنند و با استفاده از ساختارهای معمول ارتباط مثل gRPC و یا Message Queue و یا Pub/Sub با یکدیگر ارتباط بگیرند،‌که در نهایت شما را قادر خواهد ساخت تا از تیم های مختلف با زبان‌های مختلف استفاده کنید و وابستگی مجموعه را به یک زبان خاص کمتر می‌کند.تیم‌های اجرایی کمتر به همدیگر وابسته خواهند بود، زیرا ارتباط بین اجزای سیستم توسط API و یا یک ساختار قراردادی دیگر اتفاق می‌افتد و هر تیم قادر است با حفظ ساختار قراردادی روال‌های داخلی کد خود را تغییر دهد بدون اینکه نگران باشد، این کار منجر به خراب شدن کد تیم دیگر بشود.روال مناسبی برای تیم‌های چابک فراهم می‌سازد، در این ساختار تیم‌ها می‌توانند تمرکز را روی سرویس‌های خود قرار دهند و فقط نگران یک سرویس باشند.اسکیل پذیری عالی یکی از مهمترین منافع از معماری میکروسرویس امکان تغییر اسکیل هریک از اجزا، بسته به بار و فشار روی هریک از آن‌ها است. اگر این بخش به خوبی پیاده‌سازی شود منجر به تقسیم بار ایده‌آل بین اجزای سیستم و کاهش هزینه زیرساخت‌های مورد نیاز می‌شود. سرویس‌ها با تقاضای بیشتر می‌توانند Scale up شوند و سرویس‌های که تقاضای آن‌ها کمتر شده‌، می‌توانند Scale Down شوند بدین‌ترتیب می‌توان منابع را بهتر مدیریت کنیم.دیپلوی کردن سرویس‌ها به صورت مستقل باعث می‌شود کل نرم‌افزار قابلیت اطمینان بالاتری داشته‌باشد و ایجاد اصلاحات جزئی ساده‌تر شود و نیازی به بروزرسانی کل نرمافزار برای رفع مشکل در یک سرویس نخواهیم بود.مدل های پیچیده تری از Scaling قابل اجرا خواهد بود، سرویس‌های حیاتی بطور موثرتری اسکیل خواهند شد.بارگذاری پیوسته در سیستم‌های پیچیده در این معماری به نسبت معماری Monolithic خیلی آسان‌تر است به دلیل کوچکتر بودن اجزا، پیدا کردن و رفع مشکلات در هریک از این کامپوننت‌ها بسیار آسان‌تر می‌شود.مشکلات رایج در معماری میکروسرویسخوب در هر معماری یک سری از مشکلات وجود دارد و میکروسرویس‌ها هم از این قاعده مستثنی نیستند.پیچیدگیپیچیدگی یکی از بزرگترین اثرات جانبی این معماری است. درحالی که میکروسرویس‌ها می‌توانند پیچیدگی‌های دومین را با شکستن به سرویس‌های کوچکتر کاهش دهند، ولی از سمت دیگر منجر به ایجاد پیچیدگی‌های خاص خود از لحاظ سیستم‌های توزیع یافته می‌شوند، که موارد زیر را به همراه دارد:استک‌های استفاده شده مختلف در هریک از اجزای سیستم، تیم اجرایی رو مجبور می‌کند تا زمان بیشتری رو صرف یادگیری این زبان‌ها کنند.اسکیل کردن خیلی موثر‌تر است، اما به امکانات پیشرفته‌تری مانند Service Discovery،DNS Routing و دیگر امکاناتی از این دست نیاز خواهد بود.ارتباط بین اجزای سیستم ممکن است به سیستم‌های پیام‌رسان نیاز داشته‌باشد (Queue, Pub/Sub, Event Store )تراکنش‌ها در این سیستم توزیع یافته پیچیده‌تر است، هرگونه Rollback در این سیستم‌ها به دلیل نیاز به انجام Rollback در بانک‌های اطلاعاتی مختلف در سرویس‌های مختلف می‌توانند پیچیدگی و احتمال ایجاد خطا در آن‌ها بالاتر ببرند.بارگذاری کل نرم‌افزار روال پیچیده‌تری است، پیچیدگی‌هایی مثل کار با Container ها و Orchestration و مجازی‌سازی اضافه می‌شود.به زیر ساخت‌های پیچیده‌تری نیاز داریم‌،‌ در اغلب موارد به کانتینرها (Docker) و سیستم‌های Orchestration مانند Kubernetes نیاز پیدا می‌کنیم.تست‌های Integrationانجام تست‌های End-to-End و Integration Tests به دلیل وجود بخش‌های مختلف، و ارتباطات پیچیده‌تر بین آن‌‌ها پیاده‌سازی زیرساخت‌های تست و بروز نگهداری آن‌ها خیلی مشکل‌تر خواهد بود.اندازه تیم و تجربه آن‌هااستک فنی مورد استفاده در میکروسرویس‌ها پیچیده‌تر هستند و یادگیری ‌آنها مشکل‌تر است و در نتیجه تیم با تجربه‌تری و به تعداد بیشتری از افراد با مجموعه توانایی‌های Senior-level در مقایسه با یک سیستم Monolithic نیاز است. در این حالت شما تیم بزرگتری برای نگهداری نرم‌افزار خود نیاز دارید. زیرا تکنولوژی‌ها و کامپوننت‌های بیشتری وجود دارند.پیاده سازی Feature هایی که منجر به تغییر در سیستم‌های مختلف هستند زمان بیشتری نیاز دارند زیرا زمان بیشتری صرف توافق در مورد قراردادها و API ها خواهد شد.با وجود اینکه اعضای تیم بسته به کامپوننتی که روی آن کار می‌کنند، Skill set گسترده‌ای دارند ولی لزوما دید کلی و جامعی بر کلیت Application ندارند و ممکن است برطرف کردن نیازهای کسب و کار و یا پیدا کردن و رفع مشکل‌هایی را که از ارتباط بین اجزا بوجود آمده‌اند، سخت تر کند.سربارمیکرو سرویس‌های پیچیده، به دلیل پیاده‌سازی روال‌های مانیتورینگ، سیستم‌های پیام رسان، Orchestration و سرویس رجیستری و مواردی از این دست کار سربار بیشتری داشته باشند.توسعه اولیه سیستم ممکن است به دلیل این پیچیدگی‌ها طولانی‌تر باشد و زمان رسیدن به بازار محصول را به عقب بندازد.هزینه اولیه زیر ساخت ممکن است نسبت به معماری Monolithic خیلی بیشتر شود.در ساختارهای میکروسرویس، همیشه مقداری از تکرار کد بین چند سرویس وجود دارد که می‌تواند به عنوان یک سربار در نظر گرفته‌شود.کی نباید از معماری میکروسرویس استفاده کرد‌؟به یاد داشته باشید تا زمانی که مجبور نشدید، از این معماری نباید استفاده کنید. هر نرم‌افزاری نیازمندی‌های Scaling در حد Google،‌Netflix، Amazon و یا Spotify را ندارد. خیلی از منافع میکروسرویس‌ها برای این مجموعه‌ها به دلیل شرایط خاص Scaling آنهاست که شاید برای شرایط شما اصلا محلی از اعراب نداشته باشد.برخی از دلایلی که شاید برای شما بهتر است به ساختارهای Monolithic بچسبید:اگر اسکوپ نرم‌افزار شما کوچک است و قرار نیست در زمان کوتاه به اندازه‌های مثل شرایط فعلی آپارات برسید. برای نرم‌افزارهای با کاربرد مشخص که به خوبی تعریف شده‌باشند، استفاده از monolith همیشه بهترین گزینه هستد مثل:نرم افزار CRUD محوری برای استفاده داخلی شرکتنرم افزارهای کوچک با حوزه استفاده خیلی مشخص، مثل یک سایت فروش آنلاین برای حوزه خاصی از محصولاتوقتی زمان رسیدن محصول به بازار برای نرم‌افزار جدید خیلی حیاتی باشد، باید بدانید که زمان Time to Market برای معماری میکروسرویس‌ها طولانی‌تر خواهند بود.وقتی اندازه تیم شما کوچک یا متوسط است و  تجربه تیم کمتر از استاندارد باشد، بهترین گزینه استفاده از monolith خواهد بود.وقتی بودجه زیر ساخت شما محدود باشد. اگر چه در طول زمان شما با استفاده از میکروسرویس‌ها در هزینه صرفه‌جویی می‌کنید ولی باید بدانید که هزینه‌های شروع، خیلی بیشتر هستند.از همه مهتر، هیج وقت میکروسرویس را به دلیل روی بورس بودن و استفاده آن در شرکت های بزرگ و یا پیشنهاد از یک آدم معروف انتخاب نکنید(در یک کلام جو نگیرتتون ). برای خیلی از کاربردها هنوز هم مونولیت‌ها راهکار خیلی خوبی هستند. شما می‌توانید با مونولیت شروع کنید و در ادامه در صورت نیاز آن را با میکروسرویس بشکنید. به یاد داشته باشید اکثر نام‌های بزرگ صنعت بعد از تجربه ۲ تا ۳ باز refactor کردن کد بیس‌های مونولیت، سراغ استفاده از میکروسرویس رفته‌اند.کی باید سراغ معماری میکروسرویس برویم‌؟‌به طور کلی، میکروسرویس‌ها می‌توانند وقتی مفید باشند که شما یکی از سناریوهای زیر را داشته باشید.وقتی دومین‌ کار شما خیلی پیچیده باشد و تیم بزرگ و با تجربه‌ای دارید در این صورت تکه تکه کردن دومین به میکروسرویس‌ها، کار را برای شما آسان‌تر می‌کند.وقتی شما انتظار دارید فیسبوک، نتفلیکس و یا توییتر بعدی، از لحاظ فشار کاربران باشید، به عبارت دیگر وقتی رشد نمایی کاربران را انتظار دارید.اگر نرم افزار شما به عنوان SaaS قرار است تامین کننده API برای نرم افزارهای دیگری با تعداد کاربر بالا باشد. مانند درگاه‌های پرداخت، درگاه‌های ارسال پیام کوتاه و...وقتی شما یک نرم‌افزار تجارت الکترونیک با تعداد کاربران خیلی بالا و با بار نا‌متعادل روی بخش‌های مختلف سیستم خود هستید، باید سراغ میکروسرویس‌ها بروید.( دفعه بعدی که یکی از فامیل ازتون پرسید یه سایت مثل آپارات و دیجیکالا میخوام و انقدر پول داشت و گیر بود که حتما خواست اینکار رو بکنه سراغ میکروسرویس نرو برادر من!)نتیجه گیریبه طور کلی، هیچ وقت یک الگوی معماری را صرف اینکه در جایی کار کرده، انتخاب نکنید. الگویی را انتخاب کنید که برای use case و نیازهای scaling شما مناسب باشد. همه قرار نیست مثل آپارات میلیون‌ها درخواست هم‌زمان کاربران را مدیریت کنند و یا چندین ترابایت از اطلاعات را استریم کنند.</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Mon, 14 Sep 2020 10:46:46 +0430</pubDate>
            </item>
                    <item>
                <title>مدیریت سیگنال ها برای Graceful Shutdown در Go</title>
                <link>https://aparat.design/graceful-shutdown-in-golang-ekve8k6m5rwe</link>
                <description>در این مقاله یاد خواهیم گرفت چگونه سیگنال‌های ورودی سیستم عامل را برای انجام graceful shutdown در یک وب سرور نوشته‌می‌شوند و ما آن‌ها را به زبان Go مدیریت کنیم. قبل از هرچی باید بگویم که در این بخش، توجه ما بیشتر روی سیگنال‌های async(غیرهم‌زمان) متمرکز است و باید بدانید که این سیگنال‌ها توسط خطاهای برنامه ایجاد نمی‌شوند بلکه از طریق هسته سیستم عامل و یا برنامه‌های دیگر به برنامه ما ارسال می‌شوند. انواع سیگنال سیگنال SIGHUP هنگامی ارسال میشود که برنامه ترمینال کنترل کننده خود را از دست میدهدسیگنال SIGINT هنگامی ارسال میشود که کاربر در ترمینال کنترل کننده برنام کاراکتر interrupt را ارسال کند (به صورت پیش فرض این کاراکتر C^ یا Control-C است‌) سیگنال SIGQUIT هنگامی ارسال میشود که کاربر در ترمینال کنترل کننده برنامه  کاراکتر quit را ارسال کند (به صورت پیش فرض این کاراتر \^ یا Control-Backslash است) توجه: به صورت کلی هنگامی که ما قصد بستن برنامه‌ای را در ترمینال داریم، برای خروج به صورت ساده کلید‌های C^ و برای خروج با stack dump  کلید .^ را می‌زنیم.رفتار سیگنال ها در زبان Goیک سیگنال synchronous  در زبان Go به صورت پیش‌فرض منجر به ایجاد runtime panic می‌شود و ارسال هر کدام از سیگنال‌های SIGHUP، SIGINT, SIGTERM منجر به خروج برنامه خواهد شد.مدیریت سیگنال ها ایده ما در این بخش دریافت‌کردن این سیگنال‌ها و متوقف کردن آن‌هاست که به اصطلاح به آن متوقف کردن مودبانه وب سرور(graceful shutdown)می‌گویند.متوقف کردن مودبانه یا graceful shutdown به معنی خاموش کردن یک سرور بدون ایجاد اختلال در هرکدام از ارتباطات فعال در روال خاموش شدن سرور است. مراحل کار به ترتیب زیر است: ۱.  بستن تمامی listener های باز۲. بستن تمامی connection های بیکار۳. منتظر ماندن به صورت نامحدود برای برگشت وضعیت connection های باز به حالت بیکار ۴. در نهایت خاموش کردن سروراگر با مفهوم concurrency در زبان Go آشنا باشید می‌دانید مفهومی به نام Channel وجود دارد و یکی از بزرگترین منافع و مهمترین کاربردهای آن ماهیت بلاک‌کننده آن است، یعنی اگر شما در جایی منتظر دریافت اطلاعاتی از یک کانال باشید و برای آن کانال از جایی اطلاعاتی ارسال نشود کد شما در آن قسمت متوقف خواهد شد تا اطلاعات بدست آن کانال برسد.برای مثال بیایید کد زیر را باهم بررسی کنیم : https://gist.github.com/subzerobo/4811e39c09f7923f31c7f3d2e606e74f در خط اول، از تابع main یک کانال به نام done ایجاد می‌کنیم، این کانال تنها مقدار os.Signal را با ظرفیت ۱ پیام دریافت می‌کند.در خط دوم، signal.Notify باعث می‌شود که پکیج signal تمامی سیگنال‌ها از نوع SIGINT و SIGTERM را به سمت کانال done هدایت کند و در بخش ‍done-&gt; سعی میکند تا ورودی از کانال done را دریافت کند.در خط پانزدهم، اگر ما برنامه را اجرا کنیم با توجه به توضیحات بالا،  پیام &quot;Server Stopped&quot; نمایش داده‌نمی‌شود، اما اگر سعی کنید برنامه را با فشردن کلید Ctrl-C متوقف کنید خط ۱۵ اجرا شده و پیام Server Stopped نمایش داده خواهد‌شد.یه وب سرور نه چندان ساده !وقتی به اکثر مثال‌ها و مقالات موجود در خصوص graceful shutdown نگاه می‌کنیم اکثرا با یک مثال ساده وب‌سرور رو بیان می‌کنند که عملا وب سرور را در فایل اصلی پروژه اجرا می‌کنند، ولی باید بگویم که در شرایط واقعی و برنامه‌های واقعی، کمتر پیش می‌آید که به این شکل نوشته شوند. به همین منظور در ادامه یک مثال پیچیده‌تر را که به شرایط واقعی بیشتر شبیه باشد، انتخاب کردم؛ به تکه کد زیر دقت کنید:در کد زیر ما برای وب سرور خود یک structure به نام App ایجاد کردیم و این استراکچر درون خود یک وب سرور ساده دارد، از طرف دیگر این برنامه هر ۱۰ ثانیه یک بار باید یک سری از کارهای مشخص را در تابع DoBackgroundJob انجام‌دهد. https://gist.github.com/subzerobo/f7ef90f280e61c58f08fd8503cdadc1d در خط‌های ۲۸ تا ۳۰، یک کانال به نام done از نوع bool و یک کانال دیگر از نوع signal ایجاد کردیم و در ادامه در صورت دریافت سیگنال‌های SIGINT و SIGTERM مقدار را از طریق پیکج signal برای quitSignal ارسال می‌کنیم.در خط ۳۲، بعد از ایجاد مقدار myApp  تابع myApp.GracefulShutdown با ورودی‌های quitSignal و done به صورت goroutine اجرا می‌شود و در نهایت myApp.Start وب سرور را استارت می‌کند.بیایید کد را باهم اجرا کنیم:go run main.go
http: 2020/07/13 15:21:51 Operation: app.Start, HTTP Server Starting on Address ::8080 [GIN] 2020/07/13 - 15:21:56 | 200 |      70.872µs |             ::1 | GET      &amp;quot/&amp;quot
[GIN] 2020/07/13 - 15:21:56 | 200 |      100.92µs |             ::1 | GET      &amp;quot/&amp;quot
^C
http: 2020/07/13 15:22:03 Operation: app.GracefulShutdown, Graceful Shutdown Process Started 
http: 2020/07/13 15:22:03 Operation: app.Start, HTTPServer exited blocking mode 
http: 2020/07/13 15:22:03 Server stoppedبعد از اجرا کردن برنامه در محیط مرورگر خود دو بار به صفحه http://localhost:8080 مراجعه کردیم و میبینم که لاگ مربوطه در خط‌های سوم و چهارمِ خروجی ترمینال به چشم می‌خورد.هنگامی که در ترمینال Control-C را فشار دهیم مراحل زیر به ترتیب اتفاق خواهد افتاد :سیگنال SIGINT برای کد ارسال می‌شود و در تابع GracefulShutdown که منتظر دریافت اطلاعات از quitSignal است، کار خود را ادامه می‌دهد و با ایجاد یک context زمان‌دار با تایم اوت ۳۰ ثانیه‌ای منتظر می‌ماند و به HTTPServer اجازه می‌دهد تا مراحل Shutdown را اجرا کند.لازم به ذکر است اگر HTTPServer در مراحل shutdown دچار مشکلی شود و یا نتواند در زمان ۳۰ ثانیه، کار خود را به اتمام برساند خطای مربوطه را در خط ۱۳۹ نمایش خواهد داد و در نهایت کانال done را می‌بندد.در خط ۱۱۶ کد شروع وب سرور که به صورت Blocking مانده‌است با بسته شدن HTTPServer از حالت Blocking در می‌آیددر خط ۱۲۳ خروجی چاپ می‌شود و کار تابع myApp.Start به پایان می‌رسد.در تابع main برنامه با اتمام کار تابع myApp.Start به کار خود ادامه می‌دهد و منتظر دریافت اطلاعات از کانال done می‌شود که قبل تر در مرحله ۱ این کانال بسته شده استدر خط ۴۵ تابع cancel از context اصلی برنامه را اجرا خواهد کرد.تا اینجای کار سرور HTTP ما به صورت محترمانه‌ای کشته‌شد! اما یک سوال، اگر این بسته‌شدن برنامه در میان کار تابع DoBackgroundJob اتفاق بیافتد چه خواهد شد؟‌یک بار دیگه نرم‌افزار را اجرا می‌کنیم و این‌بار چند ثانیه صبر می‌کنیم تا به زمان اجرای ۱۰ ثانیه‌‌ای DoBackgroundJob برسیم و در میان کار آن، با فشار دادن Control-C برنامه رو می‌بندیم:http: 2020/07/13 15:31:23 Operation: app.Start, HTTP Server Starting on Address ::8080 
http: 2020/07/13 15:31:38 Background Job Started
http: 2020/07/13 15:31:38 Operation: app.BackgroundJobsHandler, Exited !
http: 2020/07/13 15:31:39 Background Job Step 1 Done
http: 2020/07/13 15:31:40 Background Job Step 2 Done
^C
http: 2020/07/13 15:31:40 Operation: app.GracefulShutdown, Graceful Shutdown Process Started 
http: 2020/07/13 15:31:40 Operation: app.Start, HTTPServer exited blocking mode 
http: 2020/07/13 15:31:40 Server stoppedمشکل را دیدید‌‌؟‌ مراحل اجرایی DoBackgroundJob در وسط کار متوقف شد! و ما منتظر به پایان رسیدن آن نشدیم! خوب مشکل از کجا بود؟‌همانطور که در کد می‌بینید، هنگامی که تابع myApp.Start صدا زده شد ما context را به صورت ورودی برای آن ارسال کردیم.در خط ۹۲ برنامه، هنگامی که قصد داشیم کنترل کننده BackgroundJobsHandler را صدا کنیم، دوباره context را به صورت ورودی برای آن فرستادیم.وقتی مراحل shutdown به جریان افتاد در آخرین مرحله ما تابع cancel را صدا کردیم که این به دنبال آن باید پیام مربوط در خط ۶۵، پیام چاپ می‌شد که این اتفاق نیفتاد، زیرا برنامه قبل از آنکه فرصتی برای ادامه کار داشته‌باشد، بسته شد!نکته: اگر قبل از بسته شدن یک ثانیه صبر می‌کردیم ممکن بود آن پیام نمایش داده‌شود و یا حتی اگر چند ثانیه بیشتر صبر می‌کردیم شاید مراحل ۳ گانه DoBackgroundJob هم به اتمام میرسید نه؟‌ جواب اینه که شاید ! ولی هیچ تضمینی برای اجرای درست کامل DoBackgroundJob وجود ندارد.استفاده از WaitGroupمن معمولا این مشکل را به این شکل حل می‌کنم که مراحل graceful shutdown در HTTPServer را در کنار graceful shutdown دیگر بخش‌های برنامه باهم انجام می‌دهم. بیایم یک کد اصلاح شده را باهم ببینیم: https://gist.github.com/subzerobo/ffb7903486f3d845e3d27730a6ba4897 برای این کار با استفاده از اصل ترکیب یا composition ساختار App struct را از نوع sync.WaitGroup تعریف کردم هر موقع که قصد دارم یک Background Job را که باید حتما بعد از شروع به طور کامل اجرا شود استارت کنم با اجرای دستور app.Add در خط ۷۴ یک مقدار به App WaitGroup اضافه می‌کنم و با پایان کار با صدا کردن app.Done یکی از مقدار WaitGroup را کم می‌کنیم. و در انتهای کد در تابع main به راحتی با صدا کردن دستور app.Wait منتظر می‌شوم تا تمامی کارهای در حال اجرا به اتمام برسندحالا یک بار دیگر کد را اجرا می‌کنیم و این بار هم دقیقا در میان کار DoBackgroundJob برنامه را با Control-C می‌بندیم:http: 2020/07/13 16:06:20 Operation: app.Start, HTTP Server Starting on Address ::8080 http: 2020/07/13 16:06:35 Background Job Started
http: 2020/07/13 16:06:35 Operation: app.BackgroundJobsHandler, Exited !
http: 2020/07/13 16:06:36 Background Job Step 1 Done
^C
http: 2020/07/13 16:06:36 Operation: app.GracefulShutdown, Graceful Shutdown Process Started 
http: 2020/07/13 16:06:36 Operation: app.Start, HTTPServer exited blocking mode 
http: 2020/07/13 16:06:36 Server stopped
http: 2020/07/13 16:06:37 Background Job Step 2 Done
http: 2020/07/13 16:06:38 Background Job Step 3 Done
http: 2020/07/13 16:06:39 Background Job Finished
http: 2020/07/13 16:06:39 Main Shutdown successfully, see you next time ;-)همانطور که مشاهده می‌کنید، این بار با فشرده شدن Control-C وب سرور به صورت درست بسته شد و از طرف دیگر هم در خط ۴۸ کد، منتظر WaitGroup اپ شدیم تا کار(های) شروع شده به طور کامل به پایان برسد.</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Thu, 30 Jul 2020 14:21:05 +0430</pubDate>
            </item>
                    <item>
                <title>ترکیب به جای وراثت در زبان Go</title>
                <link>https://virgool.io/golangpub/composition-over-inheritance-eabguanl36dr</link>
                <description>زبان برنامه نویسی Go با به کار گیری از یک تایپ سیستم انعطاف پذیر،امکان استفاده مجدد از کد رو با کمترین میزان تلاش در اختیار برنامه نویس قرار میدهد. البته که زبان Go هنوز هم یک زبان شئ گراست ولی بدون مشکلات همیشگی این زبانها! اگر شماهم چندین روز رو درگیر برنامه ریزی برای کلاسهای abstract و interface های مرتبط به اونها در یک برنامه پیچیده جاوا و یا ++C بوده باشید، از سادگی تایپ سیستم Golang لذت خواهید برد.برنامه نویسهای Go با استفاده از الگوی طراحی Composition به سادگی میتوانند یک تایپ رو به صورت embed در یک تایپ دیگر وارد کنند تا بتوانند از تمام امکانات تایپ مبدا استفاده کنند، البته به خاطر داشته باشیم که  زبان های برنامه نویسی دیگری هم از Composition استفاده میکنند ولی اغلب آنها عمیقا به ارث بری وابسته اند که استفاده از این امکان رو در این زبان ها مشکل و پیچیده میکنه.در زبان Go تایپها ترکیب شده از تایپ های کوچکترند که در تضاد با مدل های سنتی ارث بری هستند.خوب برای اینکه با این مفهوم بهتر آشنا بشیم با مثال همیشگی Duck شروع میکنیم.type Duck struct {
    ID int64
    Name string
}حالا میتونیم برای Duck struct یک متود هم برای خوردن به شکل زیر تعریف کنیم.func (d *Duck) Eat() {
    fmt.Println(&amp;quotDuck %s eats!&amp;quot, d.Name)
}بسیار عالی! اگه در نظر داشته باشیم یه struct غاز وحشی هم داشته باشیم که خیلی شبیه به اردک باشه ولی رنگ های مختلفی دارند و قراره رنگهاشون رو هم ذخیره کنیم چی ؟ زبان Go ارث بری نداره ولی از ترکیب (Composition) پشتیبانی می‌کندtype Mallard struct {
    Duck
    Color string
}با Embed کردن استراکچر Duck در Mallard میتونیم به خصیصه های &#x60;ID&#x60; و &#x60;Name&#x60; دسترسی پیدا کنیمduck := new(Duck)
duck.ID = 1
duck.Name = &amp;quotRick&amp;quot

mallard := new(Mallard)
mallard.Color = &amp;quotGreen&amp;quot

// copy info:
mallard.Name = duck.Name
mallard.ID = duck.ID

// or even better
mallard.Duck = *duckالبته که برای Mallard struct هم میتونیم متدهای مختص به خودش رو ایجاد کنیم.func (m *Mallard) Sleep() {
    fmt.Println(&amp;quot%s Mallard %s sleeps!&amp;quot,m.Color, m.Name)
}حالا با اینکار Mallard ما هم میتونه غذا بخوره و هم میتونه بخوابه !mallard.Eat()
malled.Sleep()

// Duck Ruck eats!
// Green Mallard Rick sleeps!اگه به چشم شئ گرایی به نتیجه نگاه کنیم، خروجی کار خیلی شبیه به ارث بری به نظر میرسه ولی در اصل اجرای اون کاملا بر اساس قاعده ترکیب یا composition هست.به قول یکی از دوستان خوبم که میگه :اگه میخواهی یک زبان رو به روش درست درک کنی بهتره به نحوه توسعه پکیج ها و کامپوننت های داخلی همون زبان نگاه کنی !و برای زبان Golang این نقل قول خیلی کارایی داره!یکی از روشهای خیلی متداول در پکیج های داخلی Golang برای lock کردن ساختارهای داده ها استفاده از همین الگوی طراحی composition هست برای مثال در کتابخانه cache ساختار hashDebug درون خود sync.Mutex را ضمیمه کرده پس هرجا برای تغییر مپ m نیاز به قفل کردن وجود داشته باشد کافیه با اجرای دستور hashDebug.Lock از قابلیت Lock که به واسطه sync.Mutex به دست آورده استفاده کنه.// hashDebug holds the input to every computed hash ID,
// so that we can work backward from the ID involved in a
// cache entry mismatch to a description of what should be there.
var hashDebug struct {
   sync.Mutex
   m map[[HashSize]byte]string
}

// reverseHash returns the input used to compute the hash id.
func reverseHash(id [HashSize]byte) string {
   hashDebug.Lock()
   s := hashDebug.m[id]
   hashDebug.Unlock()
   return s
}</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Mon, 06 Jul 2020 13:38:36 +0430</pubDate>
            </item>
                    <item>
                <title>داکرفایل چند مرحله ای برای ایمیج سبک و سریع در Golang</title>
                <link>https://aparat.design/golang-fast-lightweight-multi-stage-dockerfile-wt4nelecwtr6</link>
                <description>سرعت خروجی گرفتن در فرآیندهای توسعه و پیاده‌سازی برای اعمال سریع تغییرات در کد بسیار مهم است، بنابراین در پروسه‌های روزمره‌ای که در توسعه ابزارهای زیرساختی در آپارات داشتم به تجربه‌ای تحت عنوان داکرفایل چند مرحله‌ای برای ایجاد Image های سبک و سریع در زبان Golang رسیدم و در این مقاله می‌خواهم این تجربه رو با شما در میان بگذارم.خیلی از ما وقتی که می‌خواهیم اپلکیشنِ Golang خودمان را داکرایز کنیم، از Image رسمی پیشفرض Golang استفاده‌ می‌کنیم. https://docs.docker.com/samples/library/golang/ همانطور که Dockerfile این Image را می‌ببینید با خطوط زیر شروع می‌شود :FROM golang
FROM nginx
FROM openjdkحالا اگر این Image را دریافت کنیم، متوجه  خواهید‌شد که ۸۰۳ مگابایت حجم دارد. باید گفت، برای یک Image خالی که هیچ کدی درون آن نیست حجم خیلی زیادی است، اینطور نیست؟docker pull golang:1.13
$ docker image list
golang                                     1.13                3a7408f53f79        2 months ago        803MBاز سویی دیگر یک Image کم حجم به نام Alpine برای Golang وجود دارد که ۳۶۰ مگابایت حجم دارد درست است که حجم کمتری نسبت به Image رسمی golang دارد اما برای یک Image در حالت Production حجم خیلی زیادی است. FROM golang:alpine
$ docker image list
golang                                     alpine              459ae5e869df        10 days ago         370MBاستفاده از روش “چند مرحله‌ای برای کاهش حجمبه لطف استفاده از روش “چند مرحله‌ای” داکر در ایجاد Image ها می‌توانیم فایل خروجی نرم‌افزار خود را در Image golang:alpine بسازیم و یک Image بر اساس alpine تولید کنیم که تنها، فایل اجرایی نرم‌افزار ما در آن باشد. https://docs.docker.com/develop/develop-images/multistage-build/ برای روشن‌تر شدن موضوع بیایید باهم یک وب سرور ساده با Go بنویسیم و در ادامه سراغ Dockerfile پروژه برویم، ابتدا از Image Alpine به عنوان Builder استفاده می‌کنیم. می‌توانید حجم Image را در تصویر زیر مشاهده کنید: https://gist.github.com/subzerobo/0296050e7f1ef7e6035aa6d87f67fd0d  https://gist.github.com/subzerobo/c26797205286ff1330c8e1a145722f60 حالا وقتش هست که ببینیم Image برنامه به چه شکل ایجاد می‌شود و چه حجمی خواهد داشت؟$ docker build -t subzero/sample .
Sending build context to Docker daemon   25.6kB
Step 1/10 : FROM golang:alpine AS builder 
---&gt; 459ae5e869df
Step 2/10 : WORKDIR /src ---&gt; Using cache 
---&gt; 6cf33681f8bb
Step 3/10 : COPY . /src---&gt; b2e0287ec4f1
Step 4/10 : ENV GO111MODULE=on
---&gt; Running in b2a8def41333
Removing intermediate container b2a8def41333
---&gt; 33858d537c8c
Step 5/10 : RUN go mod download
---&gt; Running in a57d93861ca6
Removing intermediate container a57d93861ca6 
---&gt; bc14349da12c
Step 6/10 : RUN go build -o server main.go
---&gt; Running in 306afd335c6cRemoving intermediate container 306afd335c6c---&gt; 970ebfd59bd1
Step 7/10 : FROM scratch 
---&gt; 
Step 8/10 : WORKDIR /app
---&gt; Running in 0c4735c45471
Removing intermediate container 0c4735c45471
---&gt; d2ee5378c6d8
Step 9/10 : COPY --from=builder /src/server /app/
---&gt; 4644b56bd11e
Step 10/10 : ENTRYPOINT ./server
---&gt; Running in 18c324363942
Removing intermediate container 18c324363942
---&gt; 2fa59a876599
Successfully built 2fa59a876599
Successfully tagged subzero/sample:latest

$ docker image list
REPOSITORY                                 TAG                 IMAGE ID                         SIZE
subzero/sample                             latest              2fa59a876599                13MBخیلی بهتر شد نه؟‌باید بگویم هنوز هم جا برای کم شدن حجم این فایل وجود دارد، به طور مثال؛اگر هنگام ایجاد فایل خروجی، اطلاعات مربوط به Debug را حذف کنیم و فایل را مستقیم برای سیستم‌ عامل لینوکس خروجی بگیریم، این حجم باز کاهش پیدا می‌کند. برای این کار کافیست خط دهم داکرفایلی را که ایجاد کردیم به این شکل زیر تغییر دهیم:RUN go build -o server main.go
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -ldflags=&amp;quot-w -s&amp;quot -o server main.go

REPOSITORY                                 TAG                 IMAGE ID                    SIZE
subzero/sample                             latest              23ad308c5a7b           9.31MBخوب با همین تغییر بازهم حجم خروجی حدود ۲۵ درصد کاهش پیدا کرد.استفاده از روش “چند مرحله‌ای” برای کاهش زمان Buildبا توجه به اینکه برای استفاده از پکیج‌های زبان Go در ایران با مشکلات زیادی مواجه هستیم و برای Build کردن Image از پروکسی استفاده می‌کنیم، کاهش مدت زمان Build در محیط Production  یک دغدغه اصلی است.به طور معمول اگر کد در مرحله Production باشد دیگر تغییرات زیادی در پکیج‌های استفاده شده، ایجاد نمی‌شود یا حداقل در پروژه‌هایی که من تا به امروز کار کردم، این موضوع زیاد پیش آمده‌است،برای مثال، شرایطی را در نظر بگیرید که در روز، چیزی حدود ۱۰ بار تغییرات دارید و هنوز پروژه به روال عادی CI/CD شرکت اضافه نشده و از طرفی و مجبور هستید کد را به شکل دستی روی سرور Deploy کنید، با توجه به زمان Build می‌توانید تصور کنید چه سختی‌ای را به همراه دارد؟در تصویر زیر به طنز، شاهد مقایسه اندازه وزن خورشید، ستاره نوترونی، سیاه چاله و node_module هستید. درست است که حجم پیکج‌ها و ماژول‌های Golang خیلی زیاد نیست ولی مشکل پروکسی سرور برای دریافت پکیج‌های Golang با همین مقدار حجم، بسیار اذیت کننده‌است،meme سنگین تر اجسام در عالمبه همین دلیل برای حل مشکل و کاهش زمان Build دست به کار شدم و بعد از جستجو متوجه شدم، دوستانی که Node و React و پروژه هایی که نیاز به node_module دارد به راه‌حل‌های خوبی رسیدند. من نیز با توجه به روش‌های آن‌ها با اضافه‌کردن یک مرحله جدید به روش “چند مرحله‌ای” قبلی، راه‌حلی برای رفع این مشکل در Golang به شرح زیر پیدا کردم:ابتدا فایل go.mod به تنهایی در یک Image قرار می‌دهیم.بعد از آن دستور &#x60;go mod download&#x60; اجرا می‌شود که ماژول‌های مورد نیاز در یک Image واسط ذخیره شود.در مرحله بعد یک کد بر اساس این Image واسط تولید می‌شود.در انتها مشابه حالت قبل، خروجی در Image کم حجم alpine قرار داده می‌شود.نکته:با انجام این کار مادامی که تغییری در فایل go.mod پروژه اتفاق نیافتد،‌ مرحله گرفتن ماژول‌های مورد نیاز برای کامپایل پروژه skip می‌شود و سرعت ایجاد Image پروژه افزایش می‌یابد.نتیجه‌گیریزمان ایجاد Image در پروژه بالا که تعداد ماژول‌های مورد نیاز کمی داشت، در حالت اول به مدت ۱:۱۰ ثانیه است و در حالت دوم به ۳۷ ثانیه می‌رسد، این مقدار در شرایطی با ماژول‌های مورد نیازِ بیشتر، محسوس‌تر است، مثلا در پروژه لایو آپارات چیزی حدود ۴ دقیقه صرفه‌جویی در زمان داشتیم.</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Wed, 01 Jul 2020 14:33:05 +0430</pubDate>
            </item>
                    <item>
                <title>کرونا ویروس : اول سرکوب بعد رقصیدن !</title>
                <link>https://virgool.io/@ali.kaviani/hammerdance-av78898assuw</link>
                <description>۱۸ ماه آینده به چه شکل خواهد بود اگر سیاستمداران برای ما کمی زمان بخرند ؟‌  https://medium.com/@tomaspueyo/coronavirus-the-hammer-and-the-dance-be9337092b56 مقدمه مترجم : این مقاله ترجمه فارسی مقاله آقای توماس پویو است که در ادامه مقاله قبلی خود به نام کرونا : چرا باید همین الان اقدام کنیم نوشته شده است، مقاله قبلی توسط یکی از بچه ها در سایت ویرگول منتشر شده بود، که البته واقعا با توجه به طول مقاله دستش درد نکنه! این مقاله ۱۹ مارچ منتشر شده است و درباره سناریوهای احتمالی درباره آینده کرونا ویروس با توجه به اقدامات ممکن برای‌ جامعه آماری آمریکاست. با توجه به اینکه امروز میبینم شرایط توسط خیلی از هموطن هامون جدی گرفته نمیشه تصمیم گرفتم این مقاله رو ترجمه کنم. اگر ترجمه از لحاظ گرامری و نوشتاری دارای مشکلاتی هست من رو از همین الان ببخشید چون طولانی هست و قطعا زمینه تخصصی بنده نیست.مترجم: از اینجای متن به بعد ترجمه مستقیم متن  مقاله رو داریم و تماما به متن اصلی وفادار بوده امدر طول هفته گذشته نظر کشورهای مختلف درباره شرایط  از &quot;چیزی نیست بابا&quot; به &quot;شرایط اضطراریه و داریم به چخ سگ میریم&quot; تغییر کرده و با این وجود خیلی از کشورها هنوز کاری نمی کنند! هر کشور از خودش یک سوال رو داره میپرسه چه کار کنیم ؟‌ و جواب برای اونها خیلی واضح نیست.بعضی کشورها مثل فرانسه، اسپانیا یا فیلیپین شروع به اعمال قرنطیه (LockDown) های سنگین کرده اند. بقیه کشور مثل آمریکا، انگلیس، سوییس یا هلند با ترس لرز سعی در اعمال سیاست های ایجاد فاصله های اجتماعی یا Social Distancing کرده اند.چیزی که در این مقاله با استفاده از تعدادی زیادی از نمودار، اطلاعات و مدل های مختلف از منابع مختلف بررسی میکنیم شامل موارد زیر خواهد بود : شرایط فعلی چیه ؟چه راه هایی برای مقابله داریم ؟در حال حاضر یک چیز مهمه : زمان استراتژی خوب در حال حاضر چه به نظر میرسه ؟درباره تاثیرات اقتصادی و اجتماعی چه طور باید فکر کنیم‌؟سیستم درمانی دنیا همین حالا هم داره از هم میپاشه. کشورها دو راه حل بیشتر ندارند یا الان به سختی باهاش مبارزه می کنند و دچار یک اپیدمی عظیم خواهند شد. اگر راه حل دوم یعنی کاری نکردن رو پیش بگیرند ۱۰۰ ها هزار کشته خواهند شد در بعضی کشورهای حتی میلیونها نفر. این موضوع حتی ممکنه روی موج های بعدی ابتلا هیچ تاثیری نذاره. اگر امروز باهاش به سختی مبارزه کنیم تعداد کشته ها رو کنترل خواهیم کرد، به سیستم درمانمون اجازه بازیابی میدیم.بهتر آماده میشیم و بیشتر یاد خواهیم گرفت‌!دنیا تا امروز چیزی رو به این سرعت یاد نگرفته و ما به این یادگیری نیاز داریم، چون خیلی کم درباره این ویروس اطلاعات داریم و انجام تمامی این اقدامات یک چیز ارزشمند برامون به ارمغان میاره :‌برامون زمان میخره !اگر تصمیم بگیریم باهاش بجنگیم، این مبارزه در ابتدا سریع خواهد بود و در ادامه سرعت اون کم خواهد شد برای هفته ها و نه ماه ها در قرنطینه خواهیم بود و کم کم آزادی های بیشتری رو به دست میاریم.ممکنه شرایط خیلی سریع به حالت عادی برنگرده ولی در دراز مدت شرایطمون عادی خواهد شد. خوب بریم سراغ بحث !۱.شرایط فعلی چیه ؟هفته پیش این نمودار رو نشونتون دادم.دیدم که موارد کرونا ویروس در بیرون از چین در چه شرایطی قرار داره، در اون موقع نگرانی ما فقط شامل ایتالیاِ ایران و کره جنوبی بود. اگر دقت کنید در قسمت پایین سمت راست نمودار یک محدوده رو مشخص کرده بودم که شامل یک سری از کشورها هست که داشتند به تدریج درگیر میشدند. تمام منظورم من این بود که این کشورها به این سه کشور خواهند پیوست. حالا ببینیم از اون موقع شرایط به چه شکل شده است.همونطور که پیشبینی میشد تعداد موارد در نیم دوجین کشور دیگرهم به صورت انفجاری بالا رفت. در اینجا کشورهایی رو با تعداد مبتلایان بیشتر از ۱۰۰۰ نفر قرار داده ام، چند مورد رو در مورد این نمودار در نظر بگیرید:امروز اسپانیا، آلمان، فرانسه و آمریکا همگی تعداد مبتلای بیشتری به نسبت ایتالیا در زمانی که دستور قرنطینه عمومی رو صادر کرد دارند.۱۶ کشور امروز تعداد بیشتری مبتلا نسبت به استان هوبی زمانی که تحت قرنطینه کامل قرار داشت دارند! ژاپن، مالزی، کانادا، پرتغال، استرالیا، چک، بزریل و قطر بیشتر از هوبی مبتلا دارند ولی زیر ۱۰۰۰ نفر هستند. سوییس،سوئد، نروژ، اتریش، بلژیک، هلند و دانمارک همگی بالای ۱۰۰۰ نفر مبتلا دارند.آیا متوجه چیز عجیبی درباره این کشور ها نشدید‌؟ جدای از چین و ایران که دچار مبتلاهای خیلی بالایی هستند و برزیل و مالزی، هرکدام از این کشورها جزو ثروتمندترین کشورهای دنیا هستد.فکر میکنید این ویروس کشورهای پولدار رو هدف قرار داده ؟‌ یا اینکه کشورهای پولدار بهتر میتونند ویروس رو با تست شناسایی کنند ؟‌بعید به نظر میرسه که کشورهای فقیرتر دچار بیماری نشده باشند!‌ هرچند که هوای گرم و مرطوب تا حدی کمک میکنه!بیشترین برداشتی که محتمل هست اینه که کرونا ویروس یا به خاطر ارتباط کمتر این کشورها با دیگران دیرتر به اونها رسیده و یا اینکه همین الان هم اونجاست ولی این کشورها پول کافی برای تست مردم و فهمیدن وجود ویروس بین مردم رو نداره!به هرحال اگر این درست باشه، به این معنی خواهد بود بیشتر کشورها از کرونا ویروس در امان نیستند و فقط کمی زمان میبرد تا آنها هم شاهد همه گیری بین مردم باشند و شروع به اقدام خواهند کنند.۲.چه راه هایی برای مقابله داریم ؟از زمان مقاله قبل در هفته گذشته کرونا ویروس تعییر کرده و خیلی از کشورها آمار جدیدی رو ارائه کرده انداقدامات در اسپانیا و فرانسه به عنوان یک نمونه بزرگ در اینجا اسپانیا و فرانسه رو داریم، برای اسپانیا تایم لاین اقدامات به شرح زیر بود:روز پنجشنبه ۱۲ مارچ، رئیس جمهور این ادعا که مقامات اسپانیایی خطر این ویروس رو دست کم گرفته اند رد کرد و روز بعد جمعه شرایط اضطراری ملی اعلام کرد.روز شنبه این تصمیمات گرفته شدند :افراد اجازه ترک منازل خود رو ندارند مگر برای موارد مهمی مثل خرید مایحتاج،رفتن سرکار، داروخانه ها، بیمارستانها ،بانکها و شرکت های بیمه ای ممنوعیت خاص برای بیرون بردن کودکان برای پیاده روی و دیدن دوستان و خانوادهتمامی بارها و رستوران ها بسته هستند و تنها به صورت بیرون بر کار خواهند کردتمامی سرگرمی ها شامل ورزش، سینماها،‌موزه ها و جشن های عمومی تعطیل خواهند بودعروسی ها بدون مهمان برگزارخواهند شد و در مراسم ختم هم بیشتر از ۵ نفر اجازه شرکت ندارندحمل و نقل عمومی باز خواهد بودروز دوشبه مرزهای زمینی بسته شدندشرایط فرانسه هم خیلی مشابه بود با این تفاوت که زمان بیشتری برای انجام این تصمیمات صرف شد و الان شرایط آنها خیلی بدتر از اسپانیاست. برای مثال اجاره بها و مالیات برای کسب و کارهای کوچک معلق شده است. اقدامات در آمریکا و انگلستانآمریکا و انگلستان شبیه کشورهایی مثل سوییس و هلند هم تصمیاتی رو به تدریج گرفتند ! به طور مثال در آمریکا اقدامات به شرح ذیل بود :چهارشنبه ۱۱ مارچ : دستور لغو مسافرتجمعه:  اعلام شرایط اضطراری در سطح کشور ( تصمیمی برای ایجاد فاصله اجتماعی گرفته نشد)دوشنبه: دولت از عموم مردم خواست تا از رفتن به رستوران ها و بارها و اجتماعات بیشتر از ۱۰ نفر خودداری کنند. ( بازهم اجباری به ایجاد فاصله اجتماعی انجام نشد و فقط خواسته شد)خیلی از ایالت ها و شهرها پیشدستی کردن و موارد سختگیرانه رو اجباری کردند.انگلستان هم تصمیمات مشابهی رو گرفت : کلی پیشنهاد به مردم داد ولی خیلی کمتر مواردی رو اجباری کرد!این دو گروه از کشورها (اسپانیا و فرانسه ) در مقابل ( آمریکا و انگلیس ) دو راه کامل متفاوت برای مبارزه با کرونا ویروس رو پیش گرفتند توقیف و کاهش.بریم ببینیم اینها چه معنی ای دارند.راه حل اول : هیچ غلطی نکنیم قبل اینکه اینکار رو انجام بدیم، بیاید ببینیم اینکار برای کشور مثل آمریکا چه شرایطی رو ایجاد میکنه ؟ این ابزار فوق العاده پیش بینی اپیدمی میتونه بهتون کمک کنه که در سناریوهای مختلف چه اتفاقی خواهد افتاد.دقت کنید که نقطه صورتی رنگ پیک مبتلایان به ده ها میلیون نفر در یک تاریخ مشخص خواهد رسید. بسیاری از متغییر ها در این محاسبه گر به صورت پیش فرض نگهداری شده اند. تنها تغییر در آن مقدار متغییر R هست که بین ۲.۲ تا ۲.۴ است. مقدار مرگ و میر بیماری که حدود ۴ درصد در نظر گرفته شده است. طول درمان  که بین ۱۰ تا ۲۰ روز در نظر گرفته شده است. نرخ بستری در بیمارستان بین ۲۰ تا ۱۴ درصد بسته به بدی حال بیماران در نظر گرفته شده است ( ۲۰ درصد نرخ اعلام شده سازمان بهداشت جهانی است )اگر کاری نکنیم و همه مبتلا بشوند، سیستم درمانی زیر بار شدید قرارخواهد گرفت، میزان مرگ و میر به شدت افزایش پیدا میکند و حدود ۱۰ میلیون نفر کشته خواهند شد ( ستونهای آبی رنگ ). با یک حساب سر انگشتی هم اگر فرض کنیم ۷۵ درصد جمعیت آمریکایی مبتلا بشوند و ۴ درصد در اثر بیماری فوت کنند این عدد ۱۰ میلیون خواهد بود یعنی ۲۵ برابر آمریکایی هایی که در جنگ جهانی دوم کشته شدند !ممکنه با خودتون بگید ‍&quot; خیلی کمتر از اینها شنیده بودم ! این که خیلیه !‌&quot;خوب داستان چیه؟  با این همه اعداد و ارقام گیج شدن آسونه! ولی فقط دوتا عدد هست که مهم هستند. تعداد افرادی که مبتلا میشوند و مریض میشوند و درصدی از اونها که خواهد مرد. اگر فقط ۲۵ درصد مریض شوند ( یعنی بقیه هم ویروس رو داشته باشند ولی علائم مریضی رو نشون ندهند) و نرخ مرگ و میر رو ۰.۶ درصد به جای ۴ درصد در نظر بگیریم به عدد ۵۰۰ هزار مرگ در آمریکا خواهیم رسید. خیلی زیاده ولی باز ۲۰ برابر کمتر از عدد بالا خواهد بود.راجع به نرخ مرگ و میر چطور باید فکر کنیم ؟نمودار زیر همون نمودار بالایی هست ولی اینبار به افرادی که در بیمارستان بستری شده اند نگاه خواهیم کرد.رنگ آبی روشن تعداد افرادی هستد که باید در بیمارستان بستری شوند و رنگ آبی تیره تر نشون دهنده افرادی هست که به مراقبت های بیشتری درICU نیاز دارند. دقت کنید این عدد در آمریکا میتونه در بیشترین اندازه خودش به بالای ۳ میلیون نفر برسه.حالا این عدد رو با تعداد تخت های ICU در این کشور که حدود ۵۰ هزار تخت در امروز هست مقایسه کنید. این عدد اون خط تیره قرمز در نمودار هست! این همون مشکل ما خواهد بود وقتی خط تیره قرمز رنگ تعداد تخت های ICU باشه یعنی هر شخصی بالای اون خط با شرایط بحرانی نمی توانند به نگهداری که بهش نیاز دارند برسند و ممکنه بمیرند.اگر به جای تخت های آی سی یو به تعداد دستگاه های کمک تنفسی نگاهی بیاندازیم نتایج بازهم شبیه هستند امروز تعدادی کمتر از ۱۰۰ هزار از این دستگاه در آمریکا وجود دارد. در حالی که امروز حداقل یک بیمارستان در سیاتل نمیتوانند بیشتر از ۶۵ بیمار رو به دلیل کمبود امکانات اینتوبه کنند و به بیماران شانس بالای ۹۰ درصد برای مرگ می دهند.علت مرگ بالای افراد در هوبی در آن زمان و الان در ایتالیا و ایران همین موضوع است! نسبت مرگ به تعداد مبتلایان در هوبی در نهایت کاهش پیدا کرد چون اونها موفق شدند تقریبا یک شبه دوتا بیمارستان جدید بسازند کاری که ایران و ایتالیا نمی توانند انجام دهند و بعید است کشورهای زیاد دیگری هم موفق به انجام دادن اون بشوند. ببینیم دست آخر در این شرایط چه اتفاقی خواهد افتاد‌؟اگر ۵ درصد از مبتلایان به مراقبت های ویژه نیاز داشته باشند و نتوانیم این مراقبت رو انجام بدیم بیشتر اونها خواهند مرد به همین سادگی !به علاوه که اطلاعات اخیر نشان میدهد مبتلایان در آمریکا شرایط بیماری سخت تری نسبت به چینی ها دارند ولی کاش فقط همین بود! ولی نیست!تلفات جانبیاین اعداد فقط افرادی رو شامل میشه که در اثر ابتلا به کرونا ویروس کشته می شوند ولی چه اتقاقی برای بیماران دیگر مثل بیماران قلبی و ... میافته وقتی که بیمارستان ها ظرفیت پذیرش اونها رو نداشته باشند.چی میشه اگر شما دچار حمله قلبی شده اید ولی آمبولانس به جای ۸ دقیقه بعد از ۵۰ دقیقه (به دلیل تعداد بالای کرونا ویروسیها ) دنبال شما بیاد و تازه وقتی هم برسید بیمارستان تخت و دکتری برای مراقب ازتون نباشه، خوب میمیرد.در آمریکا به تنهایی سالانه ۴ میلیون مراجعه به ICU وجود داره و ۵۰۰ هزار نفر یعنی حدود ۱۳ درصد اونها با وجود بستری میمیرند. بدون وجود تخت های آی سی یو این نسبت مرگ میتونه تا ۸۰ درصد هم بالا بره و اگر خوشبینانه بگیم فقط ۵۰ درصدشون بمیرند تنها در یک سال درگیری با یک اپیدمی تعداد این مرگ های معمول از ۵۰۰ هزار نفر به ۲ میلیون نفر میرسه، یعنی ۱.۵ میلیون مرگ ناخواسته در اثر تلفات جانبی کرونا اگر به کرونا ویروس اجازه انتشار رو بدهیم سیستم درمانی آمریکا از هم خواهد پاشید و تعداد مرگها میلیونی خواهد بود. حتی بیشتر از ۱۰ میلیون نفراین موضوع برای کشورهای دیگر هم تقریبا به همین شکل هست. تعداد تخت های آی سی یو و دستگاه های تنفس مصنوعی تقریبا در کشورهای دیگر مشابه و یا کمتر از آمریکا هست واین یعنی مرگ دسته جمعی تعداد زیادی از انسانهاراه حل دوم : استراتژی کاهش شیب نمودار  یا Mitigationتا اینجا کاملا واضح هست که باید سریع واکنش نشون بدهیم دو تا راه حل باقی مونده کاهش و کنترل  هست.راه حل کاهش به این شکله :‌ &quot;جلوگیری از ابتلا به کرونا ویروس در شرایط فعلی ممکن نیست، پس بهتره بذاریم روالش رو طی کنه در حالی که سعی میکنیم پیک تعداد مبتلاها رو کاهش بدیم. پس بیاییم این نمودار رو یکم تخت کنیم تا مدیریت اون توسط سیستم درمانی امکان پذیر باشد &quot;ترجمه رنگ ها از بالا به پایین : قرمز :تعداد تخت های نگهداری بیماران سیاه :کاری انجام ندهیم  قهوه ای: ایزوله کردن مبتلاها نارنجی: ایزوله کردن مبتلاها و قرنطینه خانگی سبز : بستن مدرسه ها و دانشگاه ها آبی: ایزوله کردن و قرنطینه خانگی و ایجاد فاصله امن اجتماعی برا افراد بالای ۷۰ سالاین نمودار از یک مقاله بسیار مهم که در آخر هفته توسط کالج سلطنتی انگلیس منتشر شده برداشت شده است.انجام ندادن هیچ کاری در این شرایط با نمودار مشکی مشخص شده است، محور افقی زمان و محور عمودی تعداد بیماران نیازمند بستری به ازای هر ۱۰۰ هزار نفر مبتلا را نشان میدهد. هریک از نمودارهای دیگر اثر انجام هریک از اقدامات کنترل فاصله اجتماعی را نشان می دهد. رنگ آبی سخت ترین نوع اقدام را نشان میدهد یعنی ایزوله کردن بیماران، قرنطینه افراد سالم و قطع ارتباط افراد بالای ۷۰ سال. این خط آبی رنگ تقریبا استراتژی فعلی انگلیس رو شامل میشود هرچند که این امر رو فعلا پیشنهاد میکند و اجبار و کنترلی به اجرای آن وجود ندارد.در اینجا بازهم رنگ قرمز تعداد تخت های آی سی یو را نشان می دهد و میبینید که خیلی به پایین نزدیک است.در اینجا بازهم افرادی که بالای خط قرمز هستند احتمالا به خاطر عدم وجود آی سی یو خواهند مرد.بازهم در نظر بگیرید که با تخت کردن نمودار مبتلایان، آی سی یو ها هنوز هم برای چندماه در اختیار بیماران دیگر (غیر کرونا) فراهم نخواهد بود و تلفات جانبی را افزایش میدهد.احتمالا با شنیدن آن شوکه شده اید. وقتی میشنوید &quot;ما می خواهیم نمودار رو تخت کنیم&quot; درحقیقت این یعنی &quot;ما دانسته، سیستم درمانی رو با موج کاری عظیم خفه می کنیم و میزان مرگ و میر را حداقل تا ۱۰ برابر افزایش میدهیم&quot;شاید فکر کنید تا اینجاش هم خیلی بد بوده ! ولی هنوز تموم نشده، چون یکی از فرضیات مهم در این استراتژی کلمه ای به نام Herd Immunity یا مصونیت جمعی هست.مصونیت جمعی و جهش ژنتیکی ویروسایده کلی این هست که افرادی که مبتلا میشوند و خوب میشوند نسبت به ویروس مصون خواهند بود. لپ کلام اینکه ؛میدونم دو هفته ای روی قراره به چخ بریم، ولی وقتی تموم شد و یه چند میلیونی مردن، ویروس دیگه پخش نمیشه و بقیه ما مصون هستیم!‌ بزاریم یه بار همه بگیرند تا جمع بشه بره، چون راه حل جایگزین قرنطینه کردن هست و این یعنی ممکنه یکسال طول بکشه و ریسک ایجاد این پیک در آینده همیشه وجود داره.؛خوب اینجا یک چیز رو در نظر گرفتیم : ویروس زیاد تغییر نمیکنه. پس اگه زیاد تغییر نکنه تعداد زیادی از افراد مصون خواهند بود و بلاخره یه زمانی این اپیدمی جمع میشه.این ویروس چقدر احتمال داره جهش پیدا کنه ؟‌ خوب به نظر میرسه همین الان هم جهش پیدا کرده !!!!این نمودار جهش ژنتیکی ویروس را نشان میدهد. همانطور که مشاهده میکنید نژاد اولیه با زنگ بنفش از چین شروع شده ولی شروع به جهش کرده، نژادهای اروپایی بیشتر با رنگ سبز و زرد هستند ولی در آمریکا با نژاد با رنگ قرمز بیشتر درگیر هستند.البته خیلی هم تعجب نداره: ویروس های با هسته RNA مثل کرونا ویروس یا آنفولانزا ۱۰۰ برابر بیشتر از ویروس هایی با هسته DNA جهش پیدا می کنند. ( فکر کردی چرا واکسن سرماخوردگی کوفتی هیچ وقت کشف نشده !!‌) هرچند کرونا ویروس آهسته تر از آنفولانزا جهش کرده است.البته در نظر بگیرید که بهترین شرایط برای جهش ویروس ایجاد میلیون ها فرصت برای اون هست. دقیقا فرصتی که استراتژی کاهش ( تخت کردن نمودار ) در اختیار ویروس قرار میده : صدها میلیون آدم مبتلا و یعنی میلیونها فرصت برای جهش ویروسبه همین دلیل هست که باید هر سال واکسن آنفلوانرا بزنیم چون تعداد خیلی زیادی از شاخه های آنفولانزا بوجود اومده و همون واکسن آنفولانزای قدیمی روی همه اونها موثر نیست.بیایید اینطوری بهش نگاه کنیم :‌استراتژی تخت کردن نمودار ( Mitigation ) نه تنها فرض بر مرگ میلیونها نفر در کشوری مثل آمریکا و انگلیس رو میذاره بلکه داره روی این فرض که ویروس زیاد جهش پیدا نمیکنه قمار میکنه‌ ( در حالی که اینطور نیست ) و اینکار به ویروس فرصت جهش بیشتری رو میده. یعنی وقتی چند میلیون مرگ اتفاق افتاد هر سال باید منتظر میلیون ها مرگ دیگر به خاطر ویروس های جهش یافته بعدی باشیم و کرونا ویروس مهمان هرساله ی ما خواهد بود.بهترین راه برای جهش ویروس ایجاد میلیون ها فرصت برای اونه کاری که استراتژی کاهش شیب نمودار یا همون استراتژی Mitigation‌ اون رو براش فراهم میکنهخوب حالا که نه هیچ کاری نکردن و نه کاهش شیب نمودار ( Mitigation )‌کاری از پیش نمیبره راه حل جایگزین چیه ؟‌  راه حل سوم : روش سرکوب یا Suppressionراه حل Mitigation سعی بر محدود کردن ویروس نداره و فقط سعی میکنه که نمودار ابتلا رو کمی تخت کنه. در حالی که استراتژی سرکوب سعی میکنه تصمیمات خیلی سختگیرانه ای رو برای کنترل اپیدمی انجام بده به طور خاص :همین الان خیلی محکم جلو برید :‌ دستور بدید (خواهش نکنید) فاصله اجتماعی به شدت رعایت شود و اوضاع رو تحت کنترل در بیاورید.بعدا کم کم محدودیت ها را بردارید تا مردم بتواند به تدریج آزادی هایشون را بدست بیاورندخوب این چطور به نظر خواهد اومد‌؟‌دقت کنید نمودار عمودی از چند ده میلیون به چند ده هزار نفر کاهش پیدا کرد.با استفاده از استراتژی سرکوب، بعد از موج اول ابتلا تعداد مرگ در حدود چند هزار خواهد بود و نه چند میلیون چرا‌؟ چون نه تنها ما افزایش نمایی تعداد مبتلایان رو کنترل کرده ایم. بلکه میزان مرگ میر را به خاطر کاهش فشار روی سیستم درمانی نیز کاهش داده ایم. در اینجا میزان مرگ و میر را حدود ۰.۹ درصد در نظر گرفتم چیزی که امروز در کره جنوبی شاهد اون هستیم. که بهترین روش کنترلی روی ویروس رو که استراتژی سرکوب هست رو دنبال میکنه.خوب با این حال اینکار رو نکردن به نظر حماقت میاد! همه باید از استراتژی سرکوب استفاده کنند نه ؟‌ولی چرا خیلی از دولت ها تعلل می کنند ؟‌توضیح مترجم :‌ منظور از قرنطینه در این ترجمه معادل کلمه Lock-Down یا منع برقراری ارتباط با فضای خارجی هست ( قرنطینه خانگی ) و نه اون قرنطینه ؛قرون وسطایی به قول دوستان ؛ ولی در این متن من از کلمه قرنطینه خانگی استفاده میکنماونها از سه تا چیز میترسند : این منع برقراری ارتباط با فضای خارج (LockDown) اجباری اولیه برای چند ماه ممکنه طول بکشه، که برای خیلی از مردم قابل قبول نیست.یک قرنطینه خانگی چند ماهه اقتصاد رو نابود میکنه !ممکنه حتی مشکل رو حل نکنه چون فقط داریم مشکل اپیدمی رو به بعد منتقل میکنیم، چون به محض اینکه این قوانین رو برداریم بازهم مردم مبتلا میشوند.این روشی هست که تیم امپریال کالج روش سرکوب رو مدل کرده اند. خطوط سبز و زرد سناریوهای مختلف سرکوب هستند. به نظر خوب نمیاد ؟‌هنوز هم پیک های بزرگی رو خواهیم داشت پس چر به خودمون زحمت بدیم ؟‌خوب به این سوال های هم میرسیم. ولی یه چیز مهم تر این وسط وجود داره !ما اینجا یه موضوع رو کامل فراموش کردیم.اگه اینجوری به موضوع نگاه کنیم. هر دو راه Mitigation و Suppression در کنار هم خیلی خوب به نظر نمیرسند.یا امروز تعداد زیادی از افراد خواهند مرد و  امروز به اقتصاد ضربه نمیزنیم و یا امروز بهش ضربه میزنیم و مرگ کلی آدم رو به عقب می اندازیم .در این نگرش ارزش زمان رو در نظر نمیگیریم‌!۳. در حال حاضر یک چیز مهمه : زمان در پست قبلی،‌در باره ارزش زمان در نجات جان افراد توضیح دادیم. هر روز و هر ساعتی که ما برای اعمال محدودیت ها دست دست کنیم، این رشد خطر به صورت نمایی ادامه پیدا خواهد کرد. با هم دیدیم که چطور یک روز میتواند تعداد کل مبتلایان رو تا ۴۰ درصد کاهش و تعداد مرگ رو حتی بیشتر کاهش دهد.ما در حال تجربه یکی از بزرگترین فشارها وارده بر سیستم درمانی در تاریخ جهان هستیم که اصلا برای اون آماده نیستیم و با دشمنی مواجه هستیم که اصلا اون رو نمیشناسیم و شرایط خوبی برای جنگ نیست !فرض کنید شما قراره با بدترین دشمنتون بجنگید، که اصلا چیزی درباره ش نمیدونید و فقط دوتا راه حل دارید: اول اینکه با کله برید تو دلش و دوم اینکه فرار کنید و برای خودتون یکم زمان بخرید تا آماده بشید. حالا کدوم رو انتخاب میکنید ؟این کاری هست که باید امروز انجام بدیم. جهان تازه آگاه شده است. هر روز که برای مقابله با کرونا ویروس وقت بدست بیاریم می تونیم بهتر آماده بشویم.در بخشهای بعدی درباره جزئیاتی که برامون وقت میخره حرف میزنیم.کاهش تعداد مبتلایان با سرکوب موثر تعداد موارد واقعی در یک شب میتوانند به شدت کاهش پیدا کنند، دقت کنید موارد واقعی نه چیزی که از تست ها به صورت رسمی اعلام میشوند. در مقاله قبلی آمار هوبی رو با هم دیدیمامروز تعداد افراد مبتلای جدید در استان ۶۰ میلیون نفره هوبی به صفر رسیده است/انجام آزمایشات تا چند هفته آینده ادامه خواهد داشت. ولی این تعداد رو کاهش خواهد بود. با تعداد کم مبتلایان میزان کشندگی کاهش خواهد یافت و تلفات جانبی نیز کاهش خواهند یافت : تعداد افرادی غیر کرونایی کمتری در اثر شلوغی بیمارستان ها خواهند مرد.اثرات سرکوب (Suppression) :تعداد مبتلایان کل را کاهش خواهد دادفشار روی سیستم درمان و افرادی که در آن مشغولند را کم میکندمیزان درصد مرگ و میر را کاهش میدهدکاهش تلفات جانبیامکان درمان و بازگشت کارکنان سیستم درمانی که مبتلا، ایزوله و یا قرنطینه هستند به محل کار. فقط در ایتالیا ۸ درصد از کل مبتلایان را پرستاران و پزشکان تشکیل میدهند. (منبع)مشکل اصلی : تست و پیگیری ارتباطات مبتلایاندر حال حاضر در انگلیس و آمریکا هیچ ایده ای درباره تعداد واقعی مبتلایان وجود ندارد. نمیدانیم چند نفر مبتلا هستند. فقط میدانیم آمار رسمی آمار واقعی نیست! و واقعیت چیزی بیش از ۱۰ها هزار نفر هست. دلیل آنهم اینست که ما تست نمیکنیم.با داشتن چند هفته اضافه تر، میتوانیم مراکز تست را مرتب تر کنیم و شروع به تست همه کنیم. با داشتن این اطلاعات می تونیم به اندازه واقعی مشکل پی ببریم و بدانیم کجا ها باید بیشتر سخت گیرباشیم و کجاها را میتوانیم از قرنطینه خانگی رها کنیم.روش های تست جدید سرعت میگیرند و هزینه های آن پایین می آیندبا ایجاد وقت می توانیم بهتر پیگیر افرادی که فرد مبتلا با آنها در ارتباط بوده را پیدا کنیم مانند کاری که در چین و باقی کشورهای شرق آسیا در حال انجام است. وقتی میدانیم ویروس کجاست می توانیم فقط این بخش ها را هدف قرار دهیم. این کار شاخ غول شکستن که نیست!  اقدامات همین بخش تست و پیگیری به تنهایی توانسه میزان رشد اپیدمی در کره جنوبی را بدون ایجاد شرایط قرنطینه سخت گیرانه کنترل کند.ایجاد ظرفیت جدیدآمریکا و احتمالا انگلیس دارند بدون زره و سپر به جنگ می روند.ما در آمریکا تنها برای دو هفته ماسک داریم ، تعداد وسایل حفاظت شخصی کمی برای کارکنان وجود دارد، به تعداد کافی دستگاه تنفس مصنوعی وجود ندارد، به تعداد کافی ICU و دستگاه ECMO ( دستگاه اکسیژن رسان به خون ) وجود ندارد و همین امر باعث افزایش درصد مرگ و میر در استراتژی کاهش شیب فعلی شده است.ولی اگر کمی زمان برای خود بخریم:میتوانیم تجهیزات لازم برای موج های بعدی را بخریم میتوانیم تولید ماسک، لوازم حفاظت شخصی، دستگاه های تنفسی و EMCO را افزایش دهیم و نرخ مرگ و میر را کاهش دهیم.البته که این تنها ظرفیت لازم نیست، ما نیاز داریم کارکنان بخش درمان در کمترین زمان ممکن اضافه شوند. از کجا بیاوریم ؟‌ لازم است که افراد جدیدی را برای کمک آموزش اولیه دهیم و کارکنان درمانی بازنشسته را به کار برگردانیم. خیلی از کشورها همین الان هم شروع کرده اند.کاهش دادن میزان واگیری عمومیعموم مردم ترسیده اند!‌( البته که ایرانی جماعت نمیترسه، جوج و شمالش به راهه هنوز !‌). کرونا ویروس جدیده و چیز زیادی درباره اش نمیدونیم. مردم تا الان نفهمیده اند که دست ندهند و بغل نکنند. نمی دانند در را باید با آرنج باز کنند، بعد دست زدن به دستگیره در دستشان را نمی شویند و قبل نشتین روی میز آنرا ضد عفونی نمیکنند.وقتی به اندازه کافی ماسک داشته باشیم. میتوانیم بیرون سیستم درمانی هم استفاده کنیم، الان بهتراست ماسک را برای کادر درمانی باقی گذاریم. ولی اگر مردم نترسند برای زندگی روزمره هم می توانند از آن استفاده کنند و هنگامی که مریض هستند دیگران را آلوده نکنند. اینها تمامشان راههای ارزانی برای جلوگیری از انتقال ویروس در جامعه هستند. هرچه کمتر ویروس منتشر شود محدودیت های کمتری نیاز به وضع کردن خواهد بود. ولی ما برای آموزش مردم به زمان نیاز داریم.شناختن ویروسما درباره این ویروس جدید میزان خیلی کمی میدانیم ، ولی هر هفته که میگذرد صدها مقاله جدید منتشر می شوند.جهان بر علیه یک دشمن مشترک با هم متحد شده است. همه محققان در تمام دنیا به تکاپو افتاده اند تا ویروس جدید را بهتر بشناسند.چطور منتقل میشود ؟چطور پخش شدن آن را می شود کند کرد ؟‌درصد افراد ناقل بدون علامت چقدر است ؟‌آیا می توانند ویروس را منتقل کنند ؟‌ چقدر ؟راه های درمان درست چیست ؟‌ (روغن بنفشه ؟‌)ویروس چه مدت زنده میماند‌؟روی چه سطوحی زنده میماند ؟‌چقدر ایجاد فاصله اجتماعی کمک میکند؟هزینه های ایجاد این فاصله اجتماعی چیست ؟ بهترین روش های رهگیری مبتلایان چیست ؟چقدر تست های ما قابل اطمینان هستند ؟‌پاسخ روشن به این سوالات می تواند،‌عکس العمل ما را تا جای ممکن دقیقتر کند در کنار آنکه تبعات اقتصادی و اجتماعی را کاهش می دهیم. جواب این سوالات تنها به هفته ها زمان نیاز دارد نه سالها !پیدا کردن درمان از اینها گذشته اگر در هفته های آینده راهی برای درمان آن پیدا کردیم چی ؟‌ هر روز که وقت داشته باشیم بیشتر به درمان نزدیک میشویم. همین الان هم داروهای پیشنهادی مانند فاویپیراپیر و کلروکوین وجود دارند، اگر دوماه دیگر درمانی برای این بیماری پیدا کنیم چی ؟  چقدر احمق به نظر خواهیم رسید اگر تا آن موقع با استراتژی Mitigation میلیون ها نفر را از دست داده باشیم ؟‌۴. چکش و رقص الان میدونیم که استراتژی کاهشی (Mitigation) احتمالا گزینه افتضاحی هست و استراتژی سرکوب فواید کوتاه مدت زیادی داره. ولی افراد نگرانی های بحقی در مورد این استراتژی دارند :چقدر این مدت طول میکشد‌؟چقدر هزینه خواهد داشت ؟آیا پیک دوم به بزرگی موقعی خواهد بود که اینکار را انجام ندهیم ؟‌در اینجا دقیقتر به این موضوع نگاه خواهیم کرد که این استراتژی چگونه خواهد بود اسم آن را گذاشته ام چکش و رقصچکش اول اینکه اگر کشورها سریع و با شدت عمل کنند به دلیل تمامی مواردی که اشاره کردیم با در نظر گرفتن ارزش زمان در کمترین زمان ممکن آن را فرو خواهیم نشاند.مهمترین سوال این است، چقدر طول خواهد کشید ؟ترسی که خیلی از افراد در حال حاضر دارند این است که برای ماه ها در خانه هایشان حبس شود در حالی که متعاقب آن فاجعه اقصادی و فروپاشی روانی برایشان ایجاد خواهد شد. این ایده متاسفانه در مقاله معروف امپریال کالج نیز بررسی شده است.این نمودار را به خاطر دارید‌؟ منطقه آبی روشن  از انتهای مارچ تا انتهای ماه آگوست ناحیه ای است که در مقاله به عنوان زمان چکش پیشنهاد شده است، که شامل سرکوب اولیه و ایجاد فاصله اجتماعی به صورت اجباری است.اگر شما یک سیاستمدار هستید و میدانید که یک گزینه اجازه دادن به مرگ ۱۰۰ ها هزار نفر و یا میلیونها نفر از افراد در استراتژی mitigation و گزینه دیگر متوقف کردن اقتصاد برای ۵ ماه قبل رسیدن به همان تعداد از مرگ و ابتلا باشد، به نظر احتمال قابل بررسی به نظرتون نخواهد بود‌؟ نه ؟ولی به نظر میاد لازم نیست این اتفاق بیافته!در این مقاله به شدت به دلیل مشکلات اساسی به تحقیق امپریال کالج ایراد گرفته شده است.گفته شده است که آنها پیگیری های اشخاص مبتلا (‌استراتژی اصلی کره جنوبی و سنگاپور و چین) و محدودیت های محکم مسافرت و تاثیر آن بر اجتماعات بزرگ را در نظر نگرفته اند.زمان لازم برای بخش اول ( چکش) چند هفته و نه چند ماه است !این نمودار تعداد کل مبتلایان در هوبی چین را با ۶۰ میلیون نفر جمعیتت در هر روز از ۲۳ ژانویه نمایش میدهد در عرض ۲ هفته کشور به کار برگشته است و در عرض ۵ هفته شرایط تحت کنترل در آمده است. به یاد داشته باشید اینجا بدترین منطقه در چین از لحاظ بیماری بوده است.به یاد داشته باشید که اینها نمودارهای نارنجی رنگ هستند ستونهای طوسی رنگ ( تعداد مبتلایان واقعی) خیلی زودتر بعد از قرنطینه کامل کاهش یافته بود! نمودار ۹ را ببینید.اقداماتی که آنها انجام دادند خیلی شبیه کاری است که الان در ایتالیا، اسپانیا و فرانسه در حال انجام است: محدود کردن بیماران، قرنطینه های اجباری، مردم باید در خانه های بمانند مگر برای شرایط اضطراری که دارند و یا خرید غذا، پیگیری تماس با افراد آلوده، محدودیت های مسافرت و ...البته جزئیات مهم هستند‌!محدودیت ها در چین خیلی محکمتر بود، بطور مثال در هر خانواده یکنفر هر ۳ روز اجازه ترک خانه برای خرید را داشت و به نظر میاد همین سختگیری باعث شد خیلی زودتر شرایط تحت کنترل قرارگیرد.در ایتالیا، فرانسه و اسپانیا این اقدامات به ان اندازه سخت و محکم نیستند و پیاده سازی هم به آن اندازه سختگیرانه نیست. مردم هنوز در خیابانها را میروند، درحالی که خیلی ها هنوز ماسک ندارند. به نظر می آید این چکش آرامتری است و زمان بیشتری برای کنترل مناسب میطلبد.برخی از افراد این موضوع را به حساب آن میگذارند که سخت گیری ها نتیجه ای در بر نداشته است، ولی این موضوع غلت است !کره جنوبی در مقطع زمانی مشخصی بدترین اپیدمی بیرون از چین بود، ولی الان به شدت تحت کنترل درآمده است و آنها با تنها خواستن از مردم برای بیرون نیآمدن از خانه هایشان به این مهم دست پیدا نکرده اند.بلکه با تست های شدید، رهگیری ارتباطات مبتلایان، ایزوله کردن و قرنطینه های سخت گیرانه موفق به این کار شدند.اگر یک همه گیری مثل کره جنوبی، بدون ایجاد فاصله اجتماعی اجباری، بتواند کنترل شود، کشورهای غربی میتونادد از یک چکش که بتواند همه گیری را کنترل کند استفاده کنندو ولی موضوع فقط نظم و اجرای صحیح آن است.آیا میتوانیم برای چند هفته در خانه بمانیم و مطمئن شویم چندین میلیون نفر نمی میرند ؟‌ مطمئنم میتوانیم. البته به شرطی که بعدش چی بشه نه ؟‌رقصاگر شما کرونا ویروس را &quot;با چکش بزنید&quot;. در عرض چند هفته آنرا کنترل کرده اید و قطعا در شرایط بهتری برای ادامه مبارزه با آن هستید. حال به تلاش بلند مدت برای مدیریت ویروس تا زمان آماده شدن واکسن میرسیم.مرحله رقص: پایین نگاه داشتن R کمتر از ۱، انجام تست و پیگیری بیماران، جلوگیری از اجتماعات بزرگ، بیشتر ممنوعیت های برداشته خواهد شد و زمانی که لازم باشد بیشتر خواهد شد.احتمالا بزرگترین و مهمترین اشتباهی که در این مرحله افراد خواهند کرد این است که باید چند ماه در خانه بمانند. موضوع واقعا این نیست در واقع به احتمال زیاد زندگی های ما تا حد زیادی در این مرحله به شرایط عادی نزدیک خواهد شد.مرحله رقص در کشورهای موفقچطور میشه که کره جنوبی، سنگاپور، تایوان و ژاپن برای مدت زیادی این ویروس را دارند، در حقیقت کره هزاران مبتلا دارد ولی هنوز به مرحله Lock Down نرسیده اند ؟ https://www.bbc.com/news/av/world-asia-51897979/coronavirus-south-korea-seeing-a-stabilising-trend در این ویدیو وزیر امور خارجه کره توضیح میدهد چطور کشورش اینکار را انجام داده است. خیلی ساده! با تست و پیگیری کارآمد، ممنوعیت مسافرت، قرنطینه و جداسازی کارآمد بیماران !این مقاله هم روش سنگاپور را توضیح میدهد : https://academic.oup.com/jtm/advance-article/doi/10.1093/jtm/taaa039/5804843 می خواهید اقدامات آنها را حدس بزنید ؟‌ دقیقا مشابه کره جنوبی در مورد سنگاپور به افراد داخل قرنطینه و افرادی که  عدم اجازه مسافرت داشتند کمک اقتصادی هم کرده اند.آیا برای کشورهای دیگر دیر شده است ؟ نه یا اعمال چکش شما شانس جدیدی خواهید داشت !رقص پارامتر R من به دوره بین چکش و واکسن رقص میگم! چون در این بازه اقدامات یک چیز ثابت و مشخص نیستند. بعضی مناطق بازهم ممکن است با همه گیری مواجه شوند و برخی تا مدت طولانی همه گیری جدیدی را تجربه نکنند. بسته به شرایط میتوانیم شرایط فاصله گیری اجتماعی را سختگیرانه تر کنیم و یا این محدودیت ها را برداریم. این رقص پارامتر R است: رقصی از اقدامات بین اینکه به زندگی عادی برگردیم و جلوگیری از انتشار بیماری، رقصی بین اقتصاد و سلامتی خوب این رقص چطور انجام میشه ‌؟خوب کل این رقص دور پارامتر R میچرخه. اگر یادتون بیاد R نرخ انتقال بیماریه، عددی که اگه یادتون بیاد تو سناریو کشور آمریکا ( اگه کاری انجام ندیم‌) عددی بین ۲ تا ۳ داشت. در هفته های اول اگر کسی مبتلا بشه بین ۲ تا ۳ نر جدید رو به طور متوسط مبتلا میکنه.اگر این عدد بزرگتر از ۱ باشه بیماری به صورت نمایی تا یک اپیدمی رشد پیدا میکنه و اگر زیر یک باشه کم کم از بین میره.در دوره چکش هدف نزدیک کردن این عدد به صفر در کوتاه ترین زمان ممکن برای کنترل اپیدمی هست. برای مثال در ووهان این عدد در ابتدا ۳.۹ بوده و برا شروع LockDown و قرنطینه مرکزی بیماران تا عدد ۰.۳۲ کاهش یافت.ولی هنگامی که وارد منطقه رقص می شویم فقط کافیه این عدد زیر ۱ قرار بگیره !این نمودار مثال حدودی از نحوه جواب بدن انواع مختلف بیماران به ویروس هست و همینطور میزان انتقال بیماری آنها در این بازه زمانی، در حال حاضر هیچکس شکل دقیق این نمودار را به طور واقعی نمی داند و نمودار پایین بر اساس اطلاعات مقالات مختلف رسم شده است.به نظر میرسه، بعضی ها در فاز بدون علایم نیز بیماری را منتقل می کنند، بعد از آن علایم شروع میشود و افراد پیش دکتر خود رفته و بیماری آنها تشخیص داده می شود و میزان انتقال در آنها کاهش میاید.برای مثال در ابتدا که شما مبتلا هستید ولی علایمی ندارید. پس عادی رفتار میکنید، وقتی حرف میزنید بیماری را منتقل میکنید، به بینی خود دست میزنید و سپس به دستگیره و افرادی که بعداز شما به آن دست میزنند نیز آلوده می شوند.هرچه ویروس بیشتر شمارا مبتلا میکند، شما بیشتر ناقل خواهید بود و هنگامی که شروع به نشان دادن علایم می کنید به آرامی دیگر سرکار نمیروید، خانه میمانید و استراحت میکنید و یا پیش دکتر خود می روید. وقتی که بستری میشوید با وجود اینکه خیلی احتمال انتقال در شما بالاست ولی ویروس را پخش نمی کنید چون شما را ایزوله کرده اند.اینجاست که اثر تست های فراوان گرفته شده از افراد خود را نشان میدهند: اگر افراد تست شوند، اونها قبل از اینکه علایم نشان بدهند تست میشوند و در صورت مثبت بودن قرنطینه میشوند و دیگر بیماری را منتقل نمی کنند.اگر افراد آموزش داده شوند که علایم خود را جلوتر شناسایی کنند، تعداد روزهای که در محدوده انتقال میمانند کمتر میشوند اگر افراد به محض داشتن علایم ایزوله شوند، احتمال واگیر انها از فاز نارنجی (ناحیه دارای علامت) محو میشود.اگر افراد آموزش داده شوند، در تمام دوره مریضی تعداد افراد کمتری را مبتلا میکنند.نرخ بازگشت سرمایه فاصله گیری اجتماعی اگر در اعمال تمامی این محدودیت ها بازهم مقدارR بیشتر از ۱ باشد، لازم خواهد بود تعداد افرادی که هر شخص با آنها در تماس هستند کاهش پیدا کند. برخی از آنها ارزانترند بطور مثال از افراد خواسته شود در منزل کار کنند و برخی از آنها پر هزینه ترند مانند بستن مدارس و دانشگاه ها و خواستن از افراد برای باقی ماندن در خانه و بستن رستورانها و مغازه هااین نمودار با اعداد فرضی ایجاد شده است چون تا به امروز هیچ کس به اندازه کافی در این مورد تحقیق نکرده است و یا همه اقدامات پیشگیرانه را در کنار هم مقایسه نکرده است.خیلی حیف، چون این مهمترین نموداری است که سیاستمداران نیاردارند تا بر اساس آن تصمیم گیری کنند.نتیجه گیری : برامون زمان بخرید کرونا ویروس تقریبا همه جا منتشر شده است، تا الان ۱۵۲ کشور ماردی رو اعلام کرده اند و زمان بر علیه ماست ولی نیازی نیست که اینطور باشه!‌ یک راه روشن و مشخص برای برون رفت از این شرایط وجود دارهبرخی از کشورها خصوصا آنهایی که هنوز به شدت دچار بیماری نشده اند شاید فکر کنند آیا برای ما هم اتفاق میافته ؟ جواب اینه که احتمالا شما همین الانم حسابی مبتلا هستید و هنوز اطلاع ندارید. وقتی که به اون معنی کلمه مبتلا بشید، سیستم درمانی شما در شرایط خیلی بدتری از کشورهای پولدار خواهد بود. بهتره زودتر اقدام کنید، سالم بودن بهتر از پشیمان بودن است برای کشورهایی که الان درگیر هستن هم که گزینه روشنهدر یک سمت کشورهایی که با استراتژی کاهش شیب نمودار (mitigation) جلو میروند یک اپیدمی بزرگ را ایجاد می کنند و سیستم درمانی خودشون را از کار می اندازند و باعث مرگ میلیونها نفر می شوند و گونه های جهش یافته جدیدی از ویروس رو به دنیا تقدیم می کنند.در سمت دیگر کشورهایی که برای چندهفته Lock-Down انجام می دهند و برای ما زمان می خرند و یک برنامه اجرایی مشخص برای کنترل ویروس تا زمان پیدا شدن واکسن تهیه می کنند.برخی از کشورها مثل آمریکا، انگلستان، سوییس وهلند استراتژی mitigation رو پیش گرفته اند واین یعنی که آنها دارند بدون جنگیدن از اینکار منصرف می شوند، با وجودی که میبینند کشورهای دیگری با موفقیت اینکار را انجام داده اند میگویند ما نمی توانیم انجامش بدیم !فکر کنید چرچیل میگفت، نازی ها همه جای اروپا هستند، نمیتونیم باهاشون بجنگیم، ولش کنیم! این کاریه که خیلی از کشورها امروز دارند انجام می دهند.آنها شانسی برای جنگیدن بهتون نمی دهند خودتون باید اون رو درخواست کنید !</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Sat, 21 Mar 2020 20:39:31 +0430</pubDate>
            </item>
                    <item>
                <title>معرفی سیستم های Caching و استفاده آنها در آپارات</title>
                <link>https://aparat.design/introducing-caching-for-database-zzwfdqyuiyim</link>
                <description>در این پست می خواهیم درباره اینکه سیستم های caching چی هستند و ما چطور از آنها در طراحی سیستم های نرم افزاری استفاده می کنیم صحبت کنیم و در انتهای این مطلب می تونیم انتظار داشته باشیم که بدونیمcache چی هست و در چه شرایطی از اون میشه استفاده کرد.معماری های سه لایه مدلی است که توسط بسیاری از توسعه دهنده های برای تولید نرم افزارهای قابل انعطاف و قابل گسترش استفاده می شوند این معماری شامل ۳ لایه ی زیر هستند :Presentation Tier (User Interface)لایه ای که کاربر با اون در حال تعامل هست این لایه دستورات و نتایج اون رو از سرور به چیزی که کاربر متوجه میشه ترجمه می کنهApplication Tier (Business Logic)این لایه هماهنگ کننده نرم افزار هست، به عبارت دیگه این لایه دستورات و درخواست های کاربر رو بررسی میکنه و تصمیمات منطقی رو میگیره و داده رو بین لایه User Interface و بانک اطلاعاتی منتقل می کنه.Data Tier (Database and File Storage)این لایه هم جایی هست که همه اطلاعات در ذخیره می شوند.این لایه های معمولا به صورت مستقل از هم کار میکنند و به صورت مستقل از هم نیز نگهداری میشوند و در بیشتر موارد هر کدوم از این لایه ها بروی یک ماشین (Host) مجزا قرار دارند. پس هر بار که لایه Application درخواستی برای دریافت اطلاعات میفرسته سرعت این عملیات به عملکرد شبکه بین این ماشین ها محدود خواهد شد و البته میدونیم که مدت زمان مورد نیاز برای دریافت اطلاعات و نمایش اون نقش مهمی در تجربه کاربر از یک سرویس رو داره و عموماً جزو نیازهای اساسی هر کسب و کار آنلاینی هست.کَش و دلایل استفاده از اون چیه ؟ برای اینکه مثال ما مصداقی تر باشه یک مثال از این پروسه رو روی آپارات بررسی می کنیم. فرض کنید یک کاربر به صفحه اول آپارات در حالتی که Recommendation خاموش هست مراجعه میکنه و برای نمایش اطلاعات صفحه اول لایه Application نیازمند تعداد انجام تعدادمشخصی از query ها به بانک اطلاعاتی برای دریافت این اطلاعات هست و این یعنی به ازای هر بارگذاری  این صفحه (که تقریبا  چندصد بار در ثانیه از سوی افراد در حال بارگذاری هست) باید یک Query یکسان به بانک اطلاعاتی ارسال بشه و این یعنی حجم عظیمی از I/O روی بانک اطلاعاتی و شبکه مربوط به اون رو مطلبه. Cache کردن یه تکنیک بافرینگه که داده هایی که به دفعات از بانک اطلاعاتی دریافت می شوند رو در یک حافظه موقتی ذخیره می کنه و این کار فشار ایجاد شدو روی بانک اطلاعاتی و مدت زمان دریافت این اطلاعات رو کاهش میده. در مثال بالا وقتی برای اولین بار این اطلاعات درخواست میشه، نتیجه این Query از بانک اطلاعاتی دریافت میشه در جایی کنار لایه Application یا خیلی نزدیکتر از جایی که لایه Data قرارداره ذخیره میشه و در درخواست های بعدی این اطلاعات از اون حافظه موقتی یا Cache به لایه Application ارسال می شوند.به طور کلی مزایایی استفاده از Cache شامل موارد ذیل هستند: بهبود عملکرد : وقتی داده مورد نیاز لایه Application از طریق Cache راحتتر قابل دسترس باشه فشار روی بانک اطلاعاتی کاهش پیدا میکنه و به این شکل عملکرد نرم افزار بهبود پیدا میکنهمقیاس پذیری: با تقسیم کردن بار درخواستهای داده بروی یک سیستم کشینگ توزیع شده با هزینه پایین تر و انعطاف پذیری بیشتر مقیاس پذیری سیستم افزایش پیدا می کنه.بهبود دسترسی: به واسطه وجود Cache در سیستم حتی هنگامی که سرور بانکهای اطلاعاتی در دسترس نباشند، Cache می تواند سرویس پیوسته سیستم را تا زمانی که سرورها به مدار بازگردانده شوند رو فراهم کنند و این ترتیب سیستم نسبت به خرابی مقاوم تر خواهد بود.خب الان که با مزیت های Cache آشنا شدید شاید با خودتون بگید خوبه همه چیز رو روی اون نگهداری کنیم تا سرعت اجرای سایت بالاتر بره ! خوب این تا حدی درست هست اما چند مورد هست که استفاده از کش رو محدود میکنه. سخت افزارهایی که برای لایه Cache استفاده می شوند معمولا نسبت به سخت افزارهای مورد استفاده در بانک های اطلاعاتی گرون تر هستند اگر اطلاعات خیلی زیادی رو روی Cache ذخیره کنید بسته به نوع بستری که برای Cache استفاده می کنید مدت زمان مورد نیاز برای جستجوی اون کلید افزایش پیدا میکنه و به مرور ممکنه به جایی برسید که بانک اطلاعاتی از لایه Cache سریعتر عمل کنه و عملا نقض غرض کنه.خوب با در نظر گرفتن محدودیت های فوق زمانی که می خواهیم انتخاب کنیم که از Cache چطور استفاده کنیم باید به دو سوال اساسی پاسخ بدهیمکی می خواهم اطلاعاتی رو وارد cache کنم ؟‌کی می خواهم اطلاعاتی رو از cache خارج کنم ؟‌به مجموع این دو سوال به اصطلاح Cache Policy گفته می شود و Policy های استاندارد مختلفی در اینباره وجود دارند که از آنها می توان به LRU و LIFO اشاره کرد. در این لینک می توانید درباره این Policy های مختلف بیشتر مطالعه کنید. https://en.wikipedia.org/wiki/Cache_replacement_policies معایب استفاده از Cache یا بهتر بگیم Cache Policy اشتباه !تا اینجا درباره محاسن استفاده از cache در سیستم صحبت کردیم ولی پیاده سازی اشتباه اون و یا بهتر بگیم انتخاب قواعد اشتباه برای کش کردن می تونن باعث ایجاد مشکلات زیر بشوند :عملیات اضافه (Extra Call):فرض کنید به خاطر مدل پیاده سازی غیر صحیح cache هر بار که به اون مراجعه کنید فاقد اطلاعات لازم باشه و در این حالت باید دوباره به سراغ بانک اطلاعاتی بروید. در این حالت cache فقط یک مرحله به روال عادی شما اضافه میکنه و کار رو برای شما طولانی تر خواهد کرد.تله  Trashing:فرض کنید یک کاربر از شما می خواهد اطلاعات پروفایل خودش رو دریافت کنه و شما به اشتباه اطلاعات اون رو همیشه به یک نام ثابت و در یک محل ثابت از cache ذخیره کنید. کاربر A از شما می خواهد اطلاعات کاربری رو بهش بدید شما اون اطلاعات رو از بانک میگیرد و در cache ذخیره میکنید، به دنبال اون کاربر B میاد و از شما اطلاعات پروفایلش رو درخواست میکنه و شما دوباره اون رو در همون محل به جای اطلاعات نفر A ! در این حالت در درخواست بعدی نفر A یا اطلاعات اشتباه دریافت می کنه و یا اینکه اطلاعات رو باید دوباره از بانک دریافت کنه !مشکل Consistency یا ثبات اطلاعات: این شاید واضحترین مشکل caching باشه، وقتی اطلاعات رو از بانک اطلاعاتی می خونید و داخل cache قرار بدیم و اون اطلاعات در بانک اطلاعاتی به هر ترتیب تغییر کنند یا حذف شوند cache به نسخه قدیمی اون اطلاعات اشاره دارد، در نتیجه موارد مهم در تعیین استراتژی کشینگ تعیین رویه بروز رسانی اطلاعات در cache خواهد بود.استراتژی های Caching استراتژی caching به معنی تعیین ارتباط بین منبع اطلاعات ( بانک اطلاعاتی ) و سیستم caching و اینکه اطلاعات کش به چه شکل قابل دسترسی  هستند، می باشد. استراتژی های مختلفی در مورد نحوه کش کردن وجود دارند و انتخاب هریک از آنها تاثیر متفاوتی بر طراحی سیستم و کارآیی آن دارند. پس همیشه قبل از طراحی معماری بهتر است یکبار مسیر دریافت اطلاعات در نرم افزار خود را بررسی کنید با بتوانید انتخاب کنید کدامیک از این استراتژی ها بهتر برای شما کار میکند در ادامه برخی از معروفترین و پر استفاده ترین استراتژی ها رو با هم بررسی می کنیم.استراتژی Cache Asideدر این استراتژی کش در کنار بانک اطلاعاتی قرار میگیرد، در نتیجه Application اول درخواست دریافت اطلاعات رو برای کش ارسال میکند (Cache hit) و اگر این اطلاعات در کش وجود داشته باشد، نرم افزار مستقیما این اطلاعات رو دریافت خواهد کرد، در غیر این صورت (cache miss) برنامه دریافت اطلاعات رو برای بانک اطلاعاتی فرستاده و نتیجه رو برای cache هم ذخیره خواهد کرد تا در دفعات بعدی از این اطلاعات استفاده شود.Cache Aside Strategyاستراتژی Read Throughدر این روش بر خلاف روش پیش، کش بین Application و Database قرار خواهد گرفت و نرم افزار همیشه فقط اطلاعات رو از کش درخواست خواهد کرد، در نتیجه هنگامی که یک cache miss اتفاق بیافتد، cache مسوؤل دریافت اطلاعات از بانک اطلاعاتی بروز رسانی اطلاعات خود و ارسال آن برای Application خواهد بودRead Through Strategyاستراتژی Write Throughمشابه روش Read Through در این روش نیز کش بین Application و بانک اطلاعاتی قرار میگیرد و هر درخواست نوشتن اطلاعات بروی بانک باید از طریق cache به سمت بانک اطلاعاتی ارسال شود به عبارت دیگر کش اول اطلاعات را بروی خود بروز رسانی کرده و در ادامه این اطلاعات را بروی بانک اطلاعاتی می نویسد.Write Through Strategyاستراتژی Write Backاین روش تنظیماتی مشابه با روش Write through دارد، دراین روش Application اطلاعات رو بروی cache ذخیره سازی می کند، اما یک وقفه زمانی بین نوشتن اطلاعات از cache به بانک اطلاعاتی وجود دارد. بطور مثال cache در بازه های زمانی ثابت یا متغیر اقدام به نوشتن اطلاعات بروی بانک اطلاعاتی خواهد کرد.Write Back Strategyاستراتژی Write Aroundاین استراتژی به طور معمول با روش cache aside یا read through به صورت ترکیب شده استفاده می شود در این روش Application همیشه اطلاعات را بروی بانک اطلاعاتی به صورت مستقیم می نویسد ولی اطلاعات فقط در زمان خوانده شدن از بانک اطلاعاتی بروی کش نوشته می شوند.مقایسه مزایا و معایب استراتژی های مختلفمحاسن روش Cache Asideهنگامی که بانک اطلاعاتی در دسترس نباشد می تواند به عملیات خود ادامه دهدپیاده سازی ساده ای داردمدل داده (Data Model) بین لایه دیتابیس و کش می تواند با هم متفاوت باشنداین مدل در فشارهای بالای خواندن اطلاعات بهترین عملکرد را داردمعایب روش Cache Asideعدم تطابق اطلاعات بین بانک اطلاعاتی و کش وجود خواهد داشتهمیشه برای اولین بار با Cache miss مواجه خواهیم شد و باعث ایجاد latency خواهد شد.محاسن روش Read Throughبه دلیل عدم ارتباط مستقیم Application با بانک اطلاعات کد آن ساده تر و قابل خواندن تر است.بهترین روش برای حالتیست که یه مجموع از اطلاعات به صورت مداوم درخواست می شود.معایب روش Read Throughنیاز به برنامه نویسی پلاگین های cache پیچیده تری برای دریافت اطلاعات از Database.همیشه برای اولین بار با Cache miss مواجه خواهیم شد و باعث ایجاد latency خواهد شد.محاسن روش Write Throughاطلاعات همیشه در cache وجود دارند و با نتیجه cache miss مواجه نخواهیم شد.اگر با استراتژی Read Through به صورت همزمان استفاده شود می تواند تضمین کند که همیشه اطلاعات کش با بانک اطلاعاتی بروز هستندمعایب روش Write Throughباعث افزایش مدت زمان عملیات نوشتن در بانک اطلاعاتی خواهد شد.محاسن روش Write ‌Backمناسب برای نوشتن اطلاعات با نرخ بالاسازگاری نسبی با خطاهای دسترسی بانک اطلاعاتیکاهش فشار روی بانک با کاهش تعداد عملیات های نوشتن بروی بانک اطلاعاتیمعایب روش Write Backریسک از بین رفتن اطلاعات در صورت از دست رفتن (پایین رفتن) سرویس cache</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Wed, 23 Oct 2019 12:27:29 +0330</pubDate>
            </item>
                    <item>
                <title>پیام‌رسان NATS با هسته‌ قوی و به شکلی باورنکردنی سریع!</title>
                <link>https://aparat.design/پیامرسان-nats-با-هسته-قوی-و-به-شکلی-باورنکردنی-سریع-piwflvsm2dbr</link>
                <description>آپارات سرویسی که به صورت چند وجهی در حال رشد است، برای پاسخ به نیازهای روز افزون سرویس خود نیاز به راهکارهای به روز و پیچیده تر دارد. یکی از راهکارهایی که تیم فنی آپارات در پیش گرفته ایجاد بستری برای کار در محیط cloud است. وقتی نرم‌افزاری را برای محیط cloud طراحی می‌کنیم، معمولا انرژی زیادی صرف می‌شود تا پروژه مونولیت (Monolith) را به میکروسرویس‌های کانتینر بیس متعددی بشکنیم با این شرط که از قاعده ۱۲ فاکتوری نرم‌افزارهای ابری تبعیت کند یعنی به زبان ساده ارتباط موثر و سریعی بین بخش ها یا سرورهای این شبکه برقرار باشد.در این شرایط بیشترین زمان صرف نحوه پیاده‌سازی Code Base می‌شود اما اغلب تیم‌ها ساختار و طراحی پیام‌رسانی(Messaging) را به بعد موکول می‌کنند در حالی که پیام‌رسانی، سیستم عصبی مرکزی نرم‌افزارهای بزرگی است که از ساختار توزیع شده و مدرن بهره می‌برند. صرف‌نظر از اینکه ما از الگوی Event Sourcing  یا از مدل Work Dispatch استفاده ‌کنیم، Messaging نخ تسبیح تمام میکروسرویس‌ها است که باعث عملکرد صحیح کل سیستم می‌شود و بدون آن، سیستم توزیع‌شده ما محکوم به شکست خواهد بود. بنابراین در راستای ایجاد ساختار Messaging آنچه تیم فنی آپارات پشت سر گذاشته را در ادامه می خوانیم.چطور یک Message Broker یا Messaging Architecture را برای نرم‌افزارمان انتخاب کنیم؟با توجه به انتخاب‌های متعددی که پیش رو داریم و هر روز امکان انتخاب‌های جدید مثل قارچ رشد می‌کند، این کار در بسیاری از موارد سخت می‌شود.در دسته‌بندی از لحاظ بزرگی و پیچیدگی ما با Kafka روبرو هستیم.استفاده از Kafkaاز Kafka اغلب به عنوان یک Log Store توزیع‌یافته یاد می‌شود. معمولا فرض می‌کنیم پیام‌هایی که به یک Topic خاص منتشر می‌شود در کافکا برای مدت مشخصی نگهداری شده و مفهوم Consumer Group به پیام‌ها اجازه می‌دهد تا به صورت متوازن بین Instance‌های آن سرویس پخش شوند. کافکا سرویس بسیار قدرتمندی است، اما قدرت با خودش مسئولیت هم به همراه می‌آورد! نگهداری از کافکا سخت است و معمولا یادگیری آن برای تیم‌هایی که بخواهند به این تکنولوژی مسلط باشند، پر زحمت و زمان‌بر است.استفاده از RabbitMQاز طرف دیگر RabbitMQ یا هر بروکر ‌دیگری که از پرتوکل AMQO تبعیت می‌کند یکی از انتخاب‌های پرطرفدار  برنامه‌نویس‌هاست. RabbitMQ به نسبت سبکتر بوده و به جای استفاده از کانسپت گروه مصرف‌کننده یونیک(unique consumer groups) راه‌حل ساده‌تری را دنبال می‌کند؛ به این صورت که وظیفه مصرف کردن پیام‌های صف را به کلاینت‌ها محول می‌کند. اگر یک کلاینت اعلام دریافت یک پیام را انجام ندهد،  آن پیام در صف برگردانده شده تا توسط یک کلاینت دیگر پروسس شود. البته این روش ظرافت‌های استفاده خود را هم در‌پی‌دارد. مواردی مثل فاصله زمانی کوتاه که ممکن است در آن‌ها دو Worker یک پیام را دریافت کنند(دو بار یک درخواست بررسی شود) و موارد دیگری از این دست!استفاده از Redisنرم‌افزارهای مثل Redis که خود را به عنوان یک Message Broker معرفی نمی‌کنند هم از الگوی pub/sub پشتیبانی می‌کنند. همینطور که می‌بیند لیست محصولات و سرویس‌هایی که الگوی Meessage Brokering را ارایه می‌دهند بزرگ و متعدد است. هر کدام از این نرم‌افزارها نقاط و حوزه‌های قوت و ضعف خودشان را دارند.کافکا قدرتش را در رقابت با سیستم‌هایی با مقیاس بزرگ و سناریوهای تجمیعی از طریق persistent message logs نشان می‌دهد.اما Rabbit در محیط‌هایی که به عملکرد ساده‌تر pub/sub نیاز داریم بهتر عمل می‌کند و Redis هم ممکن است برای شرایطی که تمامی کلاینت‌های شما برای Cache از قبل با Redis در تماس باشند و شما نیازی که به نگهداری پیام‌ها نداشته باشید، انتخاب خوبی باشد.اگر واقعا بخواهیم ایده &quot;سیستم عصبی مرکزی&quot; را به معنی واقعی پیاده کنیم و نخواهیم overhead راهکارهای دیگر را تحمل کنیم، آن وقت راه بهینه چیست‌؟اگر بخواهیم به جز روش سنتی pub/sub روش‌هایی مثل request/reply و حتی رویه scatter-gather را خیلی سبک و ساده پیاده‌سازی کنیم، NATS ممکن است پیشنهاد بهتری باشه!خوب NATS یک نرم‌افزار متن‌باز با یک هسته قوی و ساده، به شکلی باورنکردنی سریع! این دلال پیام از پروتوکل متن محور استفاده می‌کند، که شما به راحتی می‌توانید با &#x60;telnet&#x60; به یک سرور NATS متصل شده و پیام‌ها را ارسال یا دریافت کنید. NATS به گونه‌ای طراحی و پیاده‌سازی شده که دایم به کار، متصل و همیشه آماده دریافت دستورات باشد.(منبع: bravenewgeek.com/dissecting-message-queues)برای اینکه بهتر موضوع را درک کنید، بیاید چند مورد استفاده معمول را باهم بررسی کنیم:الگوهای پیام رسانی :سه الگوی پیام‌رسانی توسط NATS پشتیبانی می‌شود، در حالی که در اصل به عنوان یک موتور publish-subscribe عمل می‌کند.Publish-SubscribeRequest-ReplyQueue Groupingاجزای معماری پیام رسانی :اینها لیستی از کامپوننت‌های اصلی زیر ساخت NATS هستند:‌پیام (Message):  پیام‌ها واحدهای انتقال داده هستند، پیام‌های Payload هایی هستند که برای انتقال داده بین اپلیکشن‌ها استفاده می‌شوند.موضوع (Subject): موضوع مقصد پیام‌ها را مشخص می‌کند.تولیدکننده (Producer): تولیدکننده‌ها پیام‌ها را به NATS سرور ارسال می‌کنند.مصرف‌کننده (Consumer): مصرف‌کننده‌ها پیام ها را از NATS سرور دریافت می‌کنند.سرور (Messaging Server): سرور پیام‌ها را از تولیدکننده‌ها به مصرف کننده‌ها می‌رساند.الگو Publish-Subscribe :در ساده‌ترین مدل pub-sub شما یک تولید‌کننده دارید که  پیامی را به یک موضوع (subject یا topic) مشخص ارسال می‌کند و هر کلاینتی که به پیام‌های آن موضوع مشخص علاقه داشته باشد را به آن موضوع خاص subscribe می‌کند. در اینجا NATS تضمین می‌کند که هر پیام به هر مشترک فقط یکبار ارسال شود به عبارت دیگر NATS تضمین می‌کند پیام‎ها به ترتیب ارسال، برای کلاینت‌ها ارسال شود ولی ترتیب دریافت توسط کلاینت‌ها مختلط را تضمین نمی‌کند به عبارت دیگر اگر در یک ارسال، کلاینت‌ها به ترتیب ۱-۳-۴، پیام‌ها را دریافت کنند، در ارسال بعدی این ترتیب تضمین نمی‌شود.در مقایسه NATS در این حوزه با دیگر رقبا باید به این موضوع اشاره کرد که در Kafka و یا Rabbit شما باید topic را قبل از اینکه سرویس‌ها شروع به کار کنند، بسازید در حالی که در Redis و NATS به ترتیب Channel و Subject به صورت on-fly ساخته می‌شوند و نیازی به پیش تعریف آنها نیست. همین قابلیت ساخت موضوعات به صورت on-fly سنگ بنای الگوی request-reply در NATS است.برای تست کردن این الگو به آدرس زیر مراجعه کنید :‌https://github.com/nats-io/go-nats-examples/tree/master/patterns/publish-subscribeالگو Request-Reply :یک سرویس RESTful را در نظر بگیرید، وقتی که ما یک درخواست HTTP را برای یک سرویس ارسال می‌کنیم از سرویس هم یک پاسخ دریافت می‌کنیم در این حالت ما از الگوی سنتی request-reply همگام استفاده می‌کنیم.در بسیاری از سیستم‌های Messaging پیاده‌سازی الگوی request-reply بسیار مشکل بوده و یا پیاده‌سازی آنها نیازمند توافقات عجیب و غریبی است. در حالی که در NATS پیاده‌سازی این الگو به سادگی اعلام یک subject به عنوان reply-to در زمان ارسال یک پیام است.مراحلی که به ترتیب در یک سناریو نمایش لیست ویدیوهای یک شخص خاص بر مبنای الگوی Request-Reply اتفاق می‌افتندُ به شرح ذیل است:منتشرکننده (Publisher) برای یک موضوع مشخص به طور مثال myvideos.reply ثبت نام می‌کند.منتشر‌کننده یک پیام برای موضوع myvideos.inquiry ارسال می‌کند و در این پیام نام موضوع reply-to را myvideos.reply قرار می‌دهد.منتشرکننده برای مدت زمانی مشخص response timeout منتظر دریافت یک پیام برروی موضوع myvideos.reply باقی می‌ماند.منتشرکننده از موضوع myvideos.reply ثبت نام خود را لغو می‌کند یا (unsubscribe‌) می‌کند.منتشر کننده پاسخ ارسالی را بررسی و پردازش می‌کند.در اینجا NATS برای اینکه بتواند چندین درخواست همزمان را بررسی کند و مطمئن شود که کد نوشته شده پاسخ درخواست را تنها به همان درخواست کننده مشخص ارسال نماید، اغلب به انتهای موضوع reply-to یک رشته متن تصادفی GUID اضافه می‌نماید. به طور مثال reply-to: myvideos.reply.78707692-c45b-4711-a721-49e13f90308d خواهد بود. البته معمولا این پیچیدگی‌ها توسط client های هریک از زبان‌های برنامه‌نویسی انجام می‌شود و به طور مثال در زبان GO کد شما به این شکل خواهد بود.import nats &quot;github.com/nats-io/nats.go&quot;

// Connect to a server
nc, _ := nats.Connect(nats.DefaultURL)
// Requests
msg, err := nc.Request(&quot;myvideos.inquiry&quot;, []byte(&quot;help me&quot;), 100*time.Millisecond)
// Replies
nc.Subscribe(&quot;myvideos.inquiry&quot;, func(m *Msg) {
    nc.Publish(m.Reply, []byte(&quot;I can help!&quot;))
})در این نمونه کد یک درخواست مطابق رویه بالا ارسال شده و برای مدت ۱۰۰ میلی‌ثانیه منتظر پاسخ باقی می‌ماند. در این کتابخانه زبان GO اطلاعات reply-to را از دید برنامه‌نویس مخفی کرده است. در این کد همچنان بخش subscribe و unsubscribe کردن از reply-to نیز مخفی شده است و خود کلاینت این عملیات را در پشت صحنه انجام می‌دهد.برای تست کردن این الگو به آدرس زیر مراجعه کنید :‌https://github.com/nats-io/go-nats-examples/tree/master/patterns/request-reply الگو Queue grouping :نتس (NATS) به صورت built-in از یک توزیع‌کننده بار داخلی به نام distributed queues بهره می‌برد. با استفاده از این نوع از subscriber ها به صورت خودکار توزیع پیام‌ها را بین subscriber های عضو یک گروه مشخص انجام می‌دهد.برای ساخت یک queue group هریک از کلاینت‌ها باید یک نام‌گروه مشخص را ثبت‌نام کرده و روی یک موضوع عملیات انجام دهند. همه کلاینت‌هایی که نام گروه مشترکی دارندُ با هم تشکیل یک گروه می‌دهند. این کار به جز نام‌گروه همسانُ به هیچ تنظیماتی نیاز ندارد. حال هنگامی که یک پیام برای آن موضوع منتشر می‌شودُ یکی از اعضای گروه به صورت تصادفی انتخاب شده و پیام را دریافت می‌کند. به عبارت دیگر با اینکه همه اعضای گروه در حال گوش کردن به آن موضوع خاص هستند، فقط و فقط یکی از اعضا آن پیام را دریافت یا به عبارتی پردازش می‌کند. این الگو ایده‌آل‌ترین الگو برای scale کردن میکروسرویس‌ها می‌باشد. در این روش scale-up کردن سیستم به سادگی اجرا کردن یک application دیگر و scale-down کردن به سادگی terminate کردن یکی از application ها است.این انعطاف‌پذیری و حداقل تنظیمات لازم NATS را به یکی از بهترین تکنولوژی‌ها برای ارتباط بین میکروسرویس‌ها تبدیل کرده است.import nats &quot;github.com/nats-io/nats.go&quot;

// Connect to a server
nc, _ := nats.Connect(nats.DefaultURL)

// Simple Publisher
nc.Publish(&quot;foo&quot;, []byte(&quot;Hello World&quot;))

// All subscriptions with the same queue name will form a queue group.
// Each message will be delivered to only one subscriber per queue group,
// using queuing semantics. You can have as many queue groups as you wish.
// Normal subscribers will continue to work as expected.

nc.QueueSubscribe(&quot;foo&quot;, &quot;job_workers&quot;, func(_ *Msg) {
  received += 1;
})

// Drain connection (Preferred for responders)
// Close() not needed if this is called.
nc.Drain()

// Close connection
nc.Close()برای تست کردن این الگو به آدرس زیر مراجعه کنید :‌https://github.com/nats-io/go-nats-examples/tree/master/patterns/competing-consumerکلام آخر چیزی که NATS را قدرتمند می‌کند پیچیدگی نیست،‌ بلکه سادگی است.در واقع استفاده از پروتوکل ساده در زیرساخت، توجه به سادگی و کارایی بالا و قابل اتکا بودن در cloud-native در NATS ما را قادر می‌سازد انواع الگوهای پیام‌رسانی قدرتمند را بدون از دست‌دادن امکانات مهم در کنار بسیاری از امکاناتی بدون استفاده در نرم افزارهای بزرگتر در برنامه ها پیاده‌سازی کنیم.برای آشنایی بیشتر با نحوه استفاده از NATS در زبان Go می توانید به آدرس زیر مراجعه کنید در این منبع Github که متعلق به NATS میباشد انواع الگوهای استفاده از این Message Broker توضیح داده شده است. https://github.com/nats-io/go-nats-examples/tree/master/tools نکته: یکی از مسایلی که باید در استفاده از NATS در نظر بگیریم بحث ماندگاری یا persistency در پیام‌هاست که NATS به تنهایی این قابلیت را ندارد و این امکان را از طریق یک نرم‌افزار دیگر به نام NATS Streaming انجام می‌دهد. این موضوع را در یک مطلب دیگر به صورت مجزا به زودی بررسی خواهیم کرد.</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Sun, 28 Jul 2019 16:31:11 +0430</pubDate>
            </item>
                    <item>
                <title>نظارت بر کارایی فرآیندهای نرم‌افزاری یا APM چیست؟</title>
                <link>https://aparat.design/what-is-apm-lrgt4a5z77so</link>
                <description>در دنیای نرم‌افزارها و برنامه‌های تحت وب امروز اگر بخواهید، وب اپلیکیشن به شکل روان، با کمترین مشکل و با یک سرعت مناسب اجرا شود، مونیتور‌کردن سرورها و زیرساخت‌های شبکه در مقیاس‌های بزرگ خیلی مهم می‌شود و اینکه چه سطحی از نظارت بر عملکردها برای اطمینان از اینکه سرویس همیشه در دسترس باشد لازم است؟ برای ما در آپارات مطمئن شدن از این موضوع که تمام بخش‌های حیاتی سرویس به بهترین شکل در حال کار باشند و کاربرهایمان خدمات ما را سریع و روان دریافت کنند در اولیت شماره یک قرار دارد!! تعریفی برای APM یا Application Performance Monitoring نظارت بر کارایی فرآیندهای نرم‌افزاری (Application Performance Monitoting) یکی از روش‌هایی است که در سرویس‌ها و میکروسرویس‌های مختلف آنلاین برای نظارت نحوه اجرایی فرآیندهای سیستم مورد استفاده قرارمی‌گیرد.به طور مثال صفحه اول آپارات را در نظر بگیرید:وقتی این صفحه از سمت یکی از کاربران ما بارگذاری می‌شود، بخش‌های مختلفی مانند MySQL Query ها، Cache Server ها ، عملیات‌های متعدد Redis و سرویس‌های Recommender که قسمتی از رویه‌های اجرایی برای نمایش صفحه اول سایت است، به صورت موازی و متوالی در &quot;سورس کد&quot; سایت اجرا می‌شوند. اما اینکه هر کدام از این بخش‌ها چه مقدار زمان برای اجرا شدن لازم دارند و چه اطلاعاتی در هرکدام از این مراحل در حال انتقال است، در حالت عادی برای توسعه‌دهنده مشخص نیست و یا دریافتشان نیازمند ابزار مخصوص به خود است. بنابراین در پی تغییرات اخیر در Code Base سرویس آپارات تصمیم گرفتیم که برای نظارت بر اجرای این عملکردها APM را به شکل صحیح و قابل اتکا پیاده‌سازی کنیم. برای این کار سراغ سرویس‌دهنده‌های مختلف که به صورت SaaS یا Self-Hosted در دنیای نرم‌افزار وجود دارند رفته و با بررسی مزایا و معایب آن‌ها سرویس Elastic APM را انتخاب کردیم. که در این مطلب می‌خواهم این تجربه را با شما در میان بگذارم.سرویس Elastic APM در حال حاضر خیلی از شرکت‌ها  از مجموع سرویس‌های “Elastic”  برای نگهداری لاگ‌ها و متریک‌های سیستم استفاده می‌کنند که در آن باید برای تحلیل و ردیابی مسايل به جستجو بپردازیم و کمتر مجموعه ای به سراغ سرویس Elastic APM می‌روند اما باید گفت APM این امکان را به شما می‌دهد که به راحتی رویه اجرای فرآیند‌های مختلف در نرم افزار شما را مانیتور کنید. در APM یک Transaction اصلی از سرویس (برای مثال نمایش صفحه اول سرویس) به بخش‌های کوچکتری تحت عنوان Span تقسیم میشود و اطلاعات هریک از این Span ها شامل زمان شروع، زمان پایان، اطلاعات جانبی (بطور مثال SQL Query  اجرا شده) و بسیاری از اطلاعات کلی‌تر را در قالب همان Transaction ثبت و برای APM ارسال می‌کند.تصویر شماره ۱ : محیط Elastic APM همانطور که در تصویر شماره ۲ می‌بینید خروجی که Elastic APM می‌دهد شباهت بسیاری به نحوه نمایش Network Inspector در مرورگر کروم (تصویر شماره ۳) دارد، با این تفاوت که در مرورگر کروم، شما نحوه بارگذاری فایل‌ها و درخواست‌های مختلف آن صفحه را می‌بینید ولی در APM مدت زمان و اطلاعات مربوط به هریک از Span های اجرای کد را هم می‌بینید.تصویر شماره ۲:‌نمونه خروجی Elastic APM برای یک Transactionتصویر شماره ۳ : Chrome Network Inspectorدر حال حاضر با کمک این تکنولوژی ما می‌توانیم به راحتی نحوه اجرای کد مربوط به هرکدام از بخش‌ها یا Business های وب‌سایت را در شرایط مختلف بررسی کنیم و مشکلات احتمالی در ساختار کد و یا زیر ساخت‌ها و میکروسرویس‌های مختلف را قبل از اینکه کاربران با کندی و یا بدتر از آن با خطا مواجه شوند، پیدا و برطرف کنیم.چطور باید APM را پیاده‌سازی کنیم؟‌خوب تا اینجا با کلیات APM آشنا شدیم اما برای پیاده‌سازی این سرویس دو بخش کلی را باید بدانیم:بخش اول بالا آوردن خود Elastic APM است که مقالات خوبی در رابطه‌ با آن وجود دارد که چند لینک از آن‌ها را در اینجا برای شما قرار داده‌ام.۱. https://www.elastic.co/guide/en/apm/get-started/current/install-and-run.html۲. https://logz.io/blog/application-performance-monitoring/بخش دوم شامل پیاده‌سازی آن در Code Base وب‌سایت شما است. قبل از هرچیزی باید این نکته را بدانید که Elastic APM به سرعت در حال پیشرفت است و از ۳ ماه پیش دو نسخه ماژور ۶ و ۷ خود را منتشر کرده که تغییرات زیادی در ساختار ارسال اطلاعات این دو نسخه بوجود آورده است. نکته ۱ : بنابراین شما باید در زمان نصب و بالا آوردن Elastic APM و انتخاب Agent مخصوص کد به ورژنی که آن Agent را پشتیبانی می‌کند، دقت زیادی کنید.نکته ۲: زمانی که این مطلب را برای شما می‌نویسم آخرین نسخه پایدار ارايه شده نسخه ۷.۱ است ولی در هر زمان می‌توانید از طریق آدرس elastic.co به ساختار ورودی که Elastic APM API قبول می‌کند، دسترسی پیدا کنید.در حال حاضر Elastic برای چند زبان مختلف از جمله Go, Java, Node.js, Python, Ruby, RUM به صورت رسمی کتابخانه‌ی Agent منتشر کرده‌ و البته برای زبان‌های دیگر هم Community Library های مختلفی منتشر شده‌است، در این راستا ما در آپارات برای زبان PHP تنها توانستیم یک کتابخانه پیدا کنیم که آن هم متاسفانه مشکلات زیر را داشت:۱- باگ‌های مختلفی داشت.۲- از Intake API V2.0 پشتیبانی نمی‌کرد. ۳- از همه مهم‌تر ارسال اطلاعات از طریق REST Api انجام می‌شد که برای آپارات با این حجم از ترافیک، اضافه شدن زمان مجزا برای ارسال اطلاعات به زمان بارگذاری صفحه هزینه‌ی (زمان انتظار کاربر) زیادی دربرداشت.در نتیجه تصمیم گرفتیم یک کتابخانه PHP برای Elastic APM Intake API 2.0 و با پشتیبانی از ورژن ۶.۷ تا ۷.۱ به کمک تیم توسعه آپارات آماده کنیماین کتابخانه برای زبانی مثل PHP که یک Scripting Language است یک حسن بزرگ دارد، به این شکل که  می‌تواند ارسال اطلاعات به Elastic APM را هم به صورت TCP از طریق API و هم به صورت UDP از طریق یک SideCar که با زبان GoLang نوشته شده، انجام دهد.کلام آخر:این کتابخانه الان به صورت متن باز در Github و Packagist برای استفاده عموم دوستانی که از PHP در Stack خودشان استفاده می‌کنند منتشر شده است. هم اکنون در حال تکمیل مستندات برای استفاده از این کتابخانه در Github هستیم و خوشحال می‌شویم اگر بتوانید در بهینه کردن آن مشارکت کنید.</description>
                <category>علی کاویانی</category>
                <author>علی کاویانی</author>
                <pubDate>Mon, 17 Jun 2019 17:17:56 +0430</pubDate>
            </item>
            </channel>
</rss>