Advertisement
  1. Code
  2. Laravel 5

Trì hoãn các tác vụ trong Laravel bằng cách dùng Queues

by
Read Time:14 minsLanguages:

Vietnamese (Tiếng Việt) translation by Andrea Ho (you can also view the original English article)

Trong bài này, chúng ta sẽ tìm hiểu API Queue trong framework Laravel dành cho web. Nó cho phép bạn trì hoãn các tác vụ tốn nhiều tài nguyên trong quá trình thực hiện mã lệnh để nâng cao trải nghiệm tổng thể cho người dùng cuối. Sau khi giới thiệu các thuật ngữ cơ bản, tôi sẽ minh hoạ nó bằng cách thực hiện một ví dụ thực tế.

Page load (thời gian tải trang) là một khía cạnh quan trọng của bất kỳ trang web thành công nào và không nên bỏ qua tầm quan trọng của nó vì page load ảnh hưởng đến SEO của trang web và trải nghiệm tổng thể cho người dùng cuối. Bạn sẽ chỉ cần sửa các trang web với thời gian tải trang dài thường xuyên. Tất nhiên, có những cách tiếp cận khác nhau mà bạn có thể sử dụng để khắc phục vấn đề này.

Khi điều tra, bạn thường nhận ra rằng có một số đoạn code gây ra sự trì trệ trong việc xử lý trang. Điều tiếp theo bạn có thể thử là xác định các khối có thể được trì hoãn chờ xử lý và không có tác động thực sự vào kết quả cuối cùng của trang hiện tại. Điều đó thật sự cần cải thiện tốc độ tổng thể của trang web vì chúng tôi đã loại bỏ các đoạn code gây ra sự trì trệ.

Hôm nay, chúng ta sẽ khám phá một khái niệm tương tự trong bối cảnh của framework cho web Laravel. Trên thực tế, Laravel đã cung cấp một API dựng sẵn hữu ích cho phép chúng ta trì hoãn việc xử lý các tác vụ - Queue API. Không lãng phí nhiều thời gian của bạn, tôi sẽ tiếp tục và thảo luận về các yếu tố cơ bản của Queue API.

Drivers, Connections, Queues, và Jobs

Mục đích cơ bản của Queue API là vận hành các job đã đượ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 nhau tìm hiểu những gì tôi vừa nói.

Queue Drivers

Giống như cách bạn đã sử dụng một driver khác cho kết nối cơ sở dữ liệu, bạn cũng có thể chọn từ nhiều queue driver khác nhau. API Queue hỗ trợ các adapter khác nhau như database, beanstalkd, sqs, và redis.

Queue driver chỉ là nơi được sử dụng để lưu trữ thông tin liên quan đến queue. Vì vậy, nếu bạn đang sử dụng một database cho queue driver, ví dụ, job mới sẽ được thêm vào bảng jobs trong database. Mặt khác, nếu bạn đã cấu hình redis làm queue driver mặc định, job sẽ được bổ sung vào server của redis.

API Queue cũng cung cấp hai queue driver đặc biệt cho các mục đích kiểm tra - đồng bộ (sync) và null. Queue driver đồng bộ đượ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ó sẽ hoàn toàn không được thực hiện.

Connections (các kết nối)

Khi bạn định cấu hình Queue API lần đầu tiên, bạn 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. Ít nhất, connection dự kiến ​​sẽ cung cấp các thông tin sau:

  • queue driver sẽ được sử dụng
  • Các giá trị cấu hình cụ thể của queue driver
  • tên mặc định của queue mà job sẽ bổ sung vào

Queues (các hàng đợi)

Khi bạn thêm job bất kỳ vào queue, nó sẽ được thêm vào queue mặc định. Trên thực tế, điều đó nên ổn trong đa số trường hợp, trừ khi bạn có những job cần được ưu tiên hơn những job khác. Trong trường hợp đó, bạn có thể tạo ra một queue gọi tên là high và đặt những job có ưu tiên cao hơn vào trong queue đặc biệt đó.

Khi bạn chạy một queue worker để xử lý các job đã xếp hàng, bạn có thể tùy chọn chuyển các tham số --queue, nó cho phép bạn liệt kê tên các queue theo thứ tự cần xử lý. Ví dụ: nếu bạn chỉ định --queue=high,default, thì trước tiên nó sẽ xử lý các job trong queue high, và khi đã hoàn thành nó sẽ tìm lấy các job trong queue mặc định.

Jobs

Một job trong Queue API là một tác vụ được hoãn lại từ luồng xử lý chính. Ví dụ: nếu bạn muốn tạo hình đại diện khi người dùng upload hình ảnh từ giao diện người dùng, thì bạn có thể tạo một job mới đảm trách phần xử lý hình đại diện. Theo cách này, bạn có thể trì hoãn tác vụ xử lý hình đại diện từ luông xử lý chính.

Đó là giới thiệu cơ bản về thuật ngữ Queue API. Từ phần tiếp theo trở đi, chúng ta sẽ khám phá cách tạo một queue job mới và chạy nó bằng cách sử dụng queue worker của Laravel.

Tạo queue job đầu tiên của bạn

Lúc này, bạn nên cảm thấy tự tin về queue jobs. Từ phần này trở đi, chúng ta sẽ triển khai một ví dụ thực tế mình hoạ cho khái niệm queue jobs trong Laravel.

Bạn thường sẽ phải đối mặt với tình huống mà bạn cần tạo các phiên bản hình đại diện khác nhau của một hình ảnh được upload từ người dùng. Trong hầu hết các trường hợp, nhà phát triển cố gắng xử lý nó trong thời gian thực để các phiên bản hình ảnh được tạo ra ngay khi người dùng tải lên hình ảnh

Có vẻ đó là một cách tiếp cận hợp lý nếu bạn dự định tạo ra một vài phiên bản và nó không mất quá nhiều thời gian lúc đầu. Mặt khác, nếu bạn đang đương đầu với một ứng dụng yêu cầu phải xử lý phức tạp và từ đó chiếm nhiều tài nguyên hơn, quá trình xử lý trong thời gian thực có thể dẫn đến trải nghiệm người dùng không tốt.

Một chọn lựa hiển nhiên xuất hiện trong suy nghĩ của bạn ban đầu là trì hoãn quá trình xử lý hình đại diện càng sớm càng tốt. Cách tiếp cận đơn giản nhất mà bạn có thể thực hiện trong trường hợp cụ thể này là thiết lập một cron job (tác vụ định kỳ tự động) để kích hoạt xử lý theo chu kỳ thường xuyên và bạn sẽ ổn.

Mặt khác, một cách tiếp cận tốt hơn nhiều là trì hoãn và đẩy tác vụ này vào một queue, và để cho queue worker đảm trách khi có cơ hội thực hiện phần xử lý này. Trong môi trường production, queue worker là một mã lệnh daemon luôn chạy và xử lý các tác vụ trong một queue. Lợi ích rõ ràng của các tiếp cận này là một trải nghiệm người dùng tốt hơn nhiều, và bạn không phải chờ đợi để cron chạy khi job sẽ được xử lý ngay khi có thể.

Tôi đoán đó là đủ lý thuyết để bắt đầu với một triển khai thực sự.

Trong trường hợp của chúng tôi, chúng ta sẽ sử dụng queue driver của database và yêu cầu chúng ta tạo ra bảng jobs trong database. Bảng jobs giữ tất cả các công việc cần phải được xử lý trong lần chạy tiếp theo của 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 trong file config/queue.php.

Thực tế, Laravel đã cung cấp câu lệnh artisan giúp chúng ta tạo bảng jobs. Chạy câu lệnh dưới đây ở thư mục gốc của ứng dụng Laravel, và nó sẽ tạo một database cần thiết để tạo bảng jobs.

File migration file được tạo ra ở database/migrations/YYYY_MM_DD_HHMMSS_create_jobs_table.php nên trông giống thế này:

Tiếp theo, hãy chạy lệnh migrate để thực sự tạo ra bảng jobs trong một cơ sở dữ liệu.

Và trong chừng mực đó là migration cho jobs được đề cập.

Tiếp theo, hãy tạo model Image sẽ được sử dụng để quản lý hình ảnh được upload bởi người dùng. Model image cũng đòi hỏi một bảng tương tác trong database, vì vậy chúng ta sẽ sử dụng tùy chọn --migrate trong khi tạo model Image.

Câu lệnh trên tạo class cho model Image cùng với một migration liên kết với database.

Class model Image nên giống như vậy:

Và file migration của database nên được tạo ra ở database/migrations/YYYY_MM_DD_HHMMSS_create_images_table.php. Chúng tôi cũng muốn lưu lại đường dẫn ban đầu của hình ảnh được upload từ người dùng. Hãy điều chỉnh lại code của file migration cho database của Image để trông giống như bên dưới.

Như bạn có thể thấy, chúng tôi đã bổ sung cột $table->string('org_path') để lưu đường dẫn của hình gốc. Tiếp theo, bạn chỉ cần chạy lệnh migrate để thực sự tạo bảng đó trong database.

Và trong chừng mực đó là model Image được đề cập.

Tiếp theo, hãy tạo ra một queue job thực sự chịu trách nhiệm xử lý các hình đại diện cho các ảnh gốc. Đối với việc xử lý hình đại diện, chúng tôi sẽ sử dụng thư viện xử lý hình ảnh rất phổ biến - Intervention Image.

Để cài đặt thư viện Intervention Image, hãy tiếp tục và chạy lệnh sau tại thư mục gốc của ứng dụng của bạn.

Bây giờ, đã đến lúc tạo class của Job, và chúng ta sẽ sử dụng một lệnh artisan để làm điều đó.

Lệnh đó sẽ tạo ra template cho class của Job tại app/Jobs/ProcessImageThumbnails.php. Hãy thay thế nội dung của file đó bằng nội dung sau đây:

Khi queue worker bắt đầu xử lý bất kỳ job nào, nó sẽ tìm kiếm phương pháp xử lý. Vì vậy, đó là phương thức handle giữ logic chính cho job của bạn.

Trong trường hợp của chúng ta, ta cần tạo một hình đại diện của một hình ảnh được upload từ người dùng. Code của phương thức handle khá đơn giản - chúng ta lấy ra một hình ảnh từ model ImageModel và tạo ra một hình đại diện bằng thư viện Intervention Image. Tất nhiên, chúng tôi cần phải chuyển qua model Image tương ứng khi chúng ta gửi đi job của chúng ta, và chúng ta sẽ nhìn thấy nó trong giây lát.

Để kiểm tra job mới tạo, chúng tôi sẽ tạo một form đơn giản cho phép người dùng upload hình ảnh. Tất nhiên, chúng tôi sẽ không tạo ảnh đại diện ngay lập tức; chúng tôi sẽ hoãn lại tác vụ đó để nó có thể được xử lý bởi queue worker.

Hãy tạo một file controller tại app/Http/Controllers/ImageController.php như bên dưới.

Hãy tạo một file view liên kết tại resources/views/upload_form.blade.php.

Sau cùng, hãy thêm routes cho hành động index upload trong file routes/web.php.

Trong controller ImageController, phương thức index được dùng để tạo một form upload.

Khi người dùng gửi một form đi, phương thức upload được gọi đến.

Vào lúc bắt đầu phương thức upload, bạn sẽ nhận thấy code cho việc upload sẽ di chuyển file được tải lên thư mục public/images. Tiếp theo, chúng ta chèn một database record sử dụng model App/Image.

Cuối cùng, chúng ta sử dụng job ProcessImageThumbnails để trì hoãn tác vụ xử lý hình đai diện. Điều quan trọng cần lưu ý là đó là phương thức dispatch được sử dụng để trì hoãn một tác vụ. Khi kết thúc, người dùng được chuyển đến trang upload với một thông báo thành công.

Tại thời điểm này, job được thêm vào bảng jobs để xử lý. Hãy xác nhận điều đó bằng cách thực thi truy vấn sau.

Bạn phải tự hỏi, sau đó cần những gì để xử lý một job? Đừng lo lắng - đó là những gì chúng ta sẽ thảo luận trong phần tiếp theo.

Queue Worker

Công việc của queue worker trong Laravel là xử lý các job được xếp hàng đợi (queue) để xử lý. Trên thực tế, có một lệnh artisan giúp chúng tôi bắt đầu quá trình làm việc của queue

Ngay sau khi bạn chạy lệnh đó, nó xử lý các job đang chờ giải quyết. Trong trường hợp của chúng tôi, nó sẽ xử lý job ProcessImageThumbnails đã được xếp hàng đợi khi người dùng upload một hình ảnh trước đó.

Bạn sẽ nhận thấy rằng khi bạn khởi động một queue worker, nó sẽ tiếp tục chạy cho đến khi bạn vô hiệu nó theo cách thủ công hoặc đóng terminal lại. Trên thực tế, nó đang đợi job tiếp theo được xử lý. Ngay khi có một job mới trong queue, job đó sẽ được xử lý ngay nếu queue worker đang hoạt động.

Tất nhiên, chúng ta không thể giữ nó hoạt động như vậy, vì vậy chúng ta cần phải tìm một cách để queue worker luôn chạy bên dưới nền tảng.

Có một số công cụ quản lý quá trình mà bạn có thể lựa chọn. Đây là danh sách một vài cái tên:

  • Circus
  • daemontools
  • Monit
  • Supervisor
  • Upstart

Bạn nên chọn một công cụ mà bạn cảm thấy thoải mái khi quản lý queue worker cho Laravel. Về cơ bản, chúng tôi muốn đảm bảo rằng queue worker nên chạy liên tục không ngừng để nó xử lý các queued job ngay tức thời.

Vì vậy, đó là Queue API theo ý của bạn. Bạn có thể sử dụng nó trong quá trình phát triển hằng ngày để trì hoãn các tác vụ tốn nhiều thời gian để cải thiện trải nghiệm người dùng.

Tổng kết

Trong bài viết này, chúng tôi đã thảo luận về Queue API trong Laravel, điều này thực sự hữu ích nếu bạn muốn trì hoãn việc xử lý các tác vụ tốn nhiều tài nguyên.

Chúng ta bắt đầu với giới thiệu cơ bản về Queue API, liên nó là một cuộc thảo luận về các connection (kết nối), queue (hàng đợi) và job (tác vụ). Trong nửa phần sau của bài viết, chúng tôi đã tạo ra một queue job mới để minh hoạ cho cách bạn có thể sử dụng Queue API trong thực tiễn.

Đối với những bạn vừa mới bắt đầu với Laravel hoặc muốn mở rộng kiến ​​thức, trang web hoặc ứng dụng của bạn với các phần mở rộng, chúng tôi có nhiều thứ bạn có thể học tại Envato Market.

Hãy thoải mái sử dụng form phản hồi bên dưới để đăng tải những câu hỏi và đề xuất của bạn.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.