رساندن یک برنامه Laravel به مرحله production

ترجمه و تالیف : عرفان کاکایی
تاریخ انتشار : 13 خرداد 98
خواندن در 5 دقیقه
دسته بندی ها : لاراول

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

ادغام و گسترش متوالی

ممکن است عبارات «ادغام متوالی» و «گسترش متوالی» را شنیده باشید. بگذارید به شما نشان دهم که این مسئله چرا قرار است روند گسترش شما را تسریع بخشد.

وقتی که شما در حال انتشار برنامه Laravel خود که آماده تولید است می‌باشید، از توابع آزمایش شگفت‌انگیز Laravel استفاده می‌کنید، تا مطمئن شوید که همه چیز طبق انتظار کار می‌کند. شما با نوشتن testهای unit و integration برای برنامه خود، کیفیت کد خود را افزایش می‌دهید و خطر بد عمل کردن و ضعف‌های امنیتی را کاهش می‌دهید. پس اگر در حال حاضر هیچ testای نمی‌نویسید، حال شروع به انجام این کار کنید.

اجرای خودکار آزمایشات

ادغام متوالی (CI = Continuous Integration) وقتی که شما کد خود را به سیستم کنترل نسخه می‌فرستید، آن را می‌گیرد و تمام testهای شما را یک در محیط ساخت از پیش تعریف شده اجرا می‌کند تا مطمئن شود که همه چیز درست کار می‌کند؛ نه تنها در دستگاه توسعه شما، بلکه در یک محیط تولید مانند عالی.

رساندن یک برنامه Laravel به مرحله production

من از Community Edition رایگان و متن باز GitLab برای ساختن زیرساخت مدیریت کد خود استفاده می‌کنم. این ابزار یک پلتفرم CI/CD کاملا قابل پیکربندی را فراهم می‌کند که شامل runnerهایی برای اجرای فعالیت‌ها می‌باشد.

وقتی که کد خود را به شاخه اصلی وارد می‌کنید، GitLab به طور خودکار روند CI را فعال می‌کند. در موقعیت من، GitLab از یک محفظه Docker برای راه‌اندازی محیطی که دقیقا با نیازهای یک برنامه Laravel برابری دارد، استفاده می‌کند و تمام testها را در داخل آن اجرا می‌کند.

شما نه تنها testهای phpunit، بلکه هر زنجیره ابزاری دیگری که می‌تواند باعث بروز خطا یا رفتارهای ناخواسته شود را اجرا می‌کنید. وقتی که GitLab runner هر گونه شکستی را تشخیص دهد، روند آزمایش را لغو می‌کند و نتایج را به شما گزارش می‌دهد.

گسترش

اکوسیستم Laravel یک ابزار پرکاربرد به نام Envoy را فراهم کرده است. شما به راحتی می‌توانید آن را در پروژه خود composer require کنید. تمام روند آن در فایل Envoy.blade.php و در شاخه ریشه پروژه شما، در جایی که می‌توانید فعالیت‌های بر پایه SSH، و دستوراتی که باید در هنگام اجرا انجام شوند را تعریف کنید، اتفاق می‌افتد. پس اگر می‌خواهید routeهای خود را پس از اعمال آخرین تغییرات کد که از مخزن کد شما گرفته می‌شوند cache کنید، فقط باید دستور php artisan route:cache متناظر را در فایل اجرایی Envoy خود اضافه کنید. وقتی که دستور envoy run $taskName را اجرا می‌کنید، فعالیت مشخص شده بر روی سرور از پیش تعریف شده شما از طریق SSH اجرا می‌شود و همه چیز درست پیش می‌رود.

اما شما نمی‌خواهید که هر زمان تغییری در کد شما ایجاد شده است و منتظر سیستم CI مانده‌اید تا گزارش دهد که آخرین مورد بی مشکل بوده است، این دستور را به طور دستی مجددا اجرا کنید. پس پیشنهاد می‌کنم که از گسترش متوالی (CD = Continuous Deployment) سیستم GitLab نیز استفاده کنید.

یک سند کامل درباره نحوه گسترش برنامه Laravel خود به مرحله تولید با استفاده از CI / CD وجود دارد که خواستم در اینجا به آن اشاره کنم. اما وقتی که برای اولین بار آن را خواندم، درک این که بخش Docker در این آموزش چه کاری انجام می‌داد، برایم سخت بود.

رساندن یک برنامه Laravel به مرحله production

پس در اینجا توضیح کوتاهی درباره نحوه کار GitLab، Laravel و Envoy به همراه یکدیگر برای قرار دادن کد شما بر روی وب سرور را مشاهده می‌کنید. وقتی که موارد جدیدی را به GitLab وارد می‌کنیم، GitLab به یک CI / CD runner دستور می‌دهد تا یک محفظه Docker جدید را که توسط Dockerfile در شاخه ریشه پروژه شما تعریف شده است، اجرا کند. در اینجا یک تصویر پایه PHP 7.1 استفاده شده است، برخی پکیج‌ها (مانند Git) نصب شده‌اند و Composer دانلود شده است. پس اساسا هر چیزی که Laravel نیاز دارد در آنجا موجود است. حال می‌توانید هر کاری که می‌خواهید با برنامه Laravel خود انجام دهید. در قدم اول، phpunit و دیگر زنجیره ابزارها اجرا می‌شوند، تا آخرین کد شما در داخل محفظه Docker را آزمایش کنند. اگر این کار با موفقیت انجام شود، محیط Docker از بین رفته، و اگر روند تولید را شروع کنید، مجددا ساخته می‌شود. باز هم با تشکر از Dockerfile، تمام پکیج‌هایی که برای رساندن برنامه خود به مرحله تولید با استفاد از Laravel Envoy Task Runner لازم دارید، حاضر خواهند بود. Dockerfile به PHP و برخی پکیج‌های پایه Composer وابسته است و تمام دستوراتی که شما برای دریافت آخرین کد خود از سرور نیاز دارید را اجرا خواهد کرد.

پس اساسا Docker یک مکان عصبی برای اجرای آزمایشات برنامه خود و اسکریپت‌های گسترش در یک محیط که تمام Dependencyهای مورد نیاز را به همراه دارد، فراهم می‌کند.

بر حسب تجربه شخصی خودم، این‌ها برخی ملاحظات کاربردی دیگر هستند که بهتر است در نظر داشته باشید:

  • مطمئن شوید که تمام دستورات artisan ضروری را در فایل Envoy.blade.php خود اجرا می‌کنید. (مهاجرت دیتابیس، caching، راه‌اندازی مجدد queue worker و...)
  • بررسی کنید که آیا کاربر شما حقوق کافی برای نوشتن شاخه httpdocs بر روی وب سرور شما را دارد یا نه. بسیاری از مشکلاتی که من به آن‌ها بر خوردم، مجوزهای شاخه بوده‌اند.
  • اگر در حال انجام مهاجرت‌های دیتابیس هستید، برنامه خود را قفل کنید (آن را در حالت نگهداری (maintenance) قرار دهید) تا مطمئن شوید که هیچ‌گونه تناقص دیتابیس بروز نمی‌دهد.

کد خود را بهینه سازی کنید

در هنگام توسعه داخلی، ممکن است در ابتدا به کد بهینه‌سازی شده فکر نکنید. و البته این مسئله عملا در محیط داخلی شما اهمیتی ندارد. اما حال به پیامدهای رساندن برنامه خود به مرحله توسعه فکر کنید. نه تنها شما، بلکه بسیاری کاربران دیگر هم از برنامه شما استفاده خواهند کرد. حال شما ممکن است مقیاس زیرساخت‌های سرور خود را افزایش دهید، تا تمام درخواست‌های همزمان را مدیریت کنید، یا این که می‌توانید کد خود را بهینه‌سازی کنید تا آن را قادر سازید که به مدت زمان بیشتر، و بر روی زیرساخت‌های کمتری اجرا شود. این کار می‌تواند از هدر رفتن مقداری زیادی هزینه جلوگیری کند.

کوئری‌های دیتابیس را کاهش دهید

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

از caching استفاده کنید

شما همچنین باید کاربرد caching در برنامه Laravel خود را در نظر بگیرید. اگر در حال توسعه یک برنامه انجمن هستید که کاربران می‌توانند در آن بر روی کانال‌هایی مشخص پست ارسال کنند، نیازی نخواهد بود تا کانال‌ها را در هنگام هر بار بازدید یک صفحه دریافت کنید. فقط یک بار آن را بارگذاری کنید و آن را در Redis یا Memcached ذخیره کنید، تا وقتی که مدیر موارد جدیدی را اضافه کند. این کار با Laravel بسیار ساده است و شما را از تعداد زیادی کوئری و بارگذاری دیتابیس نجات می‌دهد.

از بهینه سازهای داخلی Laravel استفاده کنید

Laravel یک سری دستورات بهینه‌سازی کد artisan فراهم کرده است که می‌توانید استفاده کنید. فقط آن‌ها را در فایل Envoy.blade.php قرار دهید تا مطمئن شوید که هر زمان یک نسخه جدید از برنامه خود را بر روی سرور تولید قرار می‌دهید، اجرا می‌شوند.

  • Route کردن caching: php artisan route:cache
  • پیکربندی caching: php artisan config:cache
  • بهنیه‌سازی بارگذاری خودکار Composer: composer install --optimize-autoloader

صف‌ها

گاهی حس می‌کنم که jobها و اعلانات قابل صف‌بندی، دست پایین گرفته‌ شده‌ترین ویژگی در Laravel هستند. به این وضعیت فکر کنید: مشتری شما یک سفارش در فروشگاه آنلاین بر پایه Laravel شما قرار می‌دهد و بر روی دکمه «خرید» کلیک می‌کند. برنامه شما چه کاری انجام خواهد داد؟ احتمالا چندین کار مانند:

  • ارسال یک ایمیل تایید به مشتری.
  • ارسال یک اعلانات به کانال Slack شما.
  • اضافه کردن سفارش به دیتابیس.
  • و...

اما در حالیکه شما تمام این کارها را انجام می‌دهید، مشتری شما انتظار دارد به صفحه «سفارش شما ثبت شد» منتقل شود. حال به بدترین موقعیت فکر کنید: با توجه به این که سرور ایمیل شما مشکلاتی دارد، پس از صبر کردن برای مدتی طولانی، صفحه همین طور بارگذاری شده و بارگذاری می‌شود و در نهایت مشتری شما با یک خطای HTTP Error 500 (timeout exception) مواجه می‌شود. این مسئله برای شهرت فروشگاه شما بسیار بد خواهد بود. اما حتی اگر به وضعیت معمولی نگاه کنید که چند ثانیه زمان برای اتصال به سرور SMTP یا Slack API نیاز خواهد بود، کاربر شما آن ثانیه‌ها را منتظر خواهد بود.

رساندن یک برنامه Laravel به مرحله production

سیستم صف Laravel طراحی شده است تا یک پاسخ را در سریع‌ترین زمان ممکن به کاربر تحویل دهد و به workerهای پس‌زمینه اجازه دهد تا کارهای متمرکز بر روی زمان را انجام دهند. به علاوه، Laravel Horizon که یک پکیج رسمی و متن باز برای برنامه Laravel شما است، به شما بینش خوبی بر روی صف‌ها و عملیات‌های شکست خورده یا موفقیت‌آمیز می‌دهد.

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

Log کردن

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

نتیجه گیری

این‌ها تجربیات و نکاتی بودند که می‌خواستم درباره رساندن یک برنامه Laravel به مرحله تولید به شما بگویم. در اینجا نیز یک خلاصه کلی از آن را مشاهده می‌کنید:

  • از کنترل نسخه (مانند Git) و CI / CD (مانند GitLav و Docker) برای آزمایشات و گسترش‌های خودکار استفاده کنید.
  • وقتی که به عملیات‌هایی می‌رسید که باید در جهت اجرای برنامه شما بر روی سرور‌های زنده اجرا شوند، از Envoy استفاده کنید.
  • کوئری‌های دیتابیس را کاهش دهید در جایی که می‌توانید، از caching استفاده کنید.
  • دستورات بهینه‌سازی داخلی Laravel و Composer را اجرا کنید.
  • در هر جایی که ارسال یک پاسخ به کاربر شما بیش از حد زمان خواهد برد یا این که می‌خواهید رد فعالیت‌های موفق / شکست خورده را بگیرید، از صف‌ها استفاده کنید.
  • Logging را فعال کرده، و به فایل‌های لاگ نگاهی داشته باشید.

منبع

دیدگاه‌ها و پرسش‌ها

برای ارسال نظر لازم است ابتدا وارد سایت شوید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید