آموزش صف بندی لاراول و استفاده از queue در هاست اشتراکی ارسال شده در ۰۷ آبان ۱۳۹۶

امروز میخوام یه پست آموزشی بزارم که مشکل خیلی ها هست

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

ببینید سختی کار اونجاست که باید با چند عنوان جدید آشنا بشین که چون شما هاستینگ نداشتین و با سرور هم زیاد کار نکردید احتمالا از طریق مستندات لاراول متوجه صف بندی نمیشین

پس اول عنوان ها رو براتون توضیح مختصر میدم تا متوجه بشین باید چه کاری انجام بدیم

عنوان اول کرون جاب هست

ببینید روی سرورهای مختلف یه سرویسی هست که مثل زمان سنج عمل میکنه یعنی مثلا میتونید بگید هر یک دقیقه یا یک ساعت یا حتی هر ماه یک کار مشخص رو انجام بده این سرویس توی سرور های لینوکسی به اسم کرون جاب (cron job) هست و سرورهای ویندوزی  Task Scheduler و نحوه کاربردشون هم تفاوت نداره از اونجایی که از نظر علما برای سرورها، سیستم عامل به جز لینوکس حرومه پس ادامه کار رو با کرون جاب پیش میریم ولی درعمل تفاوتی ندارن

 

عنوان دومی که باید توضیح بدم Scheduler لاراول هست

این بخش شاید مثل کرون جاب باشه و عملا همون شکلیه و زمان سنج لاراول هست ولی این بخش به تنهایی نمیتونه کار کنه و برای فعال شدن باید آدرسش به کرون جاب سرور داده بشه جلوتر عملی توضیح میدم

 

عنوان سوم ذخیره سازی صف هاست

ببینید شما مثلا میخواین ۱۰۰۰ ایمیل ارسال کنید اگر عادی ارسال کنید سرور نابود میشه و عملا ۹۹۰ تا ایمیل به دست کاربر نمیرسه برای حل این مشکل صف بندی میکنیم ارسال ها رو مثلا میگیم هر ۵ دقیقه ۱۰۰ تا ایمیل ارسال کن حالا برای اینکار باید کدی بنویسیم که ۱۰۰ ایمیل ارسال کنه و این کد رو ۱۰ بار بفرستیم تو صف و توی Scheduler بگیم هر ۵ دقیقه یک صف رو اجرا کن که صف ما اینجا همون کد ارسال ۱۰۰ ایمیل میشه

حالا این صف ها تو لاراول میتونن تو دیتابیس (mysql یا …) یا ردیس (نوعی دیتابیس nosql که رو رم ذخیره میشه) یا … ذخیره بشه که از طریق پوشه config و queue میتونید اینو مشخص کنید. برای شروع کار همون دیتابیس ذخیره کنید بعدا اگه خواستین تغییر بدین

روی database بزارین و کامند php artisan queue:table  و  php artisan queue:failed-table  رو بزنید تا مایگریشن جدول های مورد نیاز درست بشه و بعد هم که کامند مایگریشن بزنید تا جدول ها ساخته بشن اولی برای صف های در انتظار اجرا هست و دومی صف هایی که به هردلیلی اجرا نشدن

 

خوب بریم سراغ انجام کار

تو این مثال من میخوام هرکاربری ثبت نام کرد براش ایمیل بفرستم

تو کنترلر بعد از ثبت نام این کد رو میزنم:

;((Mail::to($user)->queue(new Mail($user, $data

 

فکر نکنم دیگه نیازی به توضیح این باشه این دستور ارسال یک ایمیل رو میفرسته تو صف اگر آشنایی ندارید بخش ارسال ایمیل لاراول رو بخونید.

حالا تو دیتابیس برید میبینید که یه رکورد جدید ثبت شده که مشخص میکنه یک صف در انتظار اجرا داریم

 

بعد باید برم که دستور اجرای صف رو بزنم

توی لوکال همونطور که میدونید با زدن کامند php artisan queue:work در ترمینال میتونید صف ها رو اجرا کنید و مشکلی ندارید

حالا مشکل اینجاست که ما رو سرور که نمیتونیم هی این کامند رو بزنیم تا صف ها اجرا بشن یا اگه هاست اشتراکی داریم که اصلا دسترسی به ssh نداریم پس چیکار کنیم

اینجاست که اون عنوان ها بدردمون میخورن و باید از زمان سنج سرور یا کرون جاب و Scheduler استفاده کنیم

توی کرون جاب هاست اگه بریم همچین چیزی میبینیم:

این دایرکت ادمین هست ولی سی پنل هم تفاوتی نداره (من به خاطر اینکه سی پنل تحریممون کرده و رو سرورهای ایران نصب نمیشه ما هم تحریمش کردیم تا بفهمه همچین تحفه ای هم نیست والا دایرکت ادمین خیلی هم بهتره)

همینطور که میبینید بخشی هست به اسم کامند که باید دستوری که میخوایم سر تایم مشخص اجرا بشه رو میزنیم

و بالاتر دقیقه ساعت و… رو نوشته اگر ما همه رو ستاره بزاریم هر یک دقیقه این کامند ما اجرا میشه اگر دقیقه رو عدد بدیم بقیه رو ستاره هر ساعت یکبار و در دقیقه نوشته شده اجرا میشه اگر ساعت عدد بدیم و بقیه ستاره هر روز یکبار و سر ساعت نوشته شده و به همین ترتیب میتونید زمان سنج رو تنظیم کنید

ما میخوایم هر دقیقه یکبار کامند php artisan queue:work اجرا بشه تا صف ها اجرا بشن برای همین همه رو ستاره میزنیم و توی بخش کامند هم php artisan queue:work رو ولی اجرا نمیشه اینطور چرا؟

چون ما توی ترمینال میریم به آدرس پروژه و php artisan queue:work رو میزنیم که اجرا میشه و تو سرور که فقط هاست ما نیست و باید آدرس هاست خودمون رو بدیم

توی عکس قسمت پایین میبینید که نوشته چطور میتونید کامند بزارید و آدرس هاست ما رو هم نوشته :

/usr/local/bin/php /home/hosseiniza/domains/domain.com/public_html/script.php
/usr/local/bin/curl –silent http://www.domain.com/cron.php > /dev/null
/usr/bin/wget -O /dev/null http://www.domain.com/cron.php

 

خوب ما میخوایم یک دستور php ران کنیم پس مثال اولش بدردمون میخوره

اگه این مثال و مستندات لاراول بخش Scheduler رو نگاه کنیم متوجه میشیم که کامند ما باید اینشکلی بشه تا درست عمل کنه:

php /home/hosseiniza/domains/hosseinizadeh.ir/artisan queue:work >> /dev/null 2>&1

به همین راحتی اگه ما این کامند رو بزاریم تو کرون جاب و ادد کنیم این کامند هر یک دقیقه اجرا میشه ولی صبر کنید این کار مشکل داره و باعث میشه سرور بعد از چند دقیقه داون بشه و رم سرور رو نابود کنید چرا؟

چون هر دقیقه این کامند اجرا میشه بدون غیرفعال شدن یعنی اگه یک ساعت بگذره ۶۰ تا کامند درحال اجرا به این شکل دارید و خودتون و سرورتون رو نابود کردید با این کار

پس چیکار کنیم؟

اینجاست که Scheduler لاراول به دادمون میرسه

برای رفع مشکل باید توی کرون جاب این کامند رو بدیم هر یک دقیقه اجرا بشه:

php /home/hosseiniza/domains/hosseinizadeh.ir/artisan schedule:run >> /dev/null 2>&1

که میاد بخش زمان سنج لاراول رو نگاه میکنه اگر کاری باید انجام بشه انجام میده حالا ما باید کامند queue:work رو توی scheduler لاراول بزاریم تا اجرا بشه

برای اینکار به پوشه app و console و فایل kernel.php میریم و اینجا میتونیم کارهایی که باید با زمان سنج انجام بشه رو وارد میکنیم

شما اینجا داخل فانکشن scheduler هرچیزی میتونید تعریف کنید مثلا هر ماه یکبار پیام های بخش پشتیبانی که از زمانشون ۲ ماه گذشته رو پاک کن:

$schedule->call(function () {
$support = \App\Support::where('time','<',jDate::forge('now - 2 month')->time())->get(['id'])->toArray();
\App\Support::destroy($support);
})->monthlyOn(4, '02:30');

که آخرش من نوشتم monthly که هر ماه یکبار اجرا میشه و همینطوری هرکاری میخواین میتونید تعریف کنید (مستندات رو بخونید)

و همچنین میتونیم queue:work رو هم اینجا تعریف کنیم به این شکل:

$schedule->command('queue:work --daemon')->withoutOverlapping();

$schedule->command('queue:work --daemon')->everyMinute()->withoutOverlapping();

این دوتا کد هیچ تفاوتی ندارن چون تو کرون جاب ما گفتیم هر دقیقه scheduler لاراول اجرا بشه و کارهایی که زمان اجراشون رسیده رو ران کنه پس نوشتن یا ننوشت هر دقیقه تو کرنل تفاوتی نداره برای این کد ولی اگر میخواستیم هر ۲ دقیقه یا بیشتر اجرا بشه باید بنویسیم تو کرنل هر ۲ دقیقه یا زمان های دیگه

خوب آخر کامند میبینید که نوشتم withoutOverlapping که این میاد همون مشکل داون شدن سرور رو حل میکنه یعنی اگه این کامند درحال اجرا نبود اجراش میکنه که باعث میشه همیشه فقط یکبار queue:work داشته باشیم

 

یه نکته رو یادم رفت اضافه کنم اگر میخواستین نتیجه اجرای کرون جاب رو تست کنید میتونید تو هاست که دارین تعریف میکنید یک ایمیل بدین و تعریف کنید که بعد از هربار اجرا یک ایمیل براتون بفرسته و نتیجه رو بگه برای اینکار اون   /dev/null 2>&1 رو بعد از کامند حذف کنید اینکار انجام میشه یعنی کامند کرون جاب رو به شکل زیر قرار بدین

php /home/hosseiniza/domains/hosseinizadeh.ir/artisan schedule:run

ولی بعد از اینکه تست درست بود دوباره غیرفعال کنید ارسال ایمیل رو وگرنه هر دقیقه یک ایمیل براتون میاد و ممکنه برای سرور مشکل درست بشه

بهترین روش برای تسته و هر دقیقه نتیجه اجرای کرون رو براتون ایمیل میکنه و اگه مشکلی باشه میگه و اگه مشکلی نباشه هم ایمیلی با متن زیر دریافت می کنید:

Running scheduled command: ‘/usr/local/bin/php’ ‘artisan’ queue:work –daemon > ‘/dev/null’ 2>&1

 

مشکلات احتمالی:

اگر سرور رو خودتون کانفیگ کردید احتمالا فانکشن های خطرناک رو بستید و اگر proc_open رو بسته باشید کرون جاب اجرا نمیشه پس باید بازش کنید که این مشکل رو بهتون ایمیل میکنه تو نتیجه اجرای کرون جاب اگه نگفت پس فانکشنش غیرفعال نشده

 

اگر دسترسی به ssh دارید میتونید کامندی که تو کرون جاب گذاشتین رو تو ssh وارد کنید و نتیجه رو همونجا ببینید اگه مشکل نداشت تو کرون جاب بزارینش (مشکلات اشتباه نوشتن آدرس رو اینطوری میشه پیدا کرد)

 

اگر روی سرورتون فایروال csf یا هرفایروال دیگه ای نصب کردید باید دسترسی اجرای کامند رو به php بدین

برای اینکار تو آدرس /etc/csf/csf.pignore آخرش exe:/usr/local/bin/php رو بزارید و اگه همزمان از php7 هم استفاده میکنید exe:/usr/local/php71/bin/php-cgi71 رو هم باید بزارید و فایروال رو ریست کنید تا مشکل حل بشه

 

اگر ایمیل رو فعال کردید که نتیجه کرون براتون بفرسته ممکنه با همچین اروری مواجه بشین:

storage/framework/cache/data/27/c1/27c1b23010afdda7ef6fe10d6d10955da1a96e64): failed to open s tream: Permission denied

که برای رفع این مشکل کافیه کش رو پاک کنید توی پوشه storage/framework/cache/data/ برید و هرچی هست پاک کنید یا اینکه توی ترمینال یا ssh کامند زیر رو بزنید:

php artisan cache:clear

 

امیدوارم مفید بوده باشه

موفق و سربلند باشید

برچسب ها: , , ,
نظرات 6 نظر

6 پاسخ به “آموزش صف بندی لاراول و استفاده از queue در هاست اشتراکی”

  1. الیاس گفت:

    ممنون از مطلب کاربردیتون

  2. هدا گفت:

    با عرض سلام و احترام ممنون از وقتی که گذاشتید برای این آموزش، بسیار مفید بود

  3. امیر گفت:

    ممنون عالی بود

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *