هر بار که سایت را آپدیت می‌کنید باید چند دقیقه‌ای down باشد؟ این دیگر قابل قبول نیست. با روش‌های مدرن Deployment می‌توانید بدون هیچ قطعی‌ای کد جدید را به سرور برسانید، کاربران هیچ خطایی نبینند، و در صورت بروز مشکل در چند ثانیه به نسخه قبلی بازگردید. Zero Downtime Deployment دیگر یک لوکس نیست، بلکه یک ضرورت برای هر سایت جدی است.

در این مقاله انواع روش‌های zero downtime deployment را بررسی می‌کنیم: از روش‌های ساده‌ای که امروز می‌توانید اجرا کنید تا تکنیک‌های پیشرفته‌تری که برای تیم‌های بزرگ استفاده می‌شوند. همچنین نکات مهمی مانند مدیریت migration های دیتابیس را که اغلب نادیده گرفته می‌شوند توضیح می‌دهیم.

چرا Downtime مشکل جدی است؟

شاید ۵ دقیقه downtime ناقابل توجه به نظر برسد. اما بیاید واقعی‌تر نگاه کنیم:

  • از دست رفتن درآمد: برای فروشگاه آنلاین، هر دقیقه downtime مستقیماً به معنی از دست رفتن سفارش است
  • خطای کاربر: کاربری که در وسط پر کردن فرم یا تراکنش با خطای ۵۰۳ مواجه می‌شود، احتمالاً برنمی‌گردد
  • اثر بر سئو: گوگل اگر در زمان crawl با خطا مواجه شود، آن صفحه را ممکن است حذف کند
  • آسیب به اعتبار: کاربران اعتماد کمتری به سایتی دارند که گاهی در دسترس نیست
  • هشدارهای monitoring: downtime هشدارهای پیاپی ایجاد می‌کند که تیم را از کارهای مهم‌تر باز می‌دارد

مفهوم کلیدی: Atomic Deployment

پایه تمام روش‌های zero downtime، مفهوم Atomic Deployment است. یعنی تغییر از نسخه قدیمی به جدید باید به صورت آنی و بدون حالت بینابین اتفاق بیفتد. کاربر یا نسخه قدیم را می‌بیند یا نسخه جدید را. هیچ لحظه‌ای نباشد که نیمی از فایل‌ها قدیم و نیمی جدید باشند.

روش اول: Symlink Switching

ساده‌ترین و کاربردی‌ترین روش برای سرور تکی است. ایده اصلی این است که به جای ویرایش مستقیم فایل‌های live، نسخه جدید را در یک پوشه جداگانه آماده کرده و سپس با یک تغییر atomic از لینک نمادین (symlink) به آن اشاره کنیم.

ساختار پوشه‌ها:

  • /var/www/releases/20240101_v1/ — نسخه اول
  • /var/www/releases/20240201_v2/ — نسخه دوم (آماده‌شده)
  • /var/www/current/var/www/releases/20240101_v1/ — لینک نمادین فعلی

وقتی می‌خواهید نسخه جدید را deploy کنید:

  1. نسخه جدید را در پوشه جدید کامل آماده کنید (composer install، npm build، و غیره)
  2. تست کنید که همه چیز کار می‌کند
  3. فقط یک دستور: ln -sfn /var/www/releases/20240201_v2 /var/www/current
  4. این تغییر آنی است و Nginx یا Apache بلافاصله از پوشه جدید سرو می‌کند

برای rollback، فقط symlink را به نسخه قبلی برگردانید. کل فرایند چند ثانیه طول می‌کشد.

روش دوم: Blue-Green Deployment

این روش برای محیط‌هایی با چند سرور استفاده می‌شود. دو محیط یکسان دارید که Blue و Green نام دارند:

  • Blue: محیط فعلی که ترافیک زنده را هندل می‌کند
  • Green: محیط آماده‌سازی که در حال حاضر idle است

فرایند deployment:

  1. نسخه جدید را روی Green deploy کنید
  2. روی Green تست کنید — کاملاً مطمئن شوید
  3. Load Balancer را تنظیم کنید که ترافیک را از Blue به Green هدایت کند
  4. اکنون Green محیط live است و Blue خاموش یا standby است

مزیت بزرگ: اگر بعد از deploy مشکلی پیدا شود، Load Balancer را برمی‌گردانید تا ترافیک به Blue هدایت شود. Rollback آنی است بدون هیچ downtime.

در deployment بعدی، نقش‌ها عوض می‌شوند: روی Blue که اکنون idle است نسخه جدیدتر را deploy کنید.

روش سوم: Rolling Deployment

این روش برای محیط‌هایی است که چند سرور وب دارند. به جای آپدیت همه سرورها به یکباره، یکی‌یکی آپدیت می‌کنید:

  1. یک سرور را از Load Balancer خارج کنید
  2. آن سرور را آپدیت کنید
  3. health check بزنید — مطمئن شوید کار می‌کند
  4. سرور را به Load Balancer برگردانید
  5. سرور بعدی را همین‌طور آپدیت کنید

در تمام این مدت، بقیه سرورها ترافیک را هندل می‌کنند. کاربران هیچ downtime نمی‌بینند. اما در این روش باید توجه داشته باشید که مدتی نسخه قدیم و جدید به صورت همزمان اجرا می‌شوند، پس باید backward compatibility را رعایت کنید.

روش چهارم: Canary Deployment

در Canary Deployment، نسخه جدید را ابتدا فقط برای درصد کوچکی از کاربران فعال می‌کنید. این «کاربران آزمایشی» (canaries) ریسک را می‌پذیرند تا اگر مشکلی باشد، تأثیر محدود باشد.

فرایند:

  1. نسخه جدید را deploy کنید اما فقط برای ۵٪ ترافیک
  2. metrics را بررسی کنید: خطاها، زمان پاسخ، نرخ تبدیل
  3. اگر همه چیز خوب بود، ترافیک را به تدریج بیشتر کنید: ۲۰٪، ۵۰٪، ۱۰۰٪
  4. اگر مشکلی پیدا شد، فقط ۵٪ تأثیر دیده‌اند و rollback آسان است

این روش برای تغییرات بزرگ که اطمینان کافی ندارید بسیار مناسب است.

ابزارهای Deployment اتوماتیک

Deployer

کتابخانه PHP که به صورت خاص برای deploy کردن پروژه‌های PHP طراحی شده. از symlink strategy استفاده می‌کند، چند سرور را به صورت موازی deploy می‌کند، و دستوراتی مثل composer install، migrations و npm build را خودکار اجرا می‌کند. برای لاراول recipe آماده دارد.

Capistrano

یک ابزار Ruby است اما برای PHP، Python و هر زبان دیگری هم قابل استفاده است. بزرگ‌ترین ابزار deployment در این حوزه است و سال‌هاست در تولید استفاده می‌شود. همان مفهوم symlink switching را پیاده‌سازی می‌کند.

Laravel Envoyer

سرویس SaaS برای deploy کردن اپلیکیشن‌های لاراول. با چند کلیک deployment پیکربندی می‌شود. Health Check قبل از switch کردن symlink، zero downtime migrations و notification در Slack دارد.

GitHub Actions / GitLab CI

با استفاده از CI/CD pipeline می‌توانید deployment را کاملاً اتوماتیک کنید: هر push به branch main یا هر tag جدید به صورت خودکار deploy شود.

Kubernetes

برای محیط‌های containerized (Docker)، Kubernetes ابزار استانداردی است. Rolling updates، blue-green و canary deployment را به صورت بومی پشتیبانی می‌کند.

چالش مهم: Database Migrations

بزرگ‌ترین چالش در zero downtime deployment، تغییرات دیتابیس است. اگر migration جدید بزنید در حالی که هنوز نسخه قدیمی کد اجرا می‌شود (مثلاً در Rolling Deployment)، ممکن است مشکل ایجاد شود.

اصل Backward Compatibility

تغییرات دیتابیس باید backward compatible باشند. این یعنی:

  • اضافه کردن ستون جدید: ایمن است. کد قدیم به ستون جدید کاری ندارد.
  • حذف ستون: خطرناک! اول کد قدیم را آپدیت کنید که دیگر از آن ستون استفاده نکند، deploy کنید، سپس ستون را حذف کنید.
  • تغییر نام ستون: به صورت مستقیم انجام ندهید. ابتدا ستون جدید اضافه کنید، کد را آپدیت کنید که از هر دو بنویسد و فقط از جدید بخواند، deploy کنید، سپس ستون قدیم را حذف کنید.
  • تغییر نوع ستون: مراقب باشید. نوع باید با داده‌های موجود و کد قدیمی compatible باشد.

Expand and Contract Pattern

این الگو برای تغییرات دیتابیس در zero downtime استفاده می‌شود:

  1. Expand: تغییر اضافه کنید بدون اینکه چیزی حذف شود. ستون جدید اضافه کنید، هر دو ستون را پر کنید.
  2. Deploy کد جدید: کد را آپدیت کنید که از ستون جدید استفاده کند.
  3. Contract: وقتی مطمئن شدید همه چیز کار می‌کند، ستون/جدول قدیمی را حذف کنید.

Health Check و Monitoring

قبل از اینکه ترافیک به نسخه جدید هدایت شود، باید مطمئن شوید کار می‌کند:

  • یک endpoint مثل /health بسازید که وضعیت سرویس را برگرداند (وضعیت دیتابیس، Redis، و سایر وابستگی‌ها)
  • Load Balancer یا ابزار deployment باید قبل از switch کردن این endpoint را بررسی کند
  • اگر health check شکست، deploy متوقف می‌شود

Rollback Plan: همیشه راه فرار داشته باشید

حتی با بهترین تست‌ها، ممکن است مشکلی بعد از deploy پیدا شود. برنامه rollback باید:

  • مستند شده و همه تیم از آن آگاه باشند
  • سریع باشد: هدف زیر ۵ دقیقه
  • تست شده باشد: rollback‌ای که هرگز تست نشده شاید کار نکند

با symlink switching، rollback فقط یک دستور است: symlink را به پوشه قبلی برگردانید. با blue-green، فقط Load Balancer را تغییر دهید.

CI/CD: اتوماسیون کامل Deployment

Continuous Integration و Continuous Deployment یعنی هر تغییر کد به صورت خودکار تست می‌شود و deploy می‌شود. مزایا:

  • تست‌ها قبل از deploy به صورت خودکار اجرا می‌شوند
  • خطاهای انسانی در فرایند deploy حذف می‌شوند
  • deploy سریع‌تر و مکررتر می‌شود
  • تیم می‌تواند با اطمینان بیشتر تغییرات کوچک‌تر و مکررتر deploy کند

وردپرس و Zero Downtime

وردپرس به دلیل درهم‌تنیدگی فایل‌ها و دیتابیس، zero downtime deployment پیچیده‌تری دارد. اما با Bedrock (از Roots.io) که یک ساختار مدرن برای وردپرس است، می‌توان از Deployer یا Capistrano برای zero downtime deployment استفاده کرد. در این ساختار، کد وردپرس به عنوان dependency با Composer مدیریت می‌شود و deployment با symlink switching انجام می‌شود.

سوالات متداول

آیا برای یک سایت کوچک هم باید zero downtime داشت؟

اگر مشتری یا کاربر از سایت استفاده می‌کند، بله. حتی برای سایت‌های کوچک، روش symlink switching ساده است و پیاده‌سازی آن یک ساعت وقت می‌گیرد. ارزش این یک ساعت سرمایه‌گذاری اولیه را دارد.

آیا Deployer برای همه فریمورک‌های PHP مناسب است؟

بله، Deployer برای هر پروژه PHP قابل استفاده است. Recipe‌های آماده برای لاراول، Symfony، WordPress و سایر فریمورک‌ها وجود دارد. برای پروژه‌های سفارشی هم می‌توانید recipe خودتان را بنویسید.

تفاوت Blue-Green و Rolling Deployment چیست؟

در Blue-Green، همیشه یک محیط کامل idle است که هزینه بیشتری دارد اما rollback کاملاً آنی است. در Rolling، سرورها یکی‌یکی آپدیت می‌شوند و منابع کمتری لازم است اما در طول deployment، هم نسخه قدیم و هم جدید اجرا می‌شوند که باید backward compatibility داشته باشند.

چطور از CI/CD شروع کنم؟

اگر کد روی GitHub است، GitHub Actions ساده‌ترین شروع است. یک workflow فایل می‌سازید که هر push به main را trigger می‌کند: تست‌ها را اجرا می‌کند، و اگر موفق بود، با SSH به سرور وصل می‌شود و Deployer را اجرا می‌کند. آموزش‌های فراوانی برای این ترکیب وجود دارد.

جمع‌بندی

Zero downtime deployment دیگر ویژگی شرکت‌های بزرگ نیست. با روش‌هایی مثل symlink switching می‌توانید امروز آن را پیاده‌سازی کنید. برای سرورهای چندگانه، Blue-Green یا Rolling Deployment مناسب است. مهم‌ترین نکته فنی، مدیریت صحیح migration های دیتابیس با رویکرد backward compatible است.

یک pipeline اتوماتیک با CI/CD، Health Check قبل از switch و برنامه rollback مشخص، سه ستون یک استراتژی deployment جدی هستند. با این رویکرد می‌توانید با اطمینان کامل و هر بار که لازم است deploy کنید، بدون اینکه کاربران هیچ اخلالی را تجربه کنند.