Hướng dẫn hàng đợi trong php

Xin chào các bạn, trong bài viết lần này chúng ta sẽ cùng nhau tìm hiểu về hàng đợi (Queue) trong framework Laravel thông qua khái phần khái niệm, cách dùng, tác dụng thực tế của nó đối với trang web của các bạn nha

Hướng dẫn hàng đợi trong php
.

1. Khái niệm

Hàng đợi (queue) là một danh sách những việc cần làm (job) được quản lý theo thứ tự. Khi chúng ta muốn thêm một công việc (job) vào hàng đợi, job phải implement interface Illuminate\Contracts\Queue\ShouldQueue. Hoạt dộng theo nguyên lý FIFO (first in first out), nghĩa là các công việc được đưa vào trước sẽ được xử lý trước.

2. Tác dụng

Trong một trang web, một điều quan trọng sẽ ảnh hưởng đến trải nghiệm sử dụng đó chính là thời gian tải trang (page load), Nếu một trang web có tốc độ tải trang chậm sẽ gây ra cảm giác khó chịu, ức chế đến với người sử dụng. Một phần khiến cho thời gian tải trang tăng lên đó chính là do cách xử lý các tác vụ của trang web đó. Các bạn có thể nghĩ đến việc thay đổi logic xử lý cho tác vụ làm chậm trang web đó, hoặc là bỏ nó đi. Nhưng nếu trong trường hợp tác vụ đó đã được xử lý một các tối ưu và không thể bỏ đi thì các bạn sẽ làm thế nào? Đó đến là lúc các bạn nên sử dụng Queue, queue giúp chúng ta trì hoãn việc xử lý các tác vụ.

3. Các khái niệm cơ bản

Mục đích cơ bản của Queue là vận hành các jobs (công việc) đã được thêm vào trong một queue (các tác vụ theo trình tự hàng đợi). Tiếp theo, queue có thể thuộc về một kết nối cụ thể và kết nối đó có thể thuộc về một queue driver cụ thể được cấu hình với chính kết nối đó. Chúng ta hãy cùng đi qua một số khái niệm nha:

3.1 Queue Drivers

Giống như các các bạn đã sử dụng một driver khác cho việc kết nối cơ sở dữ liệu, bạn có thể chọn từ nhiều queue driver khác nhau. Queue trong Laravel hỗ trợ các cổng kết nối khác nhau như database, beanstalkd, sqs, redis. Queue drivers là nơi được sử dụng để luuw trữ thông tin liên quan đến queue. Ví dụ bạn chọn driver là database thì job mới trong queue đó sẽ được thêm vào bảng jobs trong database của các bạn. Queue cũng cung cấp hai queue đặc biệt cho các mục đích kiểm tra đồng bộ (sync) và null. Queue driver sync được sử dụng để thực hiện một queue job ngay lập tức, trong khi queue driver null được sử dụng để bỏ qua một công việc để nó không thực hiện.

3.2 Queue Connections

Khi bạn cấu hình Queue lần đầu, bạn chỉ cần chỉ định một connection mặc định cần được sử dụng cho việc xử lý queue mặc định. Các connections của Queue các bạn có thể xem chi tiết tại file config/queue.php .

3.3 Jobs

Job trong queue là một tác vụ được hoãn lại từ luồng xử lý chính. Ví dụ khi bạn gửi mail cho người dùng, thì bạn có thể tạo riêng một job để xử lý phần gửi mail đó, bạn có thể trì hoãn tác vụ gửi mail tức thì bằng cách cho vào queue.

3.4 Queue

Khi bạn thêm job vào queue thì các job đó sẽ được thêm vào queue mặc định. Trên thực tế, điều đó vẫn giúp của bạn hoạt động tốt, trừ khi bạn muốn phân chia rõ các queue để thực hiện việc xử lý riêng biệt nhau. Ví dụ bạn vừa muốn xử lý việc gửi mail riêng và việc kiểm tra người dùng lâu không hoạt động thì bạn có thể tạo ra 2 queue riêng biệt có tên là send-emailcheck-user và gán độ ưu tiên cho các queue đó. Nếu bạn cho job vào một queue mặc định thì khi chạy một queue worker để xử lý các job thì chỉ cần chạy

php artisan queue:work

Còn nếu đặt trong các queue riêng biệt thì bạn cần chỉ định queue sẽ được chạy:

php artisan queue:work --queue=send-email

hoặc

php artisan queue:work --queue=check-user

4. Ví dụ

Tiếp theo mình sẽ đưa ra một ví dụ về áp dụng queue trong gửi mail trên Laravel. Trong ví dụ, mình sẽ sử dụng queue driver = database và yêu cầu tạo bảng jobs trong database. Bảng này có tác dụng giữ tất cả các công việc cần phải được xử lý trong khi chạy queue worker. Trước khi chúng ta tiếp tục tạo bảng jobs, hãy thay đổi cấu hình mặc định cho queue từ sync sang database bằng cách thay đổi value của key QUEUE_DRIVER=database trong file .env thay vì thay đổi trong file config/queue.php

QUEUE_DRIVER=database

Chúng ta có thể tạo bảng jobs bằng Artisan CLI với command sau: php artisan queue:table Sau khi chạy câu command trên, Laravel sẽ tạo ra cho chúng ta một file migrations tại database/migrations//YYYY_MM_DD_HHMMSS_create_jobs_table.php và nội dung file như sau:

bigIncrements('id');
            $table->string('queue');
            $table->longText('payload');
            $table->unsignedTinyInteger('attempts');
            $table->unsignedInteger('reserved_at')->nullable();
            $table->unsignedInteger('available_at');
            $table->unsignedInteger('created_at');
 
            $table->index(['queue', 'reserved_at']);
        });
    }
 
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('jobs');
    }
}

Tiếp theo hãy chạy lệnh php artisan migrate để tiến hành migrate, khi đó trong database của bạn đã có bảng jobs. Bây giờ hãy tạo class của job thông qua câu lệnh sau

php artisan make:job SendingEmail

Và chúng ta sẽ có class SendingEmail như sau

send(new SendMailable());
    }
}

Tiếp theo chúng ta tạo ra một route để tiến hành gửi email trong file routes/web.php

Truy cập vào đường dẫn trên không thấy có lỗi, nhưng mail vẫn chưa có ư??

Hướng dẫn hàng đợi trong php
?? . Đó là do bạn chưa chạy queue worker đó. Vào terminal và run command sau:

php artisan queue:work

Terminal sẽ hiển thị như sau:

❯ php artisan queue:work
[2020-11-11 23:25:11][1965] Processing: App\Jobs\SendingEmail
[2020-11-11 23:25:16][1965] Processed:  App\Jobs\SendingEmail
[2020-11-11 23:29:14][1966] Processing: App\Jobs\SendingEmail
[2020-11-11 23:29:32][1966] Processed:  App\Jobs\SendingEmail

Chúng ta tiến hành kiểm tra hòm thư:

Hướng dẫn hàng đợi trong php
Vậy là chúng ta đã gửi mail thành công bằng việc sử dụng Queue.

Ngoài ra, nếu bạn không muốn gửi mail tức thì, bạn có thể trì hoãn nó bằng cách sau

dispatch($mailForTesting)->delay(now()->addMinutes(10));

Queue worker đồng thời cũng sẽ cung cấp cho bạn một vài lựa chọn như sau

php artisan queue:work

Các lựa chọn:

  • --tries=3: Định nghĩa số lần xử lý job trước khi job bị fail. Bạn cũng có thể định nghĩa biến này trong job.
  • --timeout=30: Định nghĩa thời gian tối đa job có thể chạy trong queue.
  • --once: Định nghĩa worker chỉ lắng nghe và xử lý 1 job duy nhất.
  • Bạn có thể truyền cụ thể driver mà worker này sẽ lắng nghe như : redis, sqs, ...
  • --queue=name: Chỉ rõ tên queue mà worker sẽ nghe.

Worker là một process tồn tại lâu dài, nên trong quá trình deploy, nó sẽ không tự nhận biết và thích nghi với sự thay đổi của source code, vì vậy bạn cần restart nó trong quá trình deploy, bằng lệnh:

php artisan queue:restart

5. Một số tài liệu tham khảo

https://laravel.com/docs/7.x/queues

https://code.tutsplus.com/vi/tutorials/deferring-tasks-in-laravel-using-queues--cms-29957

Chúc các bạn học tập tốt, lao động tốt

Hướng dẫn hàng đợi trong php