Các bạn đã xếp hàng (hình) chưa ?

Hàng đợi là cái quái gì ?

Đơn giản có nghĩa là khi bạn ra tiệm mua hàng nếu quá đông người theo văn minh của tây lông thì phải xếp hàng thằng nào vào trước mua trước rồi té, thằng nào vào sau xếp hàng sau mua sau ra sau (FIFO - First In First Out). Hàng đợi cho phép bạn trì hoãn xử lý một hoặc một số công việc ví dụ như gửi email sau khi mua hàng sau 5 phút nhằm tăng tốc độ xử lý của ứng dụng.

Ở một ví dụ khác: Giả sử các bác có thằng cu tên Bi và các bác sai nó ra circle K mua hộ hộp durex về thổi, đồng thời vợ bác đòi nó đi mua dao cạo râu và anh các bác thì đang tám chuyện với William Cường chờ cu Bi mua giấy đem về. Như các bác thấy, nếu để cu Bi chạy đi mua đồ cùng 1 lúc ví dụ chạy lên Q12 mua durex sau đó về Q7 mua dao cạo râu rồi lại chạy lên Hóc Môn mua giấy vệ sinh thì các bác phải đợi sau khi đi mua xong toàn bộ cu Bi mới về nhà ở Q3 đưa cho bác, vợ bác, anh bác. Thay vì thế các bác nên lên cho nó cái list và để cho cu Bi tự kiểm tra rồi mua bao cho xong chạy về đưa cho bác, mua dao cạo râu rồi chạy về đưa vợ bác, và mua giấy về xong chạy về đưa cho anh bác. Các bác không cần phải đợi toàn bộ quá trình đi mua đồ của cu Bi mới có hàng xài.

Ở một thế giới khác, các bác có thể dùng hàng đợi để xử lý các tác vụ nặng như gửi email, xì-pem faceboob...vv...

Bài viết này sẽ sử dụng những gì ?

Tui cần làm những gì để tiếp cận ?

Đương nhiên là phi vô đọc document trên trang chủ Laravel - Queue rồi.
Demo kèm theo bài viết này sẽ một cái app nhỏ nhỏ gửi email nên các bác cũng cần nghía qua Laravel - Email

Bắt đầu gõ

Clone hộ em cái app laravel sau đó đặt vhost của em là (http://thiendia.app) rồi config trong file .env chọn email driver = log cho lẹ đỡ đau não.

MAIL_DRIVER=log

email template ở resource/views/email/hi.blade.php

<h3>Em ạ các bác</h3>

Không dùng hàng đợi

em phang luôn trên routes.php cho lẹ nên các bác đừng chửi e code lầy. Mở hộ em routes.php ra tạo 1 cái route mới. Trước tiên em sẽ gửi email không dùng hàng đợi

Route::group(['middleware' => ['web']], function () {

    Route::get('/email',function(){
        \Log::info("Send email without Queues started");
        \Mail::send('email.hi', [], function ($message) {
            $message->from('me@xvideos.com', 'Huy Huynh');
            $message->to('you@thiendia.com');
        });
        \Log::info("Send email without Queues finished");
    });

});

truy cập vào url : [yourdomain.xxx]/email sau đó mở laravel.log lên

[2016-03-29 03:58:52] local.INFO: Send email without Queues started  
[2016-03-29 03:58:52] local.DEBUG: Message-ID: <27af6a99bd67ef04fd7ddfcc1ada08a8@thiendia.app>
Date: Tue, 29 Mar 2016 03:58:52 +0000
From: Huy Huynh <me@xvideos.com>
To: you@thiendia.com
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<h1>Em ạ các bác</h1>  
[2016-03-29 03:58:52] local.INFO: Send email without Queues finished  

Tất cả các tác vụ đều chạy tuần tự. Vậy nếu như phải gửi khoảng 10k email các bác phải đợi hệ thống gửi, thay vì đó ta sẽ dùng hàng đợi.

Hàng đợi không delay

Em có tạo sẵn AWS SQS các bác google để biết thêm về SQS hộ em

config SQS tại config\queue.php

'sqs' => [
            'driver' => 'sqs',
            'key' => 'your-public-key',
            'secret' => 'your-secret-key',
            'prefix' => 'https://sqs.us-east-1.amazonaws.com/your-account-id',
            'queue' => 'your-queue-name',
            'region' => 'us-east-1',
        ],

.env

QUEUE_DRIVER=sqs

ở đây em xài SQS nên cần package aws sdk của amazon nên mở command line run lệnh:

composer require aws/aws-sdk-php
php artisan make:job SendEmail

mở file SendEmail.php vwaf generate ra

<?php

namespace App\Jobs;

use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendEmail extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        \Mail::send('email.hi', [], function ($message) {
            $message->from('me@xvideos.com', 'Huy Huynh');
            $message->to('you@thiendia.com');
        });
    }
}

routes.php

Route::get('/email', function () {
        \Log::info("Send email with Queues started");
        dispatch(new App\Jobs\SendEmail());
        \Log::info("Send email with Queues finished");
    });

ở command line chạy lệnh để laravel listen message được gửi trả về từ SQS để call Jobs

php artisan queue:listen

truy cập lại vào [yourdomain.xxx]/email và vào laravel.log để xem kết quả

[2016-03-29 04:35:10] local.INFO: Send email with Queues started  
[2016-03-29 04:35:12] local.INFO: Send email with Queues finished  
[2016-03-29 04:35:15] local.DEBUG: Message-ID: <4a4db293b8d4f568272ceb8ba949d1bf@swift.generated>
Date: Tue, 29 Mar 2016 04:35:15 +0000
From: Huy Huynh <me@xvideos.com>
To: you@thiendia.com
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<h1>Em ạ các bác</h1>

Hành động gửi email sẽ chạy sau khi các bác đặt lệnh gửi email.
Với hàng đợi các bác có thể xử lý các tác vụ nặng mà không cần phải chờ đợi, gián đoạn trải nghiệm của người dùng trên website của các bác.

Bây giờ ta thử đặt delay của các task

hi.blade.php

<h1>Em ạ các bác - Delay {{ $delay }}</h1>

SendEmail.php

<?php

namespace App\Jobs;

use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendEmail extends Job implements ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    public $delay;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($delay)
    {
        $this->delay = $delay;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        \Mail::send('email.hi', ['delay' => $this->delay], function ($message) {
            $message->from('me@xvideos.com', 'Huy Huynh');
            $message->to('you@thiendia.com');
        });
    }
}

routes.php

Route::get('/email', function () {
        \Log::info("Send email with Queues started");
        dispatch((new App\Jobs\SendEmail(120))->delay(120));
        dispatch((new App\Jobs\SendEmail(30))->delay(30));
        dispatch((new App\Jobs\SendEmail(60))->delay(60));
        \Log::info("Send email with Queues finished");
    });

Chạy lại một lần nữa và xem log

[2016-03-29 04:45:01] local.INFO: Send email with Queues started  
[2016-03-29 04:45:03] local.INFO: Send email with Queues finished  
[2016-03-29 04:45:36] local.DEBUG: Message-ID: <84a4f7e5238f5d05ed83fa1b60e2a67c@swift.generated>
Date: Tue, 29 Mar 2016 04:45:36 +0000
From: Huy Huynh <me@xvideos.com>
To: you@thiendia.com
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<h1>Em ạ các bác - Delay 30</h1>  
[2016-03-29 04:46:16] local.DEBUG: Message-ID: <1ddba85701af5c85d6c44cff2e80b47c@swift.generated>
Date: Tue, 29 Mar 2016 04:46:16 +0000
From: Huy Huynh <me@xvideos.com>
To: you@thiendia.com
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<h1>Em ạ các bác - Delay 60</h1>  
[2016-03-29 04:47:06] local.DEBUG: Message-ID: <2ae01f89d068003a94c5f3193b3715c5@swift.generated>
Date: Tue, 29 Mar 2016 04:47:06 +0000
From: Huy Huynh <me@xvideos.com>
To: you@thiendia.com
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<h1>Em ạ các bác - Delay 120</h1>

Theo như sắp xếp của chúng ta ở file routes task delay 120 > 30 > 60 nhưng khi xem log task nào có delay thấp nhất sẽ chạy trước tiên.

Tổng kết

Qua bài viết này em giới thiệu sơ bộ về hàng đợi, có thể bài viết của em hơi khó hiểu và có thiếu sót ở 1 vài chỗ mong các bác bỏ qua, hy vọng nó sẽ giúp các bác trong dự án thực tế. Em đã từng áp dụng hàng đợi trên nhiều dự án khác nhau và kết quả mang lại làm em rất hài lòng. Trong phần tiếp theo em sẽ giới thiệu về AWS SQS để bổ sung thiếu sót cho bài viết này.
Ngoài ra các bác không thích dùng SQS có thể tham khảo thêm các phương thức khác mà Laravel hỗ trợ cho hàng đợi. Đối với riêng em em thấy AWS awesome vl tuy giá mắc vãi :v

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Huy Huỳnh

2 bài viết.
1 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
7 9
Callbacks là gì ? Callbacks là nền tạng của lập trình không đồng bộ Javascript, nếu bạn đã quen làm việc với với Javascript chắc hẳn không còn lạ...
Huy Huỳnh viết hơn 2 năm trước
7 9
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
2 bài viết.
1 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!