<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Ali Fattahi</title>
        <link>https://virgool.io/feed/@ali.fattahi</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-16 13:34:50</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/113255/avatar/ksgCmn.jpg?height=120&amp;width=120</url>
            <title>Ali Fattahi</title>
            <link>https://virgool.io/@ali.fattahi</link>
        </image>

                    <item>
                <title>مانیتورینگ و تشخیص ناهنجاری (‌Anomaly) در داده ها با استفاده از Grafana+Prometheus</title>
                <link>https://virgool.io/@ali.fattahi/%D9%85%D8%A7%D9%86%DB%8C%D8%AA%D9%88%D8%B1%DB%8C%D9%86%DA%AF-%D9%88-%D8%AA%D8%B4%D8%AE%DB%8C%D8%B5-%D9%86%D8%A7%D9%87%D9%86%D8%AC%D8%A7%D8%B1%DB%8C-anomaly-%D8%AF%D8%B1-%D8%AF%D8%A7%D8%AF%D9%87-%D9%87%D8%A7-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-grafanaprometheus-yemhl8ps3fij</link>
                <description>در اغلب شرکت ها برای نظارت بر سرورها ، منابع، شبکه و… ،‌ از ابزارهای مانیتورینگ استفاده میکنند که به آنها کمک میکند با مشاهده داده ها و نمودارها، پیش از وقوع یک حادثه، اقدامات پیشگیرانه را انجام دهند. یکی از چالش های تیم های نظارت، این است که به مرور زمان، تعداد این نمودارها زیاد میشود و عملا امکان بررسی همزمان همه آنها وجود ندارد. برای حل این مساله اقدام به تعریف تعدادی هشدار برای هریک از انها میکنند تا در زمان وقوع مشکل و یا قبل از آن متوجه شده و اقدامات لازم را انجام دهند.به عنوان مثال، ما برای دیسک، یک مانیتور و هشدار تنظیم می‌کنیم تا در زمانی که ظرفیت استفاده شده ی آن به ۸۰٪ رسید یک هشدار برای ما ارسال شود و پیش از وقوع حادثه،‌ اقدامات لازم را انجام دهیم.  به نظر همه چیز خوب است تا این که یک ناهنجاری رخ میدهد. ناهنجاری چیست ؟به بیان ساده، بی نظمی در داده‌ها و هر داده‌ی دورافتاده (outlierها) را میتوان یک ناهنجاری در نظر گرفت. به عنوان مثال افزایش یا کاهش حجم استفاده شده دیسک در یک بازه زمانی کوتاه را میتوان یک ناهنجاری نامید.تا اینجا متوجه شدیم که ممکن است یک ناهنجاری از دیدی هشدارها پنهان بماند و اگر حجم استفاده یک دیسک در یک بازه زمانی به صورت غیرعادی کاهش پیدا کند سیستم هشدار متوجه آن نمیشد. احتمالا بگویید یک هشدار دیگر تنظیم میکنیم تا در صورت کاهش حجم استفاده از دیسک متوجه آن شویم. بله ممکن است در برخی موارد این روش جواب دهد ولی باز هم برخی از هشدارها را از دست خواهید داد یا هشدارهای اشتباه دریافت کنید زیرا که داده ها دارای نویز زیادی هستندچطور هنجارها را تشخیص دهیم ؟راه های زیادی برای تشخیص ناهنجاری در داده های time series وجود دارد. از محاسبات ساده گرفته تا استفاده از شبکه های عصبی مانند LSTMها. ما در این پست قرار است از روش &quot;3sigma rule&quot; استفاده کنیم که به نام قانون 99-95-68 نیز شناخته میشودبه صورت خلاصه ،‌ قانون 3Sigma بیان میکند که تقریبا تمام داد های نرمال ما باید در ۳ انحراف معیار از مقدار متوسط داده های ما باشد.3-sigma قانونانتظار می‌رود حدود 68 درصد از داده‌های ما در یک انحراف استاندارد، 95 درصد در 2، و تقریباً تمام داده‌های ما در 3 انحراف استاندارد از میانگین باشد.در این مقاله، ما می‌خواهیم مقدار انحراف معیار را نسبت به میانگین آن اندازه گیری کرده و در صورتی که بالاتر از عدد 3.0 بود به عنوان یک ناهنجاری در نظر بگیریم. به عبارتی باید مقدار Z-Score ما بالاتر از 3.0 باشدz-score فرمولدر  Grafana برای محاسبه ی این فرمول به ۳ مورد نیاز داریمیک Datapoint که مقادیر یک بازه زمانی (x) را نمایش میدهدمیانگین داده های ما در یک دوره زمانی طولانی تر(μ)انحراف معیار در بازه زمانی یکسان (طولانی تر) (σ)برای این مبحث ما از متریک node_disk_writes_completed_total استفاده میکنیم. این متریک نشان دهنده تعداد  write های موفق بر روی دیسک است.محاسبه ی میانگین و انحراف معیار مورد نظر ما با استفاده از از توابع داخلی Prometheus به سادگی قابل انجام است.محاسبه میانگین - avg_over_time  :avg_over_time(node_disk_writes_completed_total{instance=&amp;quot$node&amp;quot,job=&amp;quot$job&amp;quot,device=~&amp;quot$diskdevices&amp;quot}[1d]))محاسبه انحراف معیار - stddev_over_time:stddev_over_time(node_disk_writes_completed_total{instance=&amp;quot$node&amp;quot,job=&amp;quot$job&amp;quot,device=~&amp;quot$diskdevices&amp;quot}[1d])دو کوئری بالا مقادیر میانگین و انحراف معیار را در یک بازه زمانی ۱ روزه [1d] به ما میدهدآخرین بخش از داده های ما به دست آوردن یک Datapoint برای x در فرمول ما است که با گرفتن یک میانگین دیگر در طول زمان میتوان آن را به دست آورد اما این بازه زمانی توسط یک متغیر در داشبورد گرافانا مشخص میشود و مقدار ثابت ۱ روزه ندارد.avg_over_time(node_disk_writes_completed_total{instance=&amp;quot$node&amp;quot,job=&amp;quot$job&amp;quot,device=~&amp;quot$diskdevices&amp;quot}[$__rate_interval]جمع بندی کوئری ها و قرار دادن در فومول Z-Score(avg_over_time(node_disk_writes_completed_total{instance=&amp;quot$node&amp;quot,job=&amp;quot$job&amp;quot,device=~&amp;quot$diskdevices&amp;quot}[$__rate_interval]) -avg_over_time(node_disk_writes_completed_total{instance=&amp;quot$node&amp;quot,job=&amp;quot$job&amp;quot,device=~&amp;quot$diskdevices&amp;quot}[1d])) / stddev_over_time(node_disk_writes_completed_total{instance=&amp;quot$node&amp;quot,job=&amp;quot$job&amp;quot,device=~&amp;quot$diskdevices&amp;quot}[1d])نتایج :با اجرای کوئری بر روی داده های مانیتورینگ نمودارهای زیر را مشاهده میکنیمنمودار میله ای داده هابه میله های بزرگ از چپ به راست توجه کنید. ما میخواهیم برای این میله ها هشدار ارسال کنیم اما نه برای میله های کوچک در سمت چپ انهااین نموداری است که کوئری بررسی ناهنجاری به ما میدهد:نمودار ناهنجاریاگر مقدار آستانه (threshold &gt;=3) تنظیم شود،‌میله های کوچکتر در هشدارها قرار نمیگیرند اما میله های بزرگ در هشدار ما قرار میگیرند زیرا که خیلی بزرگ هستند.یک مثال دیگرنمودار میله ای داده هانمودار بالا دارای میله های بسیار بیشتری نسبت به مثال قبل است (به عبارتی دارای نویز بیشتری است)، بنابراین ما یک آستانه (threshold) ایستا نمی‌خواهیم که روی هر یک از میله ها عمل کند بلکه باید روی میله های خارج از حد معمول عمل کند. با اجرای کوئری Anomaly خروجی زیر را دریافت میکنیمنمودار ناهنجاریتوجه داشته باشید که چگونه نتایج به امتیاز z 2.5 نزدیک می شوند، اما هرگز از آستانه 3 ما فراتر نمی روند، به طور خودکار این واقعیت را در نظر میگیرد که سیگنال نویز بیشتری دارد.صحبت نهایی:پیاده سازی هشدارها برای تشخیص ناهنجاری در داده های مانیتورینگ یکی از موارد حیاتی برای پیشگیری از وقوع حوادث است. بر اساس فرمول بالا علاوه بر این که می توان ناهنجاری ها را در مصرف Ram/CPU/Disk/Load و… را تشخیص داد،‌ میتوان برای شناسایی زمان بیکاری CPU، حافظه فعلی موجود،‌ فضای فعلی موجود در دیسک مورد استفاده قرار گیرد</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Tue, 23 Apr 2024 14:23:13 +0330</pubDate>
            </item>
                    <item>
                <title>بهترین شیوه های امنیتی در PHP</title>
                <link>https://virgool.io/alifattahi/%D8%A8%D9%87%D8%AA%D8%B1%DB%8C%D9%86-%D8%B4%DB%8C%D9%88%D9%87-%D9%87%D8%A7%DB%8C-%D8%A7%D9%85%D9%86%DB%8C%D8%AA%DB%8C-%D8%AF%D8%B1-php-gktwexaomqg2</link>
                <description>زبان برنامه نویسی PHP یکی از محبوب ترین زبان ها است که امروزه مورد استفاده قرار می گیرد. این زبان توسط میلیون ها وب سایت، از جمله برخی از بزرگترین نام ها در اینترنت استفاده می شود. در حالی که PHP یک زبان بسیار قدرتمند است، اما اگر به درستی استفاده نشود، می تواند کاملاً ناامن باشد. در این پست وبلاگ، روش های برتر برای امنیت PHP را مورد بحث قرار خواهد گرفت که به حفظ وب سایت شما در برابر هکرها و کاربران مخرب کمک می کند.سعی شده است در این مقاله از مثال های بسیار ساده استفاده شود تا افراد مبتدی نیز در ابتدای کار درک درستی از مطلب پیدا کنند.۱- بروز رسانی منظم PHPنسخه های قدیمی PHP دارای مشکلات امنیتی شناخته شده هستند. این نقص‌ها در نسخه‌های جدیدتر اصلاح شده‌اند و انجام حملات را برای هکرها دشوارتر می‌کنند. در حین حفظ برنامه های PHP، باید به روز رسانی نسخه را در اولویت قرار دهید تا از سطوح حمله ای که در برابر نسخه های قدیمی آسیب پذیر هستند جلوگیری کنید.۲- مراقب حملات XSS باشید (Cross-site scripting)یک حمله XSS زمانی رخ می دهد که یک برنامه وب، external remote code را اجرا می کند. یک مثال خوب زمانی است که کاربر در فرم ورودی، HTML، جاوا اسکریپت یا CSS را وارد می کند و کدها مستقیماً در یک صفحه وب نمایش/اجرا می شود. این اجرای کد می تواند باعث اختلال در عملکرد صفحه یا نمایش نتایج ناخواسته شود.فرمی که ورودی کاربر را دریافت میکند ممکن است به صورت زیر باشد:اگر برای چاپ مقدار ورودی، این تابع PHP را فراخوانی کنید:یک مهاجم ممکن است از یک فرم ورودی با وارد کردن یک اسکریپت به جای مورد نیاز استفاده کندوقتی اسکریپت اجرا می‌شود، «This site hacked by…» به‌عنوان یک پیام هشدار در مرورگر برای کاربر نمایش داده خواهد شد.اگرچه این یک مثال ساده از حمله XSS است، اما هکرها می توانند جاوا اسکریپت پیچیده تری را در فرم های ورودی وارد کنند که می تواند یک برنامه وب را کاملاً به خطر بیندازد زیرا می تواند ویروس تروجان را به یک برنامه وب تزریق کند، نام کاربری و رمز عبور ورودی کاربر را ضبط کند، کوکی های کاربران ( حتی ادمین) را به دست آورد و کارهایی از این قبیل.از حملات XSS می توان با موارد زیر جلوگیری کرد:فیلتر کردن تمام ورودی های کاربر در بدو ورود برای حذف تگ های کد احتمالی از ورود به سایت. کتابخانه htmlpurifier میتواند در این مورد به شما کمک کند.برای جلوگیری از تفسیر داده های ورودی کاربر به عنوان محتوای فعال در پاسخ های HTTP تمام آن را Encode کنید. ( استفاده از توابع htmlspecialchars و htmlspecialchars_decode )۳- مراقب دستورات SQL باشیدهیچگاه ورودی ها را به صورت مستقیم به دستورات SQL اضافه نکنید و سعی شود از ORM ها استفاده کنید تا مقادیر را بررسی و اجرا کنندمثال بالا از ورودی کاربر به صورت مستقیم در داخل کوئری SQL استفاده شده است و این به هکر فرصتی می دهد تا query را بشکند و سعی کند اطلاعات دیگر را اجرا کند.کوئری آماده شده زیر تضمین می کند که تمام مقادیر وارد شده escape شده و هیچ جایی برای تزریق SQL باقی نمی گذارد.نکته : راه دیگر استفاده از PDO_MYSQL است.۴− تمام فایل های یک framework یا کتابخانه را آپلود نکنیددر برخی از فریم ورک های php تعدادی فایل example قرار دارد که میتواند خطرناک باشند و در محیط‌های عملیاتی هیچ نیازی به آنها نیست. ممکن است برخی از آنها امکان اجرا کدهای خارجی یا آپلود فایل و یا هرگونه رخنه امنیتی باشند. پس بهتر است بعد از نصب، تمام فایل های اضافه و example را حذف نمایید.یک نمونه،‌ در برخی از پروژه های php از یک کتابخانه جاوا اسکریپتی برای ادیتور CKEditor و… استفاده میشود که همراه با نمونه کدهای php برای آپلود فایل و تصاویر است. در آپلود چنین کتابخانه هایی با دقت عمل نمایید و هرگونه فایل php در آنها را حذف کنید.۵−  محدودیت دسترسی به دایرکتوری هامحدود کردن دسترسی به دایرکتوری را می توان با استفاده از تابع open_basedir انجام داد.به عنوان مثال، اگر تابع open_basedir روی root پروژه تنظیم شده باشد، به این معنی است که فایل‌های قابل دسترسی تنها فایل‌هایی هستند که در ریشه پروژه شما و به سمت پایین هستند.۶− پیکربندی SSL خود را verify کنیدفرم هایی که کاربران در وب سایت شما تکمیل و ارسال میکنند،‌ آدرسهایی که پیمایش میکنند و.. همگی به صورت  plain text به سرور شما ارسال میشوند. در این مسیر هر شخصی که شبکه sniff کند میتواند محتوای فرم ها و… را به دست آورد. ( یک نمونه فرم ورود کاربر با رمز عبور است ) برای جلوگیری از این موضوع می‌توانید یک گواهی ssl تهیه کرده و در سرور خود برای وب سایت خود نصب نمایید. با نصب و فعال سازی یک ssl تمامی داده ها رمزنگاری شده و فقط توسط وب سرور شما قابل decrypt است و مهاجم در بین راه نمیتواند به داده های شما دسترسی پیدا کندگواهینامه های SSL را به طور منظم verify کنید و قبل از منقضی شدن تمدید نمایید.۷- از include کردن فایل های remote خودداری کنیداز پذیرش ورودی کاربر برای include کردن فایل خودداری کنید. این به این دلیل است که مهاجم می‌تواند مسیری را وارد کند که به اطلاعات حساس منتهی می‌شود، به‌عنوان مثال، etc/passwd/ ../../..، که می‌تواند منجر به دسترسی آنها به رمز عبورها در صورتی که در سرور لینوکس/یونیکس باشد، شود.اگر به هر دلیلی نیاز به این عملیات دارید، اعتبارسنجی آن قبل از اجرا یک مرحله ضروری است. همچنین می تواند برای امنیت بیشتر از تابع open_basedir همراه شود. یک راه حل حتی بهتر در هنگام پذیرش ورودی کاربر، مشخص کردن انتخاب های احتمالی کاربر با استفاده از دستور سوئیچ است.یک مثال ساده:− ثبت خطای برنامهثبت خطا در توسعه برنامه، هم در محیط های staging و هم در محیط production، بسیار حیاتی است. به دلیل این واقعیت که گزارش های خطا به اشکال زدایی و نظارت بر عملکرد برنامه کمک می کند. بنابراین، باید گزارش‌ها را از برنامه‌های PHP در یک فایل مشخص برای استفاده بعدی ذخیره کنید. لاگ ها را به صورت زیر در داخل فایل php.ini پیکربندی کنید:برای جلوگیری از دستیابی هکرها به اطلاعات ارزشمند در سایت شما بر اساس خطا، باید نمایش خطاها را در سرور production/staging غیرفعال کنید. پارامترهای زیر را در فایل php.in تنظیم کنید:پیشنهاد میگردد برای سهولت در انجام عملیات ثبت خطا ها از ابزارهایی مانند sentry یا newrelic استفاده نمایید.- تمام ورودی های کاربران را اعتبار سنجی کنیدتمام ورودی های کاربر باید قبل از اینکه توسط کد PHP شما پردازش شود، تأیید شود. این شامل داده‌های وارد شده در فیلدهای فرم، پارامترهای URL و مقادیر JSON می‌شود. با اعتبار سنجی ورودی کاربر، می‌توانید از حملات Cross-Site Scripting (XSS) و دیگر انواع ورودی‌های مخرب جلوگیری کنید.۱۰-  امن کردن دایرکتوری های آپلود فایل و Asset هایکی از روش هایی که میتواند دست مهاجم را برای اجرای کدهای آپلود شده خود ببندد،‌ محدودیت اجرای فایل در دایرکتوری هایی است که فرم های اپلود شما،‌فایلها را در آنجا آپلود میکنند یا فایل های asset کتابخانه ها قرار دارد.تکه کد زیر در nginx میتواند از اجرای فایل های php در دایرکتوری های uploads و assets را بگیردشما میتوانید به دلخواه تغییر دهید  و اگر از وب سرور آپاچی استفاده میکنید تکه کد زیر را در .htacess قرار دهید۱۲− غیرفعال سازی توابع خطرناک در phpدر php توابعی وجود دارند که میتوان با استفاده از آنها دستوراتی را در سطح سیستم عامل اجرا کرد. مهاجمان معمولا پس از پیدا کردن رخنه‌ی امنیتی برای آپلود فایل، فایل های مورد نظر خود را آپلود کرده تا با سرعت و سهولت بیشتری بتوانند عملیات خود را انجام دهند. در این فایل ها معمولا از توابع زیر استفاده شده است که شما میتوانید در php.ini آنها را غیرفعال کرده و دست مهاجم را برای ادامه عملیات مخرب ببندیدلیست :php_uname,proc_open,proc_get_status,crack_check,crack_closedict, crack_getlastmessage, crack_opendict, psockopen, php_ini_scanned_files, hell-exec, system, dl, ctrl_dir, phpini, tmp, safe_mode, systemroot, server_software, get_current_user, HTTP_HOST, ini_restore, popen, pclose, exec, shell_exec, suExec, passthru, pclose, proc_nice, proc_terminate, pfsockopen, leak, apache_child_terminate, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, posix_ctermid, posix_getcwd, posix_getegid, posix_geteuid, posix_getgid, posix_getgrgid, posix_getgrnam, posix_getgroups, posix_getlogin, posix_getpgid, posix_getpgrp, posix_getpid, posix_getppid, posix_getpwnam, posix_getpwuid, posix_getrlimit, posix_getsid, posix_getuid, posix_isatty, posix_kill, posix_mkfifo, posix_setegid, posix_seteuid, posix_setgid, posix_setpgid, posix_setsid, posix_setuid, posix_times, posix_ttyname, posix_uname, posix_access, posix_get_last_error, posix_getppid, posix_mknod, posix_strerror, posix_access, posix_ctermid, posix_get_last_error, posix_getcwd, posix_getegid, posix_geteuid, posix_getgid, posix_getgrgid, posix_getgrnam, posix_getgroups, posix_getlogin, posix_getpgid, posix_getpgrp, posix_getpid, posix_getppid, posix_getpwnam, posix_getpwuid, posix_getrlimit, posix_getsid, posix_getuid, posix_initgroups, posix_isatty, posix_kill, posix_mkfifo, posix_mknod, posix_setegid, posix_seteuid, posix_setgid, posix_setpgid, posix_setsidposix_setuid, posix_strerror, posix_times, posix_ttyname, posix_uname, symlink, rapih, myshellexec, c99_buff_prepare, c99_sess_put,fpassthru,system ,show_source,parse_ini_fileسخن پایانیاین روش ها کامل نیستند به عنوان مثال صحبتی از CSRF و XSRF و Session Hijacking نشده است ولی میتواند تا حدی در امنیت نرم افزارهایی که به زبان php نوشته شده اند کمک کند. شما میتوانید مطالعه خود را برای موارد فوق ادامه دهید و سعی شود موارد امنیتی را همیشه به عنوان یکی از اصول کد نویسی حرفه ای خود در نظر بگیرید.نکته : فریم ورک های php مانند laravel تا حد زیادی موراد امنیتی مانند csrf، session hijacking و ... را برطرف کرده اند و ابزارهای اعتبار سنجی ورودی کاربران و... را در اختیار شما قرار میدهند ولی بخشی از موارد بالا مربوط به مدیریت سرورها میشود که باید توسط sysadmin ها اعمال شود.</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Mon, 17 Jul 2023 13:07:44 +0330</pubDate>
            </item>
                    <item>
                <title>توسعه فرهنگ Google SRE در کسب و کار</title>
                <link>https://virgool.io/alifattahi/%D8%AA%D9%88%D8%B3%D8%B9%D9%87-%D9%81%D8%B1%D9%87%D9%86%DA%AF-google-sre-%D8%AF%D8%B1-%DA%A9%D8%B3%D8%A8-%D9%88-%DA%A9%D8%A7%D8%B1-e0pfalsfqiz8</link>
                <description>پیش گفتاردر طول دوره فعالیت تخصصی، هیچ گاه یادگیری خود را متوقف نکرده ام و همیشه در حال یادگیری در موضوعات مرتبط با رشته تخصصی خود بوده ام. ضعف بزرگی وجود داشت که به دلیل کمبود وقت،‌ هیچگاه اقدام به مستند سازی و انتشار دانش و تجربه‌های خود نکرده بودم و صرفا در جلسات به اشتراک دانش میپرداختم.گاهی  اوقات مباحثی را مطالعه میکردم که هیچ منبع فارسی زبانی در مورد آن وجود نداشت و یا کامل نبودند و بعد از مدتی متوجه این موضوع گردیدم که افراد بیشتری به یادگیری آن مباحث نیاز دارند. از این رو تصمیم گرفته شد که در حد توان به مستند سازی مباحث جدید پرداخته که اولین نتیجه‌ی آن کتاب پیش روی شما است. در این کتاب تلاش شده است مباحث با بیانی ساده و روان ارائه گردد و در پانویس برخی از صفحات، کلمات انگلیسی مرتبط با یک کلمه فارسی، برای درک بهتر موضوع درج شده است.این کتاب، نتیجه‌ی یادگیری بنده از دوره ی Developing a Google SRE Culture است و تمامی سرفصل ها و موضوعات مرتبط را پوشش میدهد و سعی شده است که همه مطالب را به بهترین شکل ممکن با تصاویر اصلی منتقل کند و در نهایت برای بهبود کسب و کار شما مورد استفاده قرار گیرد.مقدمه آیا تا به حال در مورد قابلیت اطمینان سرویس های خود نگرانی داشته اید ؟ آیا تا به حال شاهد کاهش در تعامل با مشتری بوده اید، اما وقتی از تیم خود سوال میکنید، آنها نمیتوانند توضیح دهند که چرا این اتفاق می‌افتد؟ هر دو تیم توسعه و عملیات شما می‌گویند: &quot;همه چیز سبز است.&quot; اما میدانید، باید مشکلی وجود داشته باشد زیرا کاربران نهایی شما، مشتریان شما، این را به شما می‌گویند. اگر زمان قابل توجهی را صرف تولید و اجرای نرم‌افزارها کرده‌اید، احتمالاً هنگام به‌روزرسانی‌های جزئی، تاثیر منفی بر مشتریان را نیز احساس کرده‌اید. اگر این موقعیت ها برای شما آشنا به نظر می‌رسد، احتمالاً تعجب می‌کنید که چرا تیم های توسعه و عملیات شما اغلب اولویت های متناقضی دارند و چرا در لاک خود به کار خود ادامه می‌دهند. گوگل سال ها صرف اجرای سیستم ها در مقیاس عظیم کرده است. با گذشت زمان، ما شیوه‌های خود را استاندارد کرده‌ایم تا سرعت ویژگی‌هایمان را با ریسک قابل اطمینان، هم برای ما و هم برای مشتریانمان متعادل کنیم. این شیوه‌ها، همراه با فرهنگی برای حمایت از آنها، مهندسی قابلیت اطمینان سایت یا SRE می‌نامیم. چه هنوز در حال تصمیم گیری در مورد چگونگی و زمان انتقال به Cloud هستید، یا قبلاً از فناوری Cloud استفاده میکنید، این مبحث میتواند به شما کمک کند تا درک کنید که چگونه اصول عملی و فرهنگی SRE می‌توانند تاثیر مثبت دائمی بر روی پروژه های IT و کار روزانه شما داشته باشند. شما همچنین خواهید آموخت که چگونه اندازه سازمان و سطح بلوغ برای SRE میتواند بر اجرای این اصول تأثیر بگذارد.این کتاب به شما یک نمای کلی از اصول فنی و فرهنگی SRE میدهد و توضیح می‌دهد که کجا و چگونه می‌توانید آنها را در سازمان خود اعمال کنید. از آنجایی که اصول SRE با شیوه‌های فلسفه DevOps همسو هستند، این دوره اصول اولیه DevOps را نیز پوشش می‌دهد. حتی اگر قبلاً با روش‌های DevOps آشنا باشید، خواهید دید که گوگل چگونه فلسفه را تفسیر می‌کند، بنابراین امیدواریم چیز جدیدی یاد بگیرید. این کتاب دارای چندین هدف آموزشی کلی است. در پایان این دوره، می‌توانید دیدگاه Google در مورد فلسفه DevOps و رابطه بین DevOps و SRE را مورد بحث قرار دهید. ارزشی را که SRE میتواند به عملیات IT شما ارائه دهد را درک کنید. اصول فنی و فرهنگی SRE گوگل را بیان کنید. سطح بلوغ سازمان خود را در پذیرش SRE ارزیابی کنید. مشخص کنید که در یک مهندس قابلیت اطمینان سایت به دنبال چه مهارت هایی باشید و چگونه نیروی کار موجود خود را آموزش دهید. و در نهایت، درک کنید که چگونه Google میتواند به شما کمک کند تا SRE را در سازمان خود شروع کنید.دانلود کتابمخزن کتاب در گیت هاب</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Mon, 13 Feb 2023 14:31:57 +0330</pubDate>
            </item>
                    <item>
                <title>درک بهتر SLA/SLO/SLI</title>
                <link>https://virgool.io/alifattahi/%D8%AF%D8%B1%DA%A9-%D8%A8%D9%87%D8%AA%D8%B1-slaslosli-vfrvindnbx6v</link>
                <description>SLA-SLO-SLIهمه شرکت های فناوری دارای یک چیز مشترک هستند:‌مشتری!و در دنیای Always-On امروزی، انتظارات مشتری - برای خدمات رایگان و پولی - بالاست. سرعت. آپتایم. UX مفید. مشتری امروزی انتظار دارد همه چیز از استاندارد بالایی برخوردار باشد.به همین دلیل است که برای شرکت‌ها مهم است که SLA، SLO و SLI را درک کرده و حفظ کنند. سه عبارت اولیه که بیانگر وعده‌هایی است که به کاربرانمان می‌دهیم، اهداف داخلی که به ما کمک می‌کنند به این وعده‌ها عمل کنیم، و اندازه‌گیری‌های قابل ردیابی که به ما می‌گویند چگونه هستیم یا در چه وضعیتی قرار داریم!هدف هر سه مورد این است که فروشنده و مشتری در مورد عملکرد سیستم دارای نظر یکسانی باشند. سیستم های شما چقدر در دسترس خواهند بود؟ اگر سیستم از کار بیفتد، تیم شما چقدر سریع پاسخ خواهد داد؟ چه وعده هایی در مورد سرعت و عملکرد می دهید؟ کاربران می‌خواهند این موارد را بدانند و بنابراین شما به SLA، SLO و SLI نیاز دارید.توافق نامه سطح خدمات SLA - Service Level Agreements‏SLA (توافق نامه سطح خدمات) توافقی است بین سرویس دهنده و مشتری در مورد معیارهای قابل اندازه گیری مانند آپتایم، پاسخگویی و مسئولیت ها.این توافق‌نامه‌ها معمولاً توسط تیم‌های حقوقی و تجاری یک شرکت تنظیم می‌شوند و نشان‌دهنده وعده‌هایی هستند که به مشتریان می‌دهید و عواقب آن در صورت عدم تحقق آن وعده‌ها.به طور معمول، عواقب آن شامل جریمه های مالی، اعتبار خدمات یا تمدید مجوز می شود.چالش SLA هااندازه گیری، گزارش دهی و رسیدن به SLA ها بسیار دشوار است. این توافق‌ها - عموماً توسط افرادی نوشته می‌شوند که خودشان در زمینه‌های فناوری نیستند و اغلب وعده‌هایی را می‌دهند که اندازه‌گیری آن برای تیم‌ها دشوار است، همیشه با اولویت‌های تجاری فعلی و در حال تغییر همسو نیستند و تفاوت‌های ظریف را در نظر نمی‌گیرند. به عنوان مثال، یک SLA ممکن است قول دهد که تیم ها مشکلات گزارش شده در محصول X را ظرف 24 ساعت حل خواهند کرد. اما همان SLA توضیح نمی دهد که اگر مشتری 24 ساعت طول بکشد تا پاسخ ها یا اسکرین شات ها را برای کمک به تیم شما در تشخیص مشکل ارسال کند، چه اتفاقی می افتد. آیا این بدان معناست که فرصت 24 ساعته تیم به دلیل تاخیر پاسخ مشتری از بین رفته است یا اینکه ساعت بر اساس زمانی که مشتریان پاسخ می دهند شروع و متوقف می شود؟ SLA ها باید به این سؤالات پاسخ دهند، اما اغلب در انجام این کار شکست می خورند.برای بسیاری از کارشناسان، پاسخ به این چالش، قبل از هر چیز این است که بخش فناوری باید در ایجاد SLA ها دخالت داشته باشد. هرچه IT و DevOps بیشتر با تیم توسعه حقوقی و تجاری برای SLAهایی که سناریوهای دنیای واقعی را بررسی می کنند همکاری کنند، SLA ها بیشتر شروع به انعکاس واقعیت های کلیدی می کنند، مانند همین که مشتریان حل مشکل خود را به تاخیر می اندازند!چه کسی به SLA نیاز دارد؟‏SLA توافقی بین فروشنده و مشتری است. شرکت هایی که خدماتی را به صورت رایگان به کاربران ارائه می کنند، بعید است که برای آن کاربران رایگان SLA بخواهند یا نیاز داشته باشند.اهداف سطح خدمات یا SLO - Service Level Objectivesیک SLO (هدف سطح خدمات) توافقی است در یک SLA در مورد یک معیار خاص مانند زمان کار یا زمان پاسخ. بنابراین، اگر SLA قرارداد رسمی بین شما و مشتری باشد، SLOها وعده هایی هستند که به آن مشتری می دهید. SLO ها چیزی هستند که انتظارات مشتری را تعیین می کنند و به تیم های IT و DevOps می گویند که باید به چه اهدافی دست یابند و خود را بر اساس آن ارزیابی کنند.چالش های SLO ها‏SLO ها به اندازه ی SLA ها نفرت انگیز نیستند، اما اگر مبهم، بیش از حد پیچیده یا غیرممکن باشند، می توانند به همان اندازه مشکلات ایجاد کنند. سادگی و وضوح دو کلید اصلی است که باعث میشود مهندسین شما عصبانی نشوند. فقط مهمترین معیارها باید واجد شرایط وضعیت SLO باشند، اهداف باید به زبان ساده بیان شوند، و مانند SLAها، همیشه باید مسائلی مانند تاخیر در سمت مشتری را در نظر بگیرند. اهداف باید واضح باشند و به زبان ساده بیان شوندچه کسی به SLOها نیاز دارد؟در جایی که SLA ها فقط در مورد مشتریان پولی هستند، SLO ها می توانند هم برای حساب های پولی و بدون پرداخت و هم برای مشتریان داخلی و خارجی مفید باشند.سیستم های داخلی مانند CRM ها، Data Repository های مشتری و اینترانت می توانند به اندازه سیستم های خارجی مهم باشند. و داشتن SLO برای آن سیستم‌های داخلی بخش مهمی است که نه تنها به اهداف تجاری دست می‌یابد، بلکه تیم‌های داخلی را قادر می‌سازد تا به اهداف مشتریان خود برسند.شاخص سطح خدمات SLI - Service Level Indicatorیک SLI (شاخص سطح خدمات) انطباق با SLO (هدف سطح خدمات) را اندازه گیری می کند. بنابراین، برای مثال، اگر SLA شما مشخص می‌کند که سیستم‌های شما در 99.95% مواقع در دسترس خواهند بود، SLO شما احتمالاً 99.95% uptime است و SLI شما اندازه‌گیری واقعی uptime شما است. شاید 99.96٪ باشد. شاید 99.99 درصد. برای اینکه SLA شما مطابقت داشته باشد، SLI باید به وعده های داده شده در آن سند عمل کند یا از آن فراتر رود.چالش SLI هامانند SLOها، چالش SLIها ساده نگه داشتن آنها، انتخاب معیارهای مناسب برای ردیابی، و پیچیده نکردن کار IT با ردیابی تعداد زیادی از معیارهایی است که در واقع برای مشتریان مهم نیستند.یک طرح دقیق برای ترمیم فاجعه ایجاد کنیددر صورت بروز downtime چه خواهید کرد؟ اگر از قبل پاسخ آن سوال را نمی‌دانید، پاسخ پیش‌فرض «هدر دادن وقت گرانبها در زمان بحران برای فهمیدن اینکه چه کاری انجام دهید» خواهد بود.هرچه برنامه واکنش شما به حوادث بهتر باشد، تیم های شما سریعتر و موثرتر حوادث را مدیریت خواهند کرد. به همین دلیل است که اولین گام هر برنامه مدیریت حادثه جدید باید فرآیند و برنامه ریزی باشد.چه کسی به SLI نیاز دارد؟هر شرکتی که عملکرد خود را با SLO ها اندازه گیری می کند، برای انجام این اندازه گیری ها به SLI نیاز دارد. شما واقعا نمی توانید SLO بدون SLI داشته باشید.بهترین پیشنهادهای SLA، SLO و SLI ‏SLA ها را حول انتظارات مشتری بسازید.هر قسمت از قرارداد مشتری شما باید حول محور مواردی باشد که برای مشتری اهمیت دارد. در آخر، یک حادثه ممکن است به معنای پرداختن به 10 مؤلفه مختلف باشد. اما از نظر مشتری، تنها چیزی که اهمیت دارد این است که سیستم مطابق انتظار عمل کند.‏SLAها و SLOهای شما باید این واقعیت را منعکس کنند. با ریز شدن در موارد و دادن وعده های جداگانه برای هر یک از آن 10 جزء، کار را بیش از حد پیچیده نکنید. وعده های خود را محدود به عملکرد high-level سیستم نگه دارید. این کار مشتریان را راضی‌ترنگه می‌دارد و کمتر سردرگم می شوند و زندگی متخصصان فناوری اطلاعات را که مسئول اجرای وعده‌های SLA شما هستند، ساده‌تر می‌کند.از زبان ساده در SLA ها استفاده کنیدمشتریان همیشه توضیح نمی خواهند، بنابراین اگر زبان SLA شما پیچیده است، احتمالاً خود را برای برخی سوء تفاهمات دردناک آماده می کنید. هرچه زبان شما ساده تر باشد، احتمال تضاد مشتری در آینده شما کمتر خواهد بود.با SLO ها، کمتر، بیشتر است (Less is More)هر معیاری برای موفقیت مشتری حیاتی نیست، به این معنی که هر معیاری نباید SLO باشد. تا حد امکان به SLO های کمتری متعهد شوید و روی مواردی تمرکز کنید که برای مشتریان اهمیت بیشتری دارند.هر معیار قابل پیگیری نباید SLI باشدبه طور مشابه، ردیابی عملکرد در 10 مؤلفه برای هر یک از 10 SLO می تواند خیلی سریع سخت شود. در عوض، به طور استراتژیک انتخاب کنید که کدام معیارها واقعاً برای SLOهای اصلی شما مهم هستند و انرژی خود را برای ردیابی مؤثر آنها صرف کنید.عوامل خارج از کنترل تیم IT را اضافه کنید.چه اتفاقی می‌افتد وقتی مشتری همان کسی است که زمان را برای حل کردن مشکل کاهش می‌دهد؟ اگر در SLA خود در این مورد واضح نیستید، تیم شما ممکن است با استاندارد غیرممکن حل و فصل مسائل مشتری بدون دخالت مشتری درگیر شوند.تولید در بودجه خطاجا گذاشتن(فرصت) برای شکست‌ها نه تنها از کسب‌وکار در برابر نقض SLA و عواقب سنگین محافظت می‌کند، بلکه فضایی را برای چابکی ایجاد می‌کند - برای تیم که سریعاً تغییرات را انجام دهد و فضای لازم برای امتحان راه‌حل‌های جدید نوآورانه را داشته باشد که ممکن است شکست بخورند.از ظرفیت میزان خطای قابل قبول (بودجه خطا) به عنوان یک فرصت استفاده کنید.گوگل در واقع استفاده از بودجه خطای باقیمانده را برای downtime برنامه ریزی شده توصیه می کند، که می تواند به شما کمک کند مسائل پیش بینی نشده را شناسایی کنید (مانند سرویس هایی که به طور نامناسب از سرورها استفاده می کنند) و انتظارات مناسب از مشتریان خود را حفظ کنید.به ماه شلیک نکنیدفقط به این دلیل که تیم شما احتمالاً می‌تواند 99.99٪ آپتایم را حفظ کند، به این معنی نیست که 99.99٪ باید عدد SLO شما باشد. همیشه بهتر است کم وعده کنید و بیشتر تحویل دهید.برای کسانی که از مدل Google پیروی می‌کنند و از تیم‌های Site Reliability Engineering (SRE) برای پر کردن شکاف بین توسعه و عملیات استفاده می‌کنند، SLAs، SLOs و SLI‌ها برای موفقیت اساسی هستند.SLA به تیم ها کمک می کند تا مرزها و بودجه های خطا را تعیین کنند. SLO ها به اولویت بندی کار کمک می کنند. و SLI ها به SRE ها می گویند که چه زمانی باید همه راه اندازی ها را متوقف کنند تا در بودجه خطای در معرض خطر صرفه جویی کنند – و چه زمانی می توانند سر کیسه را شُل کنند :)جمع بندیاگر از این مطلب استفاده کردید با یک کامنت منو خوشحال کنید.</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Mon, 12 Dec 2022 15:37:37 +0330</pubDate>
            </item>
                    <item>
                <title>معرفی ابزار Kompose - تبدیل فایل docker compose به ریسورس های kubernetes و openshift</title>
                <link>https://virgool.io/alifattahi/%D9%85%D8%B9%D8%B1%D9%81%DB%8C-%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1-kompose-%D8%AA%D8%A8%D8%AF%DB%8C%D9%84-%D9%81%D8%A7%DB%8C%D9%84-docker-compose-%D8%A8%D9%87-%D8%B1%DB%8C%D8%B3%D9%88%D8%B1%D8%B3-%D9%87%D8%A7%DB%8C-kubernetes-%D9%88-openshift-lpawosye8jja</link>
                <description>ابزار kompose برای کمک به کاربرانی است که با docker-compose آشنا هستند تا راحت تر به سمت Kubernetes کوچ کنند. این ابزار فایل docker-compose را دریافت کرده و آن را به ریسورس های kubernetes تبدیل میکنه.تبدیل فرمت Docker Compose به مانیفست ریسورس Kubernetes ممکن است دقیق نباشد، اما برای اولین استقرار یک برنامه در Kubernetes به ما خیلی کمک میکنه.یک مثال ساده$ kompose convert -f docker-compose.yaml
INFO Kubernetes file &amp;quotfrontend-service.yaml&amp;quot created
INFO Kubernetes file &amp;quotredis-master-service.yaml&amp;quot created
INFO Kubernetes file &amp;quotredis-slave-service.yaml&amp;quot created
INFO Kubernetes file &amp;quotfrontend-deployment.yaml&amp;quot created
INFO Kubernetes file &amp;quotredis-master-deployment.yaml&amp;quot created
INFO Kubernetes file &amp;quotredis-slave-deployment.yaml&amp;quot created
$ kubectl apply -f .
$ kubectl get po
NAME                            READY     STATUS              RESTARTS   AGE
frontend-591253677-5t038            1/1       Running             0          10s
redis-master-2410703502-9hshf   1/1       Running             0          10s
redis-slave-4049176185-hr1lr         1/1       Running             0          10sخب حالا که متوجه شدیم این ابزار چقدر ساده و کاربردی هست بریم برای نصب ابزارنصب Komposeما چندین راه برای نصب Kompose داریم. روش ترجیحی ما دانلود باینری از آخرین نسخه GitHub است. Kompose از طریق GitHub در یک چرخه سه هفته ای منتشر میشه، شما می توانید تمام نسخه های فعلی را در صفحه GitHub release page. مشاهده کنید. نسخه ی فعلی در حال انتشار این مقاله v1.26.1 است. شما باید در هنگام نصب آخرین نسخه را دانلود نمایید.نصب روی لینوکس و مک او اس# Linux
curl -L https://github.com/kubernetes/kompose/releases/download/v1.26.1/kompose-linux-amd64 -o kompose# macOS
curl -L https://github.com/kubernetes/kompose/releases/download/v1.26.1/kompose-darwin-amd64 -o kompose
chmod +x kompose
sudo mv ./kompose /usr/local/bin/komposeویندوزاز این لینک دانلود کرده و در مسیر PATH ویندوزی خود قرار دهیدنصب با استفاده از پکیج در CentOSابزار Kompose در رپوزیتوری EPEL قرار دارد و باید این نکته را در نظر داشته باشید که از قبل این رپوزیتوری را نصب و فعال کرده باشیدsudo yum install epel-release
sudo yum -y install komposeنصب با استفاده از پکیج روی Ubuntu/Debianwget https://github.com/kubernetes/kompose/releases/download/v1.26.1/kompose_1.26.1_amd64.deb # Replace 1.26.1 with latest tag
sudo apt install ./kompose_1.26.1_amd64.debنصب با استفاده از Dockerdocker build -t kompose https://github.com/kubernetes/kompose.git
docker run --rm -it -v $PWD:/opt kompose sh -c &amp;quotcd /opt &amp;&amp; kompose convert&amp;quotمثال تبدیل برای openshift$ kompose convert --provider=openshift
INFO OpenShift file &amp;quotfrontend-service.yaml&amp;quot created
INFO OpenShift file &amp;quotredis-master-service.yaml&amp;quot created
INFO OpenShift file &amp;quotredis-slave-service.yaml&amp;quot created
INFO OpenShift file &amp;quotfrontend-deploymentconfig.yaml&amp;quot created
INFO OpenShift file &amp;quotfrontend-imagestream.yaml&amp;quot created
INFO OpenShift file &amp;quotredis-master-deploymentconfig.yaml&amp;quot created
INFO OpenShift file &amp;quotredis-master-imagestream.yaml&amp;quot created
INFO OpenShift file &amp;quotredis-slave-deploymentconfig.yaml&amp;quot created
INFO OpenShift file &amp;quotredis-slave-imagestream.yaml&amp;quot createdوب سایت kompose</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Sat, 19 Nov 2022 11:22:34 +0330</pubDate>
            </item>
                    <item>
                <title>مقدمه ای بر Kubernetes</title>
                <link>https://virgool.io/alifattahi/an-introduction-to-kubernetes-and-its-components-v1ufourpgsh3</link>
                <description>مقدمه ای بر کوبرنتیزمقدمه ای بر Kubernetesامروز قرار بود یه مقاله ای در مورد CRD ها در Kubernetes بنویسم. ولی فکر کردم شاید بهتر باشه ابتدا یه مقدمه ای در مورد Kubernetes و اجزای تشکیل دهنده اون داشته باشم تا درک بقیه مقالات مربوط به kubernetes راحت تر باشه و در هنگام مطالعه مقالات بعدی سوالات کمتری در ذهن شما ایجاد بشه.سطح مقاله :‌ متوسطمدت زمان مطالعه :  15 دقیقهکوبرنتیز (Kubernetes) چیست؟کوبرنتیز که به نام K8S نیز شناخته میشود،‌یک سیستم اوپن سورس برای خودکارسازی استقرار، مقیاس بندی و مدیریت نرم افزارهای Containerze شده است. Kubernetes بر اساس تجربه 15 سال اجرای Workloadهای Production در Google، همراه با بهترین ایده ها ساخته شده است. نام Kubernetes از یونان سرچشمه میگیرد که به معنی سکان دار یا خلبان است. K8s  به عنوان مخفف از شمردن هشت حرف بین &quot;K&quot; و &quot;s&quot; حاصل می شود. این پروژه در سال ۲۰۱۴ توسط شرکت گوگل به صورت اوپن سورس ارائه گردید.پاد (POD) چیست ؟پاد،‌کوچکترین و پایه ای ترین واحد قابل استقرار در کوبرنتیز است. یک پاد شامل یک یا چند کانتینر است. هنگامی که یک Pod چندین کانتینر را اجرا می کند، کانتینرها به عنوان یک موجودیت واحد مدیریت می شوند و منابع Pod را به اشتراک می گذارند.پاد در کوبرنتیزچرا ما به کوبرنتیز نیاز داریم و چه کارهایی برای ما انجام میدهد ؟کانتینرها راه خوبی برای بسته بندی (bundle) و اجرای برنامه هستند. در محیط های Production نیاز به مدیریت کانتینرهایی که برنامه شما را اجرا میکنند دارید و همچنین باید مطمئن باشید که downtimeای وجود ندارد. برای مثال، در صورتی که یک کانتینر down شد یک کانتینر دیگر اجرا شود. حال اگر این عملیات توسط یک سیستم مدیریت شود کار شما آسانتر خواهد شد. اینجاست که Kubernetes به کمک ما میآید و یک framework برای اجرای انعطاف پذیر سیستم های توزیع شده در اختیار ما قرار میدهد که عملیات لازم را برای scaling و failover برای برنامه شما انجام میدهد و همچنین الگوهای استقرار و … را در اختیار شما قرار میدهد.کلاستر کوبرنتیز از نمایی دیگرکلاستر کوبرنتیزچیزهایی که Kubernetes در اختیار شما قرار میدهد :ء- Service DIscovery و Load Balancing : کوبرنتیز می‌تواند یک کانتینر را با استفاده از نام DNS یا با استفاده از آدرس IP خود expose کند.در صورتی که ترافیک ورودی به کانتینر زیاد است، میتواند بار و ترافیک شبکه را بین کانتینرها توزیع کند تا یک استقرار پایدار بماند.ء- Storage orchestration :‌  کوبرنتیز به شما این امکان را می دهد که به طور خودکار یک سیستم ذخیره سازی مورد نظر خود را mount کنید، مانند local storage، ارائه دهندگان ابر عمومی و موارد دیگر.ء- Rollout و Rollback خودکار :‌شما می توانید state مورد نظرتان را برای کانتینرهای deploy شده توصیف کنید و state واقعی را با rate کنترل شده به state مورد نظرتان تغییر بدهید. برای مثال شما میتوانید به کوبرنیتز بگویید کانتینرهای جدیدی را برای شما بسازد و کانتینرهای فعلی را حذف کند و منابع آن را به کانتینرهای جدید اختصاص دهد.ء- Automatic bin packing :‌ شما مجموعه ای از nodeها را در اختیار kubernetes قرار میدهید تا کانتینرها را بر روی آنها اجرا کند و مشخص میکنید که هر کانتینر چه مقدار CPU و RAM نیاز دارد. kubernetes به صورت خودکار کانتینر شما در node هایی اجرا میکند که منابع لازم را داشته باشد تا به بهترین شکل از منابع استفاده شود.خوددرمانی (Self-healing) : کوبرنتیز کانتینرهای دارای مشکل را restart و replace میکند، کانتینرهایی را که وضعیت سلامت درستی ندارند را kill کرده و تا زمانی که آماده سرویس دهی به کلاینت نباشند به آنها ترافیکی هدایت نمیکندمدیریت Secret ها و پیکربندی ها :‌  کوبرنتیز  به شما امکان می دهد اطلاعات حساس مانند رمزهای عبور، توکن های OAuth و کلیدهای SSH را ذخیره و مدیریت کنید.  شما می توانید secret ها و config های برنامه را بدون بازسازی image کانتینر خود مستقر و به روز کنید.اجزای تشکیل دهنده Kubernetesیک کلاستر کوبرنتیز از چند کامپوننت که بر روی ماشین های مختلف که بخشی از کلاستر هستند تشکیل شده است.یک کلایتر کوبرنتیز شامل ۲ کامپوننت اصلی است :نود Control Plane (نود مستر) که وظیفه مدیریت و هماهنگی کلاستر را برعهده دارد.نود/نودهای Worker که کانتینرهای ما را اجرا میکنند.هر یک از این کامپوننت ها میتوانند یک سرور فیزیکی، مجازی و یا سرور ابری باشند.نود Control Planeبه عنوان نود master یا head شناخته میشود.این node وظیفه ی مدیریت node های worker و هچنینpodهای داخل کلاستر را بر عهده دارد.در محیط های production برای پایداری بیشتر، این node معمولا به صورت کلاستر اجرا میشود تا high availability و fault-tolerance را فراهم کندنود control plane دستورات را از cli یا یک ui از طریق api دریافت میکند.توصیه میشود که workload ها بر روی node های control plane اجرا نشوند.نودهای Workerسرورهای فیزیکی یا مجازی که شامل سرویس های لازم برای اجرای اپلیکیشن های کانتینرایز شده است.یک کلاستر کوبرنتیز به حداقل یک نود worker نیاز دارد اما معمولا تعداد این nodeها زیاد است.این nodeها میزبان podهای برنامه های شما هستند و podها برای اجرا روی این node ها برنامه ریزی و هماهنگ میشوند.شما میتوانید با افزودن و حذف این nodeها، کلاستر را کوچکتر و یا بزرگتر کنید.کامپوننت های Control Planeکامپوننت های Control Plane وظیفه تصمیم گیری در مورد تمام کلاستر را دارند،‌همچنین event های کلاستر را تشخیص داده و پاسخ مناسب را ارائه میدهند. کوبرنتیز به چندین سرویس مدیریتی در حال اجرا بر روی Control Plane متکی است که این سرویس ها جنبه هایی مانند ارتباط بین کامپوننت های کلاستر،‌ برنامه ریزی workloadها، وضعیت کلاستر و… را مدیریت میکنند.لیست کامپوننت های Control PlaneETCDKube-apiserverKube-control-managerkube-schedulerکامپوننت ETCDبه عنوان یک DataStore برای کلاستر عمل میکندیک دیتابیس key-value قدرتمند و با قابلیت High available است که وضعیت کلاستر را نگهداری میکند.اطلاعاتی در مورد podها و nodeهای در حال اجرا در کلاستر و … را نگهداری میکند.در صورتی که چند نود مستر وجود داشته باشیم،‌ دیتا را بین آنها sync میکند.در صورتی که از etcd در کلاستر استفاده میکنید با استفاده از دستور etcd snapshot save از دادهای کلاستر خود نسخه پشتیبانی تهیه کنید.ابزار etcdctl به زبان Go نوشته شده است و به ما این اجازه را میدهد تا داده های داخل کلاستر etcd را دستکاری کنیم.  کارهایی که میتوانیم با آن انجام دهیم :ذخیره، بروزرسانی و حذف یک keyبررسی سلامت کلاستراضافه و حذف نود etcdساخت snapshot از دیتابیسهمچنین دارای مکانیزم watch است که یک اینترفیس event-based را برای نظارت بر تغییرات key ها به صورت async ارائه میدهد. به محض این که مقدار یک key تغییر کند،‌  watcher آن مطلع میشود. این یک ویژگی حیاتی در Kubernetes است، زیرا کامپوننت API Server به شدت به آن متکی است تا از هرگونه تغییر در آن مطلع شود و کامپوننت مناسب آن تغییرات را فراخوانیکامپوننت API Server (kube-apiserver)ء-APIهای Kubernetes را ارائه میدهدزمانی که در خط فرمان از kubectl استفاده میکنیم درواقع در حال ارتباط با kube-apiserver هستیم.از kube-apiserver برای پردازش عملیات REST، اعتبار سنجی آنها و بروز رسانی آبجکت های مرتبط با آنها در etcd استفاده میشود.تنها کامپوننتی است که به etcd متصل است. تمام کامپوننت های دیگر باید از kube-apiserver برای کار با کلاستر استفاده کنند.این کامپوننت دارای مکانیزم watch در داخل خودش است (شبیه به etcd). ویژگی watch به کامپوننت هایی نظیر kube-scheduler و kube-control-manager اجازه تعامل با api-server را میدهد و در صورتی که تغییری در ectd رخ دهد، از تغییرات مطلع شده و task مرتبط با آن را انجام میدهند.به نحوی طراحی شده است که بتوان به صورت افقی مقیاس بپذیرد.فایل های manifest با فرمت های json/yaml برایش قابل درک است.یک مثال : زمانی که ما یک پاد را ایجاد میکنیم چه اتفاقی رخ میدهد ؟مراحل ایجاد یک پاد در کلاستر کوبرنتیزء- Kubectl دستور را به api-server ارسال میکندء- Api-server درخواست را اعتبار سنجی کرده و آن را در etcd ذخیره میکندء- Etcd به api-server اطلاع میدهدء- Api-server کامپوننت scheduler را فراخوانی میکندء- Scheduler تصمیم میگیرد که پاد در کدام نود اجرا شود و آن را به api-server برمیگرداند.ء- Api-server آن را در etcd ذخیره میکندء- Etcd به api-server اطلاع میدهدء- Api-server کامپوننت kubelet را در نود مورد نظر فراخوانی میکند.ء- Kubelet با استفاده از api با docker daemon صحبت میکند  تا container را ایجاد نماید.ء- Kubelet وضعیت پاد را به api-server میدهد.ء- Api-server وضعیت جدید را etcd ذخیره میکندکامپوننت kube-control-managerء- Kube-control-manager وضعیت کلاستر را از طریق ویژگی watch در api server مشاهده کرده و زمانی که به آن اطلاع رسانی میشود،‌ تغییرات لازم را برای حرکت از state موجود به state مورد نظر انجام میدهد.مثال :‌ خرابی node، ریپلیکیشن کامپوننت ها، و حفظ تعداد پادها و غیره را مدیریت می کند.ء- Kube-control-manager فقط یک سرویس (controller) نیست بلکه شامل بسیاری از سرویس های دیگر است که بر اساس flag آنها، تصمیم به فعال/غیرفعال سازی آنها میگیرد.به منظور فعال سازی controller ها، از flagهای زیر در هنگام پیکربندی کلاستر استفاده کنید.لیست کنترلر های قابل فعال سازی در کلاستر کوبرنتیزبه منظور جلوگیری از پیچیدگی،‌تمام این سرویس ها (controller ها) در یک process عمل میکنند. به عنوان مثال کنترلر هایی که تا به امروز توسط کوبرنتیز ارائه شده است :ء-  Node controller : مسئول توجه و پاسخ دادن در هنگام down شدن یک node است.ء-  Replication controller: مسئول نگهداری تعداد  صحیح  podها به ازای هر آبجکت replication controller در سیستم است.ء-  Endpoints Controller: سرویس ها و pod ها را به هم متصل میکند. در واقع آدرس ip پادها که به صورت داینامیک به آنها اختصاص داده شده است را جمع آوری کرده و به عنوان یک service selector عمل میکند که service و pod را بر اساس labelها به هم متصل میکند.ء- Service Account &amp; Token Controllers: این کنترلر وظیفه ساخت account های پیش فرض و api access token ها را برای namespace های جدید دارد.ء- Cloud Controller Manager وقتی کلاستر در محیط ابری در حال اجرا است، cloud-controller-manager با فناوری‌های ابری زیربنایی در cluster شما integrate می‌شود.ء- Cloud-controller-manager فقط کنترلرهایی را اجرا می کند که مختص ارائه دهنده ابر شما هستند.ء- Cloud-controller به شما امکان می دهد کلاستر خود را به API ارائه دهنده ابر لینک کرده و کامپوننت هایی که با پلتفرم ابری در تعامل هستند را از کامپوننت هایی که فقط با کلاستر شما در تعامل هستند، جدا کند.کنترلرهای زیر می توانند وابستگی هایی به ارائه دهنده خدمات ابر داشته باشند:ء- Node controllerء- Route Controller: برای راه اندازی route ها در زیر ساخت ابریء- Service controller : برای ایجاد ،‌بروز رسانی و حذف load balancer ارائه دهنده ابر.کامپوننت kube-scheduler:این کامپوننت وظیفه برنامه ریزی برای ساخت pod جدید را دارد و node ای را برای این کار در نظر میگیرد که از نظر منابع و فضا مناسب pod مورد نظر باشد.درواقع به kube-apiserver و kube-controller-manager برای pod های جدید ایجاد شده گوش می دهد و سپس آن را برای یک node موجود در کلاستر برنامه ریزی می کند.در صورتی که نود مناسبی برای پاد مورد نظر یافت نشود آن را در وضعیت pending قرار میدهد تا زمانی که نود مناسب آن پیدا شود.مثال :‌ در صورتی که یک اپلیکیشن نیاز به 1 گیگ حافظه و ۲ هسته پردازنده داشته باشد، برنامه ریزی میشود تا در node ای اجرا شود که دارای حداقل نیازمندی ها باشد.عواملی که برای تصمیم گیری های kube-scheduler در نظر گرفته می شوند عبارتند از:منابع مورد نیاز موجود باشدمحدودیت های سخت افزاری و نرم افزاریپیکربندی های Affinity و anti-affinityمحل داده هاتداخل inter-workloadء- Taint ها  و dealine هاکامپوننت های نودهای Workerهر نود worker دارای کامپوننت های زیر است:KubeletKube-proxyContainer Runtime Interface (CRI)کامپوننت kubelet :یک Agent است که در تمام nodeهای کلاستر در حال اجرا است. (حتی نود control plane)به عنوان مجرای بین api-server و node عمل می کند و گزارشات را به api-server میدهد.سرویس kubelet به عنوان یک واسطه بین kube-apiserver و CRI (Container Runtime Interface) عمل می کند.مشخصات pod را از kube-apiserver دریافت می کند و تضمین می کند که podها و containerهای آنها سالم هستند و در state مورد نظر کار می کنند.پادها را راه اندازی و اجرا میکند.ء- Kubelet ازcontainer runtime برای راه‌اندازی پاد استفاده می‌کند، چرخه عمر آن را مانیتور کرده و readiness و … را بررسی میکند.کاموننت kube-proxyء- Kube-proxy با اجازه دادن به ارتباطات بین پادها، کانتینرها و node ها، ترافیک شبکه را مدیریت می کند.این کامپوننت یک pod است در تمام نودهای کلاستر اجرا میشود ( حتی control plane)این pod تغییرات kube-apiserver را زیر نظر میگیرد و شبکه را از طریق قوانین iptables که ترافیک را به endpoint صحیح ارسال می کند، به روز نگه می دارد.اطمینان حاصل می کند که هر pod آدرس IP منحصر به فردی را دریافت می کند.این امکان را فراهم می کند که همه کانتینرهای یک پاد یک IP واحد را به اشتراک بگذارند.این کامپوننت load balancing را در تمام podهای یک service انجام میدهد.ء- Container Runtime Interfaceبرای راه‌اندازی کانتینرها روی nodeها به نرم‌افزار Container Runtime نیاز داریم، می‌توانیم از Container Runtime مختلفی استفاده کنیم، اما به طور گسترده از docker استفاده می‌شود.برای اجرای کانتینرها، هر worker node دارای یک container runtime engine است.ء- kubelet با داکر صحبت می‌کند و کانتینرهای ما را در صورت تقاضا اجرا یا متوقف می‌کند.ء- Kubernetes از چندین Container Runtime پشتیبانی می کند: Docker، containerd، cri-o، rktlet.در این مقاله شما با اجزای تشکیل دهنده یک کلاستر کوبرنتیز آشنا شده اید. شاید برخی از کلمات برای شما نامفهوم باشد. در صورت هرگونه ابهام میتوانید در کامنت ها سوال خود را مطرح نمایید.به دلیل عدم پشتیبانی ویرگول از  راست چین کردن پاراگراف هایی که با حروف انگلیسی شروع میشوند مجبور به استفاده از ء- برای راست چین کردن شده ام. لطفا در صورت مشاهده این حرف در ابتدای پاراگرفها، آنها را نادیده بگیرید.</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Sun, 13 Nov 2022 21:02:57 +0330</pubDate>
            </item>
                    <item>
                <title>ده اشتباه در پیکربندی NGINX</title>
                <link>https://virgool.io/alifattahi/nginx-10-common-mistakes-qsjxxbslauuc</link>
                <description>در این مقاله به ۱۰ اشتباه رایج در پیکربندی nginx و راه حل آنها پرداخته میشود.اشتباه ۱ : Not Enough File Descriptors per Workerدستور worker_connections حداکثر تعداد کانکشن های باز  همزمانی که یک پردازنده (worker proccess)میتواند داشته باشد (پیش فرض ۵۱۲) را مشخص میکند. همه انواع کانکشن ها (برای مثال، کانکشن های پروکسی سرورها) نیز در این مقدار حداکثر شمرده میشوند نه فقط کانکشنهای کلاینت ها!. اما این نکته را باید در نظر داشته باشیم در نهایت یک محدودیت دیگه در تعداد کانکشن های همزمان در هر worker وجود داره :‌ محدودیت سیستم عامل بر روی جداکثر تعداد File Descriptor هایی که به هر process اختصاص داده شده است. در توزیع های UNIX جدید، این محدودیت پیش فرض ۱۰۲۴ است.برای اکثر استقرار های NGINX  به جز پروژه های کوچک، مقدار ۵۱۲ خیلی کم هست. در واقع در فایل پیش فرض nginx.conf برای نسخه رایگان و plus این مقدار به ۱۰۲۴ افزایش داده است.اشتباه رایج پیکربندی این است که محدودیت file descriptor ها را به حداقل دو برابر مقدار worker_connections افزایش نمی دهید. راه حل این است که مقدار آن را با دستور worker_rlimit_nofile در فایل nginx.conf اصلی تنظیم کنید.چرا به تعداد file descriptor های بیشتری نیاز است ؟ هر کانکشن از یک worker process در انجینکس به یک کلاینت یا upstream server، یک file descriptor مصرف میکند. وقتی nginx به عنوان یک وب سرور عمل میکند، از یک FD برای کانکشن کلاینت و یک FD برای فایلی که آن را serve میکند استفاده میکند و این برای حالت حداقلی است اما اکثر صفحات وب از تعداد زیادی فایل ساخته شده اند و نیاز به تعداد بیشتر FD است. زمانی nginx که به عنوان proxy server استفاده میشود، از یک FD برای هر کانکشن و یک FD برای upstream و یک FD سوم برای فایلی که به صورت موقت response را نگه داری میکند استفاده میشود و زمانی که از nginx به عنوان یک  caching server استفاده می شود، رفتار آن مشابه وب سرور برای response های cache شده و شبیه proxy server در زمانی cache وجود ندارد و یا منقضی شده است.انجینکس همچنین از یک FD به ازای هر Log file و یک جفت FD برای ارتباط با master process استفاده میکند اما معمولا این تعداد در برابر تعداد FD هایی که در کانکشن ها و فایلها استفاده میشود ناچیز است.یونیکس (UNIX) معمولا راه های مختلفی برای تنظیم تعداد FD ها در هر Process ارائه میدهد.دستور ulimit در صورتی که  nginx در shell اجرا شده باشد.اسکریپت init یا متغیرهای سرویس systemd در صورتی که nginx به صورت service اجرا شده باشد.فایل etc/security/limits.conf/به هرحال روش قابل استفاده، بستگی به نوع اجرای nginx دارد در حالی که دستور worker_rlimit_nofile ارتباطی با نوع اجرای انجینکس ندارد.همچنین یک محدودیت در سطح سیستم عامل برای تعداد File Descriptor ها وجود دارد که میتوان آن را به وسیله دستور sysctl fs.file-max  تغییر داد. مقدار پیش فرض معمولا به اندازه کافی بزرگ هست اما بهتره یک محاسبه در این مورد با فرمول زیر انجام شود.(worker_rlimit_nofile * worker_processes)که معمولا به طور قابل ملاحظه ای کمتر از fs.file‑max است. اگر به هر دلیلی مثلا یک حمله ی DoS باعث استفاده از تمام آن شود دیگه حتی امکان ورود به سیستم عامل برای فیکس کردن اون هم نداریم ?اشتباه ۲: دستور error_log offیک اشتباه رایج این است که فکر میکنیم دستور error_log off، لاگ گیری را غیرفعال میکند. در واقع، برخلاف دستور access_log ، دستور error_log پارامتر off نمیگیرد.در صورتی که شما دستور error_log off را در پیکربندی ها استفاده کنید، nginx یک فایل لاگ خطا به نام off در دایرکتوری پیش فرض خودش ( etc/nginx/ ) ایجاد میکندبه دلیل این که error log ها حاوی اطلاعات حیاتی در مورد هر مساله در nginx و یا سرویس هستند. ما به شما پیشنهاد نمیکنیم که error log ها را غیرفعال کنید. به هر حال فضای ذخیره سازی محدود است و اگر ممکن است داده های لاگ تمام فضای شما را اشتغال کند و تصمیم به غیرفعال کردن آن گرفته اید. از دستور العمل زیر استفاده نمایید.error_log /dev/null emerg;بعد از این دستور نیاز است یک بار وب سرور reload گردد تا تغییرات اعمال شوند.اشتباه ۳ :فعال نکردن Keepalive Connections در Upstream Serversبه صورت پیش فرض، nginx به ازای هر درخواست یک کانکشن جدید به یک upstream(backend) server باز میکند. این کار ایمن ولی ناکارمد است! چون nginx و server باید ۳ پکت برای برقراری کانکشن و ۳ یا ۴ پکت برای خاتمه دادن به آن مبادله کنند.در حجم ترافیک بالا،‌باز کردن یک کانکشن جدید برای هر درخواست میتواند تهدیدی برای منابع سیستم باشد و حتی میتواند باز کردن کانکشن جدید دیگر غیرممکن شود. دلیل آن هم این است که برای هر کانکشن، ۴ جفت اطلاعات شامل آدرس مبدا، پورت مبدا، آدرس مقصد، پورت مقصد باید به صورت unique باشد.برای کانکشن ها از nginx به یک upstream server، سه عدد از این المنت ها (اول، سوم و چهارم)  ثابت است ولی پورت مبدا، به صورت متغیر است. زمانی که یک کانکشن بسته میشود، سوکت لینوکس به مدت دو دقیقه در حالت TIME-WAIT قرار میگیرد که در حجم ترافیک بالا، امکان تکمیل پورت های داخل pool وجود دارد که در صورت این اتفاق، nginx توانایی باز کردن کانکشن جدید به upstream server را ندارد.راه حل این است که keepalive connection را بین nginx و upstream server فعال کنیم. این روش احتمال تمام شدن پورت های pool را کاهش می دهد و هم عملکرد را بهبود می بخشد.به منظور فعال کردن keepalive connection:اضافه کردن دستور keepalive در هریلاک {}upstreamاین نکته را در نظر داشته باشید که این دستور تعداد کانکشن ها به upstream server به ازای هر worker process را محدود نمیکنه. این یک تصور غلط رایج است. پس پارامتر keepalived نباید اونقدر که فکر میکنید عدد بزرگی باشه.ما پیشنهاد میکنیم پارامتر را به مقدار ۲ برار تعداد سرورهای لیست شده در بلاک {}upstream قرار بدید. این مقدار به اندازه ای کافی برای nginx  بزرگ است که بتونه تمام کانکشن های keepalived را نگه داری کنه وهمچنین به اندازی کافی کوچک هست که upstream server ها بتوانند کانکشن های ورودی جدید را نیز پردازش کنند.در نظر داشته باشید هنگامی که یک الگوریتم load balacer برای بلاک {}upstream مشخص میکنیم (منظورhash, ip_hash, least_conn, least_time, یا random است ) باید در بالای دستور keepalived قرار گیرند. این یکی از استثناهای نادر در قاعده کلی است و ترتیب دستورات در پیکربندی NGINX مهم نیست.بلاک {}location که درخواست ها را به سمت upstream هدایت میکند باید همراه با این دو دستور در کنار proxy_pass باشد:proxy_http_version 1.1;proxy_set_header   &quot;Connection&quot; &quot;&quot;;به صورت پیش فرض nginx از HTTP/1.0 برای کانکشن های upstream server استفاده میکند و  بر همین اساس یک Connection: close  به header درخواست هایی که به سرور می فرستد اضافه میکند و در نتیجه زمانی که درخواست کامل شود، کانکشن بسته میشود و keepalived در {}upstream نادیده گرفته میشود.دستور  proxy_http_version به nginx میگه که از HTTP/1.1 استفاده کنه و دستور proxy_set_header مقدار close را از هدر Connection حذف میکنه.اشتباه ۴:‌ فراموش کردن نحوه عملکرد وراثت دستوراتدستورالعمل های NGINX به صورت رو به پایین یا outside-in به ارث برده می شوند: یعنی یک context فرزند از دستورات والد خود به ارث میبرد. برای مثال، تمام بلاک های {}server و {}location در {}http مقادیر  دستوراتی که داخل بلاک {}http اضافه شده است را به ارث میبرند و تمام دستورات در بلاک {}server به بلاک های فرزند {}location به ارث میرسد. به هر حال اگر یک دستوری در هردوی آنها موجود باشد دیگر از والد خود به ارث نمی برند و دستور و مقدار همان بلاک مورد استفاده قرار میگیرد. اشتباه اونجایی هست که این قانون در دستورات array فراموش میشه که نه تنها میتونه در چندین context اضافه بشه بلکه متیونه چندی بار در یک context استفاده بشه. برای مثال دستورات proxy_set_header  و add_header. همین واژه ی add در دستور میتونه باعث فراموش شدن این قانون بشه.در مثال زیر نحوه عملکرد وراثت را برای دستور add_header نشون میدیمبرای سروری که به پورت 8080 گوش میده هیچ دستور add_header در هیچ یک از بلاک های {}server و {}location وجود ندارد ولی به دلیل وراثت ما هر دوی آن را در header داریم.برای سروری که به پورت 8081 گوش میده یک دستور add_header در بلاک {}server وجود داره ولی در بلاک {}location وجود نداره. Header هایی که در بلاک{}server وجود دارد دو header تعریف شده در بلاک {}http را نادیده میگیرد.در بلاک location /test یک دستور add_header وجود دارد و این دستور باعث میشود دو header در والد خود یعنی {}server و دو header از {}http را نادیده بگیرد.اگر بخواهیم یک بلاک {}location  هدر های تعریف شده در والد خود را به همراه هدرهای تعریف شده در بلاک خود حفظ کند باید تمام آنها را مجدد تعریف کنیم. دقیقا چیزی که در بلاک location /correct تعریف شده است.اشتباه ۵ : دستور proxy_buffering offبافر پروکسی به صورت پیش فرض در nginx فعال است. یعنی پارامتر دستور proxy_buffering مقدار on است.بافر پروکسی به این معنی است که NGINX پاسخ یک سرور را در بافرهای داخلی ذخیره می کند و تا زمانی که کل پاسخ بافر نشود، شروع به ارسال داده به client نمی کند. سرورهای پروکسی شده میتوانند در سریع ترین زمان ممکن پاسخ خود را برگردانند تا برای ارائه ی درخواست های دیگر در دسترس باشند. بافر کردن به بهینه سازی عملکرد کلاینت های کند (slow) کمک میکنه چون nginx پاسخ را تا زمانی که کلاینت نیاز داره تا کل آن را دریافت کنه، بافر میکنه.زمانی که بافر پروکسی غیرفعال است، nginx فقط بخش اول پاسخ سرور را قبل از شروع ارسال به کلاینت در یک بافر که به صورت پیش فرض به اندازه یک memery page است بافر میکند. (بسته به نوع سیستم عامل 4KB یا 8KB). معمولا این مقدار برای response header کافی است. سپس NGINX همزمان با دریافت پاسخ، پاسخ را برای مشتری ارسال می‌کند و سرور را مجبور می‌کند تا زمانی که NGINX بتواند بخش پاسخ بعدی را accept کند به صورت idle قرار بگیرد.خیلی شگفت انگیزه که بعضیا بافر پروکسی را غیرفعال میکنند. شاید هدفشون کاهش تاخیر تجربه شده توسط کلاینتها باشه، اما تأثیر اون ناچیزه در حالی که عوارض جانبی متعدد داره: با غیرفعال کرد بافر پروکسی، rate limit و caching حتی در صورت پیکربندی، دیگه کار نمیکنه و عملکرد هم ضعیف میشه.فقط در یک سری موارد بسیار محدود ممکنه غیرفعال کردن بافر پروکسی منطقی باشه (مثل long polling) . بنابراین ما به شدت از تغییر این پیش فرض خودداری می کنیم. پیشنهاد میکنم این مقاله را بخونید (NGINX Plus Admin Guide)اشتباه ۶ : استفاده نامناسب از دستور ifاستفاده از دستورالعمل if بیشتر به صورت تریک است، به خصوص در بلوک های {}location. اغلب اون چیزی که ما انتظار داریم را انجام نمیده و حتی ممکنه باعث خطاهایی هم بشه. در واقع از اونجایی استفاده ازش ترسناکه که یک مقاله در ویکی nginx با عنوان if is Evil وجود داره که پیشنهاد میکنم برای جزییات بیشتر از مشکلات و راه پرهیز از آنها، اونو بخونید.به طور کلی، دستوراتی که معمولا میتونید به صورت امن در بلاک {}if استفاده کنید return و rewrite هستند. مثال زیر، از دستور if برای تشخیص درخواست هایی که هدر X-Test دارند استفاده میکنه. nginx خطای 430 (Request Header Fields Too Large) را برمیگردونه، آن را از location نامگذاری شده @error_430 میگیره و درخواست را به upstream به نام b پروکسی می کنه.برای این مورد و بسیاری دیگر از استفاده های if، اغلب امکان اجتناب از دستورالعمل وجود داره. در مثال زیر،  زمانی که یک درخواست شامل هدر X-Test است، بلاک map مقدار متغیر upstream$ را b ست میکنه و درخواست به گروه upstream با اون نام پروکسی میشهاشتباه ۷ : بررسی بیش از اندازه health checkپیکربندی چندین سرور  برای درخواست‌های پروکسی در یک upstream group (به عبارت دیگر، اضافه کردن دستور proxy_pass یکسان در بلوک‌های چند {}server) کاملاً معمول هست. اشتباه، استفاده از دستور health_check در همه بلاک های {}server است. این دستور فقط یک بار اضافه بر روی upstream هست و هیچ اطلاعات اضافه ای را ارائه نمیکنه.راه حل این هست که فقط یک health check به ازای هر {}upstream تعریف بشه. اینجا ما یک health check  برای یک upstream group به نام b در یک location نامگذاری شده تعریف کردیمدر پیکربندی‌های پیچیده، می‌تواند مدیریت را برای گروه‌بندی همه location های health check در یک سرور مانند این مثال، ساده‌تر کرد.اشتباه ۸ :‌ دسترسی نا امن به metric هامتریک های پایه ای در مورد عملکرد NGINX در ماژول Stub Status در دسترس است.برای فعال سازی metrics collection دستور stub_status یا api به ترتیب در یک بلوک {}server یا {}location اضافه کنید که تبدیل به URLی می شود که برای مشاهده metric ها به آن دسترسی دارید.برخی از این متریک ها شامل اطلاعات حساسی هستند که میتواند برای حمله به وب سایت یا اپ های شما که توسط nginx پروکسی شده است مورد استفاده قرار گیرد و اشتباهی که رخ میدهد این است که برای این آدرس محدودیت دسترسی تنظیم نشده است. در ادامه چند روش برای امن کردن آدرس متریک ها را ارائه میدیم.در پیکربندی زیر، هر شخصی در اینترنت میتواند به متریک ها به آدرس  http://example.com/basic_status  دسترسی داشته باشد.محافظت از متریک ها با استفاده از HTTP Basic Authenticationبه منظور محافظت از متریک ها به وسیله رمز عبور میتوانید از HTTP Basic Authentication استفاده کرد. برای این کار از دو دستور  auth_basic و auth_basic_user_file استفاده میشود. فایل htpasswd شامل لیستی از نام کاربری و رمز عبور کاربرانی است که می توانند متریک ها را مشاهده کنند.محافظت از متریک ها با دستورات allow و denyاگر نمی‌خواهید کاربران مجاز مجبور به ورود به سیستم شوند، و آدرس‌های IP را که از طریق آنها به متریک ها دسترسی خواهند داشت، می‌دانید، گزینه دیگر دستور allow است.می توانید آدرس های IPv4 و IPv6 و محدوده CIDR را مشخص کنید. دستور deny all مانع از دسترسی از هر آدرس دیگری می شود.ترکیب دو روشاگر بخواهیم هر دو روش را با هم ترکیب کنیم چه؟ ما می‌توانیم به کلاینت اجازه دهیم از آدرس‌های خاص بدون رمز عبور به متریک ها دسترسی داشته باشند و همچنان برای کلاینتهایی که از آدرس‌های مختلف وارد می‌شوند، نیاز به ورود به سیستم داشته باشند. برای این ما از دستور satisfy any استفاده می کنیم. این دستور به NGINX می‌گوید که اجازه دسترسی به کلاینت‌هایی را بدهد که یا با HTTP Basic وارد می‌شوند یا از یک آدرس IP از پیش تأیید شده استفاده می‌کنند. برای امنیت بیشتر، می‌توانید satisfy را روی all تنظیم کنید تا حتی افرادی که از آدرس‌های خاصی آمده‌اند نیاز به ورود داشته باشند.این پیکربندی فقط به کلاینت هایی که از شبکه 96.1.2.23/32 یا localhost می‌آیند، بدون رمز عبور دسترسی دارند. از آنجایی که دستور در سطح {}server تعریف شده‌اند، محدودیت‌های یکسانی برای API و داشبورد اعمال می‌شود. به عنوان یک نکته جانبی، پارامتر write=on به api به این معنی است که این کلاینت ها می توانند از API برای ایجاد تغییرات پیکربندی نیز استفاده کنند.برای اطلاعات بیشتر درباره پیکربندی API و داشبورد، به NGINX Plus Admin Guide مراجعه کنید.اشتباه ۹ :‌استفاده از ip_hash در زمانی که همه ی ترافیک از یک بلاک 24/ CIDR می آید.الگوریتم ip_hash ترافیک را بین سرورهای داخل یک {}upstream براساس hash آدرس ip کلاینت، پخش میکند. کلید hashing، سه اکتت اول آدرس IPV4 یا کل آدرس IPV6 است. این روش پایداری session را ایجاد می کند، به این معنی که درخواست های یک کلاینت همیشه به همان سرور اولیه ارسال می شود، مگر زمانی که آن سرور در دسترس نباشد.فرض کنید ما nginx را به عنوان یک reverse proxy بر روی یک شبکه خصوصی برای high availability نصب کرده ایم. ما چند فایروال، روتر، لودبالانسر لایه ۴ و gateway های مختلفی را در جلوی NGINX قرار می‌دهیم تا ترافیک از منابع مختلف را بپذیریم و اون را به nginx میدیم تا برای به صورت reverse proxy به upstream server ها بدهد. پیگربندی زیر یک نمونه اولیه است :اما یه مشکل وجود داره. همه دستگاه‌ها در یک شبکه 10.10.0.0/24 هستند، بنابراین برای NGINX به نظر می‌رسد که تمام ترافیک از آدرس‌هایی در آن رنج CIDR می‌آید. به یاد داشته باشید که الگوریتم ip_hash سه اکتت اول یک آدرس IPv4 را هش می کند. در استقرار ما، سه اکتت اول برای هر کلاینت یکسان است (10.10.0) بنابراین hash برای همه آنها یکسان است و هیچ مبنایی برای توزیع ترافیک در سرورهای مختلف وجود ندارد.برای حل این موضوع از الگوریتم توزیع بار hash  با پارامتر  $binary_remote_addr  به عنوان hash key استفاده کنید. این متغیر آدرس کامل کلاینت را می گیرد و آن را به یک باینری تبدیل می کند که 4 بایت برای آدرس IPv4 و 16 بایت برای آدرس IPv6 است. اکنون هش برای هر دستگاه متفاوت است و تعادل بار همانطور که انتظار می رود کار می کند.ما همچنین پارامتر consistent را برای استفاده از روش هش کردن ketama به جای پیش‌فرض در نظر می‌گیریم.این امر تعداد کلیدهایی را که در هنگام تغییر مجموعه سرورها به upstream server ها remap می شوند تا حد زیادی کاهش می دهد که باعث بهبود عملکرد میشود.اشتباه ۱۰ : عدم استفاده از گروه های upstreamفرض کنید از NGINX برای یکی از ساده‌ترین موارد استفاده، به‌عنوان یک reverse proxy برای یک برنامه backend مبتنی بر NodeJS که در پورت 3000 گوش می‌دهد، استفاده می‌کنید. یک پیکربندی معمول ممکن است به این صورت باشد:دستورالعمل proxy_pass به NGINX میگه که درخواست‌های کلاینت به کجا را ارسال کند. تنها کاری که NGINX باید انجام دهد این است که hostname را به آدرس IPv4 یا IPv6 تبدیل کند. هنگامی که اتصال برقرار شد NGINX درخواست ها را به آن سرور ارسال می کند.اشتباه اینجا این است که فکر میکنیم چون فقط یک سرور وجود دارد - و بنابراین دلیلی برای پیکربندی load balancer وجود ندارد - ایجاد یک بلوک {}upstream بی معنی است. در واقع، یک بلوک {}upstream چندین ویژگی را آنلاک می کند که باعث بهبود عملکرد میشه، همانطور که در این پیکربندی نشان داده شده است:تنظیمات upstream در nginxدستورالعمل zone یک zone حافظه مشترک ایجاد می کند که در آن تمام worker processهای در یک host می توانند به پیکربندی و اطلاعات وضعیت سرورهای upstream دسترسی داشته باشند. چندین گروه upstream می توانند zone را به اشتراک بگذارند.دستور server دارای چندین پارامتر است که می توانید از آنها برای تنظیم رفتار server استفاده کنید. در این مثال، شرایطی را که NGINX برای تعیین unhealthy بودن سرور و در نتیجه واجد شرایط بودن برای پذیرش درخواست‌ها استفاده می‌کند، تغییر داده‌ایم. در اینجا اگر تلاش ارتباطی حتی یک بار در هر دوره 2 ثانیه ای شکست بخورد (به جای پیش فرض یک بار در دوره 10 ثانیه). سرور را unhealthy در نظر می گیرد. ما این تنظیم را با دستور proxy_next_upstream ترکیب می‌کنیم تا اون چیزی را که NGINX یک تلاش ارتباطی ناموفق در نظر می‌گیرد، پیکربندی کنیم، در این صورت درخواست‌ها را به سرور بعدی در گروه upstream ارسال می‌کند.به شرایط پیش‌فرض خطا و مهلت زمانی، http_500 را اضافه می‌کنیم تا NGINX یک کد HTTP 500 (خطای سرور داخلی) را از یک سرور upstream برای نشان دادن تلاش ناموفق در نظر بگیرد.دستورالعمل keepalive تعداد کانکشن های بیکار keepalive به سرورهای upstream که در cache هر worker process حفظ می شوند، تنظیم می کند.منبع</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Sat, 05 Nov 2022 21:10:05 +0330</pubDate>
            </item>
                    <item>
                <title>عیب یابی مشکلات شبکه در Docker با استفاده از کانتینر کمکی.</title>
                <link>https://virgool.io/alifattahi/%D8%B9%DB%8C%D8%A8-%DB%8C%D8%A7%D8%A8%DB%8C-%D9%85%D8%B4%DA%A9%D9%84%D8%A7%D8%AA-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-docker-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-%DA%A9%D8%A7%D9%86%D8%AA%DB%8C%D9%86%D8%B1-%DA%A9%D9%85%DA%A9%DB%8C-hktbzqvlue8v</link>
                <description>یکی از مشکلاتی که معمولا sysadmin ها با Docker دارند مسائل مربوط به شبکه است که برای عیب یابی آنها نیاز به ابزارهایی مانند telnet، ping،nmap،netstat،wireshark و... میشود و معمولا ایمیج های داکر به صورت پیش فرض دارای چنین ابزارهایی نیستند و ما فقط درهنگام عیب یابی به این ابزارهای نیاز داریم. اولین راه حلی که به ذهن میرسه این هست که بریم داخل container و سریع دستور نصب را بزنیم و ابزار را نصب کنیم.این یک روش اشتباهه! به عنوان مثال در کانتینر nginx، جای پکیج های عیب یابی شبکه نیست. دلیل آن هم کاملا روشنه. کانتینر nginx چه نیازی به wireshark یا nmap داره ؟ مگه بدون این ابزارها نمیتونه کار کنه ؟خب چطور عیب یابی انجام بدیم ؟ راه حل اون ساده هست. ما با یک کانتینر کمکی این کار را انجام میدیم. کانتینر های کمکی فقط برای عیب یابی شبکه نیستند و میشه کارهای زیادی را با اون انجام داد.کار کانتینر کمکی کارش چیه ؟ فرض کنید ما یک کانتینر اصلی داریم که وظیفه ش مشخصه و کارشو انجام میده. میایم در کنارش کانتیرنر کمکی میاریم بالا تا یک سری ابزارهای کمکی در اختیار ما قرار بده. مثلا ما یک کانتینر اصلی db داریم و این نیاز داره در ابتدای شروع به کارش یک سری دیتا به داخل کپی بشه. ابتدا کانتینر اصلی میاد بالا و ما یک کانتینر کمکی که وظیفه ی کپی کردن فایل را برعهده داره میاریم بالا.در مثال کانتینر nginx فرض میکنیم که ما نیاز به ابزارهای کمکی برای عیب یابی شبکه داریم برای این کار ما یک کانتینر کمکی که دارای ابزارهای مختلف برای عیب یابی شبکه هست را میاریم بالا میچسبونیمش به کانتینر اصلی nginx و وقتی ما در داخل کانتینر کمکی دستوری برای عیب یابی اجرای میکنیم دقیقا مثل این هست که داریم داخل کانتینر اصلی اون دستور را اجرا میکنیم بدون این که نیاز باشه یک سری پکیج اضافه روی کانتینر اصلی نصب بشه.یکی از کانتینر های معروف برای عیب یابی های شبکه که ابزارهای زیادی هم داره nicolaka/netshoot هست. برای استفاده از اون هم میتونیم این کانتینر را درشبکه ی کانتینر اصلی بیاریم بالا و دستورات را در اون اجرا کنیم.بریم سراغ مثال های عملی.ابزار tcpdumptcpdump یک ابزاری هست که میتونیم با استفاده از اون پکت های ورودی/ خروجی را بخونیم، انالیز کنیم و از این دسته کارها.در این مثال ما یک کانتینر nginx اجرا میکنیم و یک کانتینر nicolaka/netshoot هم برای عیب یابی اون میاریم بالا و به شبکه کانتینر اصلی وصل میکنیم# docker run -d –name mynginx -p 80:80 nginx
# docker run -it –net container:mynginx nicolaka/netshootخب همانطور که مشاهده میکنید در اجرای کانتینر کمکی از دستور -d یا -itd استفاده نشد. دلیل اون هم مشخصه. این کانتینر کمکی هست و پس از پایان ماموریتش دیگه باهاش کاری نداریم. پس از اجرای دستور بالا وارد کانتینر netshoot شدیم و دستور زیر را اجرا میکنیم# tcpdump -i eth0 port 80 -c 1 -Xvvسوییچ -i eth0 اشاره به کارت شبکه داخل کانتینر mynginx داره.اجرای دستور tcpdumpپس از اجرای این دستور میتونیم آی پی  docker host را در داخل یک مرورگر باز کنیم تا به nginx اصلی وصل بشیم و tcpdump پکت ورودی را کپچر کرده و نتیجه را به ما نشون میده tcpdumpنتیجه دستورابزار iperfمثال دوم، iperf ابزاری برای تست performance شبکه هست. گاهی اوقات پیش میاد که میگن مشکل کندی داریم و این مشکل میتونه دلایل مختلفی داشته باشه که یکی از اونها ممکنه کندی شبکه باشه و ما میخوایم متوجه این بشیم که آیا ارتباط بین دو کانتینر دارای کندی هست یا خیر.برای این کارابتدا یک شبکه از نوع bridge در داخل داکر میسازیم# docker network create perf-testخب حالا دو کانتینر کلاینت و سرور برای تست مورد نظرمون میاریم بالا و نتایج را میبینیم# docker run -itd –name perf-test-a –network perf-test nicolaka/netshoot iperf -s -p 9999
# docker run -itd –name perf-test-b –network perf-test nicolaka/netshoot iperf -c perf-test-a -p 9999خب میتونیم با اجرا دستور زیر لاگ کانتینر perf-test-a را مشاهده کنیمنتیجه ی تست عملکرد شبکه با دستور iperfمثال سوم استفاده از ابزار netstatبرای این مثال ما مجدد یک کانتینر به نام mynginx و یک کانتینر کمی میاریم بالا# docker run -d –name mynginx -p 80:80 nginx
# docker run -it –net container:mynginx nicolaka/netshootحالا میتونیم دستور netstat را اجرا کنیم تا پورت های باز را مشاهده کنیمنتیجه اجرای دستور netstatمیبینیم که پورت 80 در حال listen شدن هست و انگار دستور را داخل کانتینر nginx اجرا کردیممثال چهارم. استفاده از netcatگاهی اوقات شما از یک پورتی استفاده میکنید که دیده نمیشه و میخواید چک کنید که آیا فایروال اون را بلاک کرده یا نه.در این مثال ابتدا ما یک شبکه در داکر میسازیم به نام mynet و بعد از اون هم دوتا کانتینر # docker network create mynet
# docker run -d –name mynginx –net mynet -p 80:80 nginx
# docker run -itd –name mynetcat –net mynet nicolaka/netshoot nc -vz mynginx 80
# docker logs mynetcatو نتیجه :نتیجه دستور ncوقتی این پیام را میبینیم متوجه میشیم که حداقل فایروال این پورت را بلاک نکرده و با موفقیت به پورت وصل شدیممثال پنجم، ابزار iftop برای مانیتور کردن پهنای باند شبکه به صورت realtime# docker run -d –name mynginx –net mynet -p 80:80 nginx
# docker run -it -net container:mynginx nicolaka/netshoot iftop -i eth0نتیجه دستور iftopخب به انتهای این مقاله رسیدیم. امیدوارم مقاله مفیدی باشه و گره ای از مشکلات شما باز کنه. در صورتی که مشکلی در روند کار مشاهده کردید میتونید در کامنت ها درج کنید تا پاسخ بدم.</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Fri, 13 May 2022 23:44:48 +0430</pubDate>
            </item>
                    <item>
                <title>روشی برای کار با داده های آماری در دیتابیس - شبیه سازی Materialized view در Mariadb/Mysql</title>
                <link>https://virgool.io/alifattahi/%D8%B1%D9%88%D8%B4%DB%8C-%D8%A8%D8%B1%D8%A7%DB%8C-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-%D8%AF%D8%A7%D8%AF%D9%87-%D9%87%D8%A7%DB%8C-%D8%A2%D9%85%D8%A7%D8%B1%DB%8C-%D8%AF%D8%B1-%D8%AF%DB%8C%D8%AA%D8%A7%D8%A8%DB%8C%D8%B3-%D8%B4%D8%A8%DB%8C%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-materialized-view-%D8%AF%D8%B1-mariadbmysql-hjbiz5onoxtg</link>
                <description>مقدمهچندی پیش در یکی از پروژه هایی که در پذیرش24 کار میکردم نیاز به یک داشبورد آماری شد که باید برای به دست آوردن آمارهای روزانه / ماهانه و سالانه با فیلتر های مختلف یک تعداد کوئری اجرا میکردم و چالش از اونجایی شروع شد که در این کوئری ها باید بین چند جدول join انجام میشد و تعداد رکوردهای اون tableها هم سر به فلک میکشید و در نتیجه زمان پاسخ کوئری حدود 2 دقیقه طول میکشید. یکی دیگه از مشکلات این بود که تعداد کاربران سیستم خیلی زیاد بودن و در زمان لانچ پروژه تعداد زیادی کوئری اجرا میشد که عملا با اون روش کار عاقلانه ای نبود. پس دست به کار شدم و روشی که در همراه‌پی استفاده استفاده کرده بودم را اونجا هم اجرا کردم البته یکم توسعه دادم. به دلیل اهمیت محرمانگی اطلاعات نمیتونم در این مقاله از tableهایی که برای پذیرش24 استفاده کردم را ذکر کنم ولی یک نمونه ساده شده از روش مورد استفاده در همراه‌پی را تشریح میکنم و سعی میکنم به روشی بیان کنم که هم ساده باشه و هم جزییات فنی دقیق بیان بشه.تشریح مساله و چالش های اون:ما تو یک نسخه قدیمی از همراه‌پی از دیتابیس Mysql Percona Xtradb cluster استفاده میکردیم یک فورک از Mysql هست و یکی از چالش هایی که داشتیم مربوط به آمار تراکنش های هر کاربر به تفکیک نوع تراکنش بود. البته چالش فقط برای تراکنش نبود برای تمام آمارهای سیستم بود ( مثلا آمار دستگاه هایی که عملیات پرداخت را انجام دادن به تفکیک دسکتاپ و موبایل و نوع سیستم عامل و ...). حالا شاید از خودتون بپرسید این که چالشی نداره با یک کوئری میشه تمام این اطلاعات را به دست آورد. بله درسته ولی اگر تعداد رکوردهای جدول چند میلیون باشه و تعداد کاربران سیستم هم زیاد و تعداد درخواست های آماری به صورت هم زمان زیاد باشه چی ؟ قطعا جواب منفیه و روش فعلی اصلا جوابگوی کار ما نیست.در Postgresql یک ویژگی به نام Materialized View وجود داره که جواب کار ما هست ولی Mariadb/Mysql چنین ویژگی نداریم. البته یک پروژه تولید شده بود به نام Flexview که یک سری جداول موقت برای نگه داری اطلاعات آماری تولید میکرد و در نهایت Depricate شد.راه حل چی بود ؟راه حل این مساله این بود که ما یک سری جداول آماری داشته باشیم و به صورت تدریجی آمارهای اون را به‌روزرسانی کنیم و به جای کوئری روی table های اصلی، کوئری را روی table های آماری اجرا کنیم. به عنوان مثال آمار تعداد تراکنش های هر روز هریک از کاربران. روند کار هم به این شکل هست که ما کوئری های اصلی را یک بار اجرا میکنیم و نتایج اون را در این tableها نگه داری میکنیم و در یک بازه زمانی مشخص اون کوئری ها را اجرا میکنیم تا مجدد بروز رسانی اطلاعات انجام بشه. شاید از خودتون بپرسید این که باز همون کوئری ها را اجرا میکنه و بهینه نیست. در ادامه روش کار را توضیح میدم که چطور این مساله هم حل میشه.برای درک بهتر یک مثال میزنم:تعداد کاربر : 50000میانگین تعداد تراکنش های هر کاربر در روز: 25انواع تراکنش : واریز – برداشت – عودت وجهمیانگین تعداد رکوردها در روز : 000/50 * 25 = 000/250/1میانگین تعداد رکوردها در ماه : 000/500/37حالا تصور کنید تعداد زیادی درخواست در روز برای آمارهای روزانه/ هفتگی/ ماهانه خودشون را به تفکیک نوع تراکنش و... بیاد به سمت جدول تراکنش ها که نتیجه‌ی اون میشه کندی و گاهی اوقات از دسترس خارج شدن سرور و یا کمبود منابع و هزینه های اون.ماهیت مساله این هست که تعداد تراکنش روز گذشته هیچ وقت تغییر نمیکنه و پایان هر روز دیگه مشخصه که هر کاربر چقدر تراکنش داشته و تعداد تراکنش روز جاری هم به صورت افزایشی هست و هیچ وقت تعداد تراکنش ثبت شده در جدول تراکنش ها کمترنمیشه پس میشه به این نتیجه رسید که اگر ما آمار تعداد تراکنش روزانه ی هر کاربر را در یک جدول دیگه ذخیره کنیم دیگه نیازی نیست برای روزهای گذشته و حتی روز جاری تا زمان جاری، کوئری آماری را روی جدول اصلی تراکنش ها اجرا کنیم ( تصور کنید که چقدر فشار روی دیتابیس کم میشه و چقدر سرعت افزایش پیدا میکنه ? )خب از تئوری مساله بیام سراغ مبحث عملی با ذکر مثال :ما 3 جدول طراحی میکنیم به نام های :Transactions : جدول اصلی تراکنش هاTransactions_summary : جدول آماری تراکنش هاsummaries_updates : توی این جدول اطلاعات آخرین بروز رسانی را نگه داری میکنیم تا آپدیت های آمار به صورت تدریجی انجام بشه.اگر تصاویر کیفیت لازم را ندارند میتونید به کدهای داخل گیت مراجعه کنیدجدول transactions :در این جدول تراکنش های اصلی نگه داری میشود. در این مثال برای اینکه مساله قابل فهم تر باشد طراحی جداول خیلی ساده انجام شده است.جدول transactionsجزییات جدول transactionsجدول transactions_summary:در این جدول خلاصه آمارهای جدولtransactions نگه داری میشود.جدول transactions_summarytransactions_summaryییات جدول نکته ی مهم که در این جدول وجود داره وجود کلید unique هست به نام tr_summary_unq که از ترکیب چند فیلد تشکیل شده.اگر دقت کنم در داده های آماری مساله ی ما برای هر کاربر در هر دوره ی زمانی تنها سه رکورد یکتا وجود داره.به عنوان مثال کاربر 1 در روز فقط میتونه 3 رکورد برای transaction_type های مختلف داشته باشه. در ادامه بیشتر توضیح میدم.جدول summaries_updates:در این جدول تاریخ و زمان آخرین آپدیت جدول آماری را نگه داری میکنیم. فرض کنید ما چندین جدول آماری برای موارد مختلف داریم که باید اطلاعات آخرین بروز رسانی هر کدام را نگهداری کنیم.جدول summaries_updatesدر ادامه باید یک سری داده ی تصادفی را در جدول transactions اضافه کنیم که بنده برای این مثال از فریم ورک flask استفاده کردم و کد اونو توی گیت هابم قرار میدم، شما هم میتونید از هر ابزاری برای این کار استفاده کنید. حتی میشه از procedure ها هم برای این کار استفاده کرد.تولید داده های تصادفی برای جدول transactionsدر کد بالا ما میخوایم 80% از رکوردها از نوع incoming  15% از نوع outgoing  5% از نوع refund باشند که با استفاده از متد choices() انجام شد.بعد از اتمام این مرحله دیگه کامل در mariadb/mysql هستیم و وارد مبحث اصلی میشیمما ابتدا از نوشتن اولین function شروع میکنیمدر اصل کار این تابع این هست که از جدول summaries_updates چک میکنه آیا سابقه ای از آپدیت جدول خلاصه آمار مورد نظر ما وجود داره یا خیر. اگر وجود داره که تاریخ و ساعت آخرین آپدیت اون جدول را میده و اگر وجود نداره تاریخ 200 روز قبل را میده و یک رکورد در جدول summaries_updates ثبت میکنه . شاید بپرسید چرا 200 روز ؟ این یه عددی هست که شما میتونید تغییرش بدید.من فرض را بر این گذاشتم که دیتای جدول برای کمتر از 200 روز هست.همانطور که در پارامتر این تابع هم مشخص هست فقط یک ورودی از نوع varchar داره که اسم جدول مورد نظر ما ( در این مثال transactions_summary ) است.درمرحله ی بعد ما باید یک Procedure بنویسیم که یک aggregation query اجرا کنه و نتیجه ی اون را در جدول transaction_summary بریزه3 نکته ی مهم در این Procedure وجود داره :اون شرطی هست که هر بار این Procedure اجرا میشه نره کل جدول را اسکن کنه و از تاریخ و ساعت آخرین آپدیتش شروع به بروز رسانی کنه ( خط 17 و 18 ). با این حرکت فقط برای اولین بار کل جدول اسکن میشه و دفعات بعد که این Procedure صدا زده میشه دیگه کل جدول درگیر نمیشهخط 26 تا 28 که ما چک میکنیم اگر رکورد تکراری وجود داشت ما داده های آماریمون را update میکنیم. به دلیل این که در ادامه میبینید ما این Procedure را هر 60 ثانیه صدا میزنیم و ممکنه در جدول transactions ما رکورد جدیدی مربوط به اون روز ثبت شده باشه که نیاز است آپدیت انجام بشه. شاید بپرسید داده تکراری چی هست. با ذکر یک مثال ساده توضیح میدم. برای دوره ی زمانی daily هر user_id بیشتر از یک رکورد  در روز برای تراکنش هایی از نوع incoming نمیتونه داشته باشه. اگر از قبل این رکورد وجود داشته باشه یعنی باید به داده های آماری اون بروز رسانی بشه تا رکورد اضافه با آمار اشتباه ثبت نشه. خط 29 که تاریخ و ساعت آخرین آپدیت را در جدول summaries_updates ثبت میکنه و دفعات بعد از اونجا به بعد را آپدیت میکنه (آپدیت تدریجی)تا اینجای کار ما function و Procedure مورد نظرمون را پیاده سازی کردیم و باید بریم سراغ مرحله آخر که بروز رسانی جدول است.در اولین خط ما event_scheduler دیتابیس را روشن میکنیم که هر در دوره های زمانی مورد نظرمون Procedure ما را صدا بزنه. در خط های بعدی هم یک event ایجاد میکنیم که هر 60 ثانیه یک بار اجرا بشه. این عدد بستگی به نوع مساله شما ممکنه تغییر کنه و مشخص کننده بازه ی زمانی بروز رسانی آمارها است.شاید بپرسید چرا به جای event از Trigger استفاده نکردم ؟ دلیلش این هست که Procedure ما transactional هست به همین دلیل نمیتونیم از trigger استفاده کنیم.سوال دومی که ممکنه پیش بیاد درمورد duration های weekly/monthly/annual هست. این موارد برای تمرین بیشتر گذاشته شده تا شما updateTransactionSummary  را توسعه بدید.تا اینجای کار با روش کار آشنا شدیم. حالا باید یک تست انجام بدیم که performance کار را نمایش بده. روش تست هم به این شکل هست که ما برای آمار یکسان از دو جدول transactions و transactions_summary یک کوئری میگیریم و زمان پاسخ را باهم مقایسه میکنیمتست روی جدول اولو نتیجه ی کوئریتست روی جدول دومو نتیجه ی کوئریهمانطور که مشاهده میکنید نتایج یکسان ولی تفاوت زمان پاسخ با 25 برابر یا به عبارتی 2500% اختلاف اون هم روی فقط 200/000 رکورد. تصور کنید تعداد رکوردهای جدول اصلی چند ده میلیون باشه، اون زمان کارایی اصلی این روش خودشو نشون میده.از مزایای این روش :سرعت بالافشار خیلی کمتر به سرورمیشه پارتیشن بندی کرد بدون درگیر شدن با محدودیت های پارتیشن بندی در mysql مثل index ها و...قابل اجرا بر روی دیتابیس های قدیمی و یا دیتابیس های در حال استفاده که فشار کوئری های آماری زیادی را تحمل میکنناز معایب این روش :تاخیر در آپدیت آمارها ( قابل تنظیم از 1 ثانیه تا روزانه و ... )شاید گاهی اوقات scheduler دیتابیس کار نکنه و یکم آمار قدیمی بشه و مبجور بشید یه refresh بزنید.شما بگید ?آدرس گیت پروژه : https://github.com/alifattahi/mysql-materialized/</description>
                <category>Ali Fattahi</category>
                <author>Ali Fattahi</author>
                <pubDate>Fri, 22 Apr 2022 12:45:11 +0430</pubDate>
            </item>
            </channel>
</rss>