ارسال ایمیل انبوه با استفاده از صف در لاراول

یکی از کارهای این هفته من نوشتن ماژول ارسال ایمیل به ۳۰۰۰ تا ۵۰۰۰ کاربر میشد، برای همین تصمیم گرفتم که مراحل این کار ساده رو بصورت یک پست در وبلاگم قرار بدم.
برای حل مساله از queue لاراول استفاده کردم، حالا اگه سوال براتون پیش اومده صف چی هست با یک مثال براتون می گم:
فرض کنید شما وارد یک فست فود می شید و سفارش یک پیتزا می دید و هزینه و پرداخت می کنید ولی خب بلافاصله پیتزا شما آماده نمیشه بلکه سفارش پیتزای شما به افرادی که مشغول درست کردن پیتزا هستند داده می شه و بعد از آماده کردن پیتزا، تحویل شما داده می شه.
Queue هم همین طور کار می کنه که شما یکسری وظایف بهش می دید و صف تک تک کارها رو انجام می ده.
برای تنظیم صفی که می خواهید استفاده کنید باید در فایل env در مقابل متغیر QUEUE_DRIVER یا در فایل config/queue.php مشخص کنید.
بطور پیش فرض لاراول از sync استفاده میکنه که یعنی بصورت همزمان کارها انجام می شه و صفی نیست و بیشتر برای سیستم های لوکال کاربرد داره و در حالت واقعی باید یکی از سیستم های زیر رو استفاده کنید.
پکیج مورد نیاز |
نام صف |
استفاده از دیتابیس بعنوان صف |
DataBase |
aws/aws-sdk-php 3.0 |
Amazon SQS |
pda/pheanstalk ~3.0 |
Beanstalkd |
iron-io/iron_mq ~2.0|~4.0 |
IronMQ |
predis/predis 1.0 |
Redis |
من از سرویس SQS آمازون استفاده کردم که یکی از بهترین سرویسهای آمازون هست، ولی در نهایت همه این سیستمها یک کار مشابه برای ما انجام میدهند.
در این بخش من فرض میکنم که لیست ایمیلی از کاربران به طول ۳۰۰۰ ایمیل آدرس از دیتابیس دریافت کردید و برای کم کردن خطاها و مشکلات باید این لیست به لیست های کوچکتر ۱۰۰ تایی تقسیم کرد تا به خطای time out بر نخوریم.
در فایل route.php برای تست کدهامون، آدرس زیر رو وارد می کنیم:
1 2 3 |
Route.php Route::get(‘email/sendemail’, ‘EmailController@sendEmail’); |
فایل کنترلر
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php namespace App\Http\Controllers; class EmailController extends Controller { Public function sendEmail (){ $emailList = [‘example@mail.com’, ‘name@example.com’,......] if (!empty($emailList)) { $emailListChunks = array(); $emailListCount = count($emailList); $offset = 0; do { $emailListChunks[] = array_slice($emailList, $offset, 100); $emailListCount -= 100; $offset += 100; } while ($emailListCount > 0); foreach ($emailListChunks as $emailChunk) { Mail::queue('emails.template, ['text' => ‘your text’], function($message) use ($emailChunk) { $message->from(sajad.ayooby@gmail.com', 'Ayooby.ir'); $message->subject(‘Laravel is awesome’); $message->bcc($emailChunk); }); } } } } |
در خطهای ۱۵ تا ۱۸ آرایه خودمون رو ۱۰۰ تایی تقسیم کردیم هر چند راه های زیادی برای تقسیم آرایه هست که می تونید به stackoverflow مراجعه کنید و راههای پیشنهادی دیگه رو ببینید.
در خط ۲۳ متد queue رو استفاده کردیم، در ورودی اول فایل view رو مشخص میکنیم که در اینجا emails.template رو وارد کردیم و یک متغیر به نام text که در فایل view میتونیم به text$ از اون استفاده کنیم، در مرحله بعد باید فرستنده و گیرنده ایمیل مشخص بشه که در یک تابع closure قرار میدیم.
برای مشخص کردن فرستنده ایمیل از متد message->from$ استفاده کردیم و همون طور که مشخصه subject برای عنوان ایمیل و در نهایت من از bcc استفاده کردم جهت احترام به مشتری ها!
خب حالا وارد آدرس http://example.com/email/sendemail بشید با این کار ایمیل ها وارد صف می شن، ولی خب باید به لاراول دستور اجرای صف رو بدیم، یعنی تا اینجا ما سفارش پیتزا رو دادیم و نیاز داریم که دستور پخت پیتزا رو به آشپز بدیم، برای اجرای دستور شروع پخت چند کار میشه کرد.
راه ساده استفاده از دستور
1 |
php artisan queue:work |
این دستور یکبار همه کارهای صف رو انجام می ده.
برای گوش دادن همیشگی به صف می تونید از دستور زیر استفاده کنید:
1 |
php artisan queue:listen |
خب این دو دستور رو هر بار توی ترمینال بزنید، که کار دلچسبی نیست پس بهتره روش بهتری استفاده کنید و می تونید از kernel و cronjob استفاده کنید، همه کارها بصورت اتوماتیک انجام بگیره.
در فایل app/Console/Kernel.php کد زیر رو وارد کنید
1 2 3 4 5 6 |
protected function schedule(Schedule $schedule) { ….. $schedule->command('queue:listen')->dailyAt('09:45'); …. } |
این دستور هر روز ساعت ۹:۴۵ دستور queue:listen رو اجرا می کنه.شما میتونید از cronjob هم استفاده کنید به این صورت که
1 |
$schedule->command('queue:listen')->cron('* * * * * *'); |
Cron یک سرویس زمانبندی است که وظیفه اجرای روتینهای خاصی را در زمان مشخص بر عهده دارد.
درباره cronjob بیشتر بدونید
برای راحتی کار می تونید از سرویسهای ایمیلی مثل mailgun یا mail chimp استفاده کنید که هر دو سرویسهای رایگان در اختیار شما قرار میده و میتونید آمار خوبی از ایمیلهاتون داشته باشید که هر دو این سرویسها توسط لاراول پشتیبانی میشه.