Quay lại

RabbitMQ là gì và cách sử dụng trong Laravel Chuyên mục PHP và Laravel    2023-05-29    610 Lượt xem    98 Lượt thích    comment-3 Created with Sketch Beta. 0 Bình luận

RabbitMQ là gì và cách sử dụng trong Laravel

Hôm nay chúng mình sẽ cùng tìm hiểu RabbitMQ là gì và cách ứng dụng nó vào trong application của chúng ta như thế nào nhé , ở phần 1 này chắc mình sẽ đi từ cơ bản trước nhé, sau bài này mình sẽ ra phần 2 để tạo ra 1 ứng dụng cụ thể hơn và áp dụng nó trong thực tế sẽ như thế nào nhé , Ok let gooo !

Như các bạn đã biết khi ứng dụng của chúng ta trở nên phức tạp hơn , phình to hơn thì cách tốt nhất chắc là tách rời một số modules ra làm nhiều phần và xử lý chúng một cách riêng biệt để giảm sự phụ thuộc của chúng , với cách này nếu trong trường hợp có một số modules fail thì application của bạn cũng không sợ bị sập cùng các modules kia . Như bình thường khi ứng dụng của bạn là một thể nguyên khối khi một phần trong đó được updated thì toàn bộ application của bạn cũng được deploy lại . 

Trong trường hợp chúng ta tách rời các modules ra thì chúng ta không cần phải lo rằng chúng liên kết như thế nào nữa mà chỉ cần tập trung vào module đang update mà thôi. Một số cách để hỗ trợ giao tiếp giữa các modules như là: Sử dụng API (ví dụ: REST và GraphQL), RPC (Remote Procedure Calls) và Message Brokers (ví dụ: RabbitMQ và Kafka).

Trong bài hướng dẫn này mình chỉ tập chung vào thằng Brokers là RabbitMQ thôi nhé ! Vậy thì RabbitMQ là gì trước tiên phải hiểu nó là gì và cách sử dụng của nó như thế nào ? lợi ích của nó là gì đã nhé .

What is RabbitmQ?

RabbitMQ là một message broker cung cấp các cách để tạo hàng đợi cho các ứng dụng được kết nối để trao đổi message. Trong một ứng dụng RabbitMQ điển hình, bạn cần phải có queue, producersconsumers.

Hàng đợi đóng vai trò là đường dẫn giữa producers và consumers, producers gửi thông báo đến queue để consumers chấp nhận, xóa khỏi hàng đợi và xử lý. Khi nhiệm vụ/quy trình đã hoàn thành, broker sẽ được thông báo để đưa các message ra khỏi hàng đợi.

Trong hướng dẫn này, bạn sẽ học cách tách một phần của ứng dụng Laravel thành một worker (một quy trình PHP chạy backgound) và cách giao tiếp giữa worker và ứng dụng. Để làm điều này, chúng ta sẽ xây dựng một ứng dụng Laravel cơ bản sẽ gửi một tin nhắn từ trình duyệt web và nhận phản hồi trên worker console.

Tại sao nên sử dụng RabbitMQ?

RabbitMQ có ích theo nhiều cách để đơn giản hóa quá trình phát triển. Ví dụ:

  1. Task Queues (Hàng đợi tác vụ ): RabbitMQ có thể được sử dụng làm hàng đợi tác vụ để quản lý các jobs run backgound. Khi một task được gửi vào hàng đợi, RabbitMQ sẽ lưu trữ tác vụ đó cho đến khi có sẵn một worker process để thực thi tác vụ đó. Với cách tiếp cận này, các tasks không bị bỏ qua hoặc bị loại bỏ cho đến khi nhận được phản hồi từ consumer.
  2. Event-Driven Architecture: RabbitMQ có thể được sử dụng để triển khai event-driven architecture, trong đó các ứng dụng giao tiếp với nhau bằng cách publishingsubscribing (pub/sub) các sự kiện. Nơi các thành phần có thể được thêm vào hoặc loại bỏ mà không ảnh hưởng đến phần còn lại của hệ thống.
  3. Micro-services Communication: RabbitMQ có thể được sử dụng làm kênh liên lạc giữa các dịch vụ vi mô. Trong kiến ​​trúc vi dịch vụ, mỗi dịch vụ thực hiện một nhiệm vụ cụ thể, với việc giao tiếp giữa các dịch vụ là rất quan trọng. RabbitMQ cung cấp một cách đáng tin cậy và có thể mở rộng để giao tiếp này có thể thực hiện được mà không có độ trễ phản hồi đáng kể.
  4. Distributed Systems: RabbitMQ có thể được sử dụng để xây dựng các hệ thống phân tán. Trong một hệ thống phân tán, các modules khác nhau cần giao tiếp với nhau. RabbitMQ cung cấp một cách để trao đổi thông báo giữa các modules, đảm bảo độ tin cậy và tính nhất quán.
  5. Internet of Things (IoT) Messaging: RabbitMQ có thể được sử dụng để kết nối các thiết bị IoT. Các thiết bị IoT tạo ra rất nhiều dữ liệu và RabbitMQ có thể giúp quản lý dữ liệu đó bằng cách cung cấp một hệ thống message cho phép giao tiếp hiệu quả giữa các thiết bị và ứng dụng.
  6. Chat Applications: RabbitMQ có thể được sử dụng trong các ứng dụng trò chuyện để gửi tin nhắn giữa những người dùng trong thời gian thực. RabbitMQ cung cấp một hệ thống nhắn tin có thể mở rộng và đáng tin cậy, có thể xử lý khối lượng lớn tin nhắn và người dùng.

Trước khi vào phần thực hành các bạn cần phải chuẩn bị một số yêu cầu sau nhé:

  1. Kiến thức về PHP
  2. PHP8.1
  3. Composer đã được cài globally
  4. Tài khoản CloudAMQP

Tạo một ứng dụng Laravel

Để cài đặt, chúng ta sẽ sử dụng Composer, nhưng trước khi bắt đầu, hãy tạo một dự án Laravel bằng cách chạy lệnh bên dưới.

composer create-project laravel/laravel rabbitmq-tut

Tiếp theo, vào thư mục và khởi động ứng dụng bằng cách chạy các lệnh bên dưới đây :

cd rabbitmq-tut
php artisan serve

Nếu mọi thứ suôn sẻ, bạn sẽ có một máy chủ đang chạy tại http://localhost:8000 phục vụ với trang mẫu của Laravel.

Bây giờ, hãy thêm php-amqplib vào dự án của chúng ta để PHP có thể giao tiếp với RabbitMQ. Để làm điều đó, hãy chạy lệnh bên dưới.

composer require php-amqplib/php-amqplib

Với mục đích của bài viết này, chúng ta sẽ sử dụng CloudAMQP làm máy chủ RabbitMQ mặc định. Điều hướng đến bảng điều khiển CloudAMQP. Dưới đây là giao diện của bảng điều khiển của mình , còn các bạn chưa có thì click vào Create new instance nhé.

Sau đó, nhấp vào phiên bản mới được tạo để truy xuất thông tin chi tiết về máy chủ, như có thể thấy bên dưới. Với demo của mình thì nó được đặt tên là micro-service.

Tiếp theo, chúng ta kết nối php-amqplib với instance này. Để làm điều đó, hãy thêm các biến sau vào tệp .env trong dự án của bạn, hãy để ý cái khoanh đỏ của mình nhé để dễ copy:

MQ_HOST="armadillo-01.rmq.cloudamqp.com"
MQ_PORT="5672"
MQ_USER="acfxlhpb"
MQ_PASS="abcc22222"
MQ_VHOST="acfxlhpb"

Các biến được liệt kê thuộc về máy chủ AMPQP là port, user, password và vhost. Bạn có thể truy xuất các khóa này từ bảng điều khiển phiên bản CloudAMQP.

Tạo một RabbitMQ service

Giờ đây, ứng dụng đã được tạo khung sườn rồi, điều tiếp theo chúng ta sẽ phải làm là tạo một service để xử lý các hoạt động của RabbitMQ. Tạo một thư mục mới có tên app/Services và trong thư mục đó tạo một tệp mới có tên RabbitMQService.php và thêm nội dung bên dưới đây vào nhé.

<?php

namespace App\Services;

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Connection\AMQPSSLConnection;
use PhpAmqpLib\Message\AMQPMessage;

class RabbitMQService
{
    public function publish($message)
    {
        $connection = new AMQPStreamConnection(env('MQ_HOST'), env('MQ_PORT'), env('MQ_USER'), env('MQ_PASS'), env('MQ_VHOST'));
        $channel = $connection->channel();
        $channel->exchange_declare('test_exchange', 'direct', false, false, false);
        $channel->queue_declare('test_queue', false, false, false, false);
        $channel->queue_bind('test_queue', 'test_exchange', 'test_key');
        $msg = new AMQPMessage($message);
        $channel->basic_publish($msg, 'test_exchange', 'test_key');
        echo " [x] Sent $message to test_exchange / test_queue.\n";
        $channel->close();
        $connection->close();
    }
    public function consume()
    {
        $connection = new AMQPStreamConnection(env('MQ_HOST'), env('MQ_PORT'), env('MQ_USER'), env('MQ_PASS'), env('MQ_VHOST'));
        $channel = $connection->channel();
        $callback = function ($msg) {
            echo ' [x] Received ', $msg->body, "\n";
        };
        $channel->queue_declare('test_queue', false, false, false, false);
        $channel->basic_consume('test_queue', '', false, true, false, false, $callback);
        echo 'Waiting for new message on test_queue', " \n";
        while ($channel->is_consuming()) {
            $channel->wait();
        }
        $channel->close();
        $connection->close();
    }
}

Service này sẽ chịu trách nhiệm publishing và consuming các message từ queue jobs (hàng đợi jobs). Để hiểu đầy đủ đoạn mã trên, bạn sẽ cần hiểu luồng thông báo RabbitMQ. Nó hoạt động như thế sau nè:

  1. Producer sẽ publishes một message tới một exchange.
  2. Exchange nhận được message và định tuyến message đến queue thích hợp. Việc exchange cũng tính đến các thuộc tính của thông báo, chẳng hạn như route key, tùy thuộc vào loại exchange.
  3. Để exchange giao tiếp với queue, một ràng buộc phải được tạo giữa hai trong số chúng. Sau đó, exchange sẽ route cái message vào hàng đợi còn tùy thuộc vào thuộc tính message nào được cung cấp.
  4. Các message được định tuyến sẽ ở trong hàng đợi cho đến khi chúng được xử lý bởi consumer.
  5. Consumer xử lý tin nhắn và đánh dấu nó là đã received/consumed.

Tiếp theo, chúng ta tạo một lệnh consumer sẽ lắng nghe queue của chúng ta và sử dụng nó khi có một tin nhắn mới. Chạy lệnh dưới đây để tạo một cmd mới.

php artisan make:command MQConsumerCommand

Bây giờ, hãy thêm đoạn mã sau vào tệp app/Console/Commands/MQConsumerCommand.php.

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Services\RabbitMQService;

class MQConsumerCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'mq:consume';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Consume the mq queue';

    /**
     * Execute the console command.
     */
    public function handle(): void
    {
        $mqService = new RabbitMQService();
        $mqService->consume();
    }
}

Khi lệnh này được chạy, nó sẽ kích hoạt function consume() trong RabbitMQService, hàm này sẽ lần lượt lắng nghe các tin nhắn đến từ hàng đợi có tên test_queue.

Tiếp theo, đến consumer. Trong ứng dụng dành cho consumer, chúng ta sẽ tạo một biểu mẫu để publish test_queue. Để làm điều đó, hãy cập nhật resource/views/welcome.blade.php để khớp với mã bên dưới.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Rabbitmq-tut</title>
    <!-- Fonts -->
    <link rel="preconnect" href="https://fonts.bunny.net">
    <link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" />
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="antialiased">
    <div class="h-[100vh] flex justify-center items-center ">
        <form action="/api/message" method="post" class="w-[700px]">
            <textarea class="border border-gray-300 w-full rounded-[10px] min-h-[300px] p-4" placeholder="enter message" name="message" id="message"></textarea>
            <button class="bg-blue-500 px-10 py-[12px] rounded-[10px] text-white mt-2">Send message</button>
        </form>
    </div>
</body>
</html>

Tiếp theo, thêm route sau vào cuối của file routes/api.php.

Route::post("/message", function (Request $request) {
    $message = $_POST['message'];
    $mqService = new \App\Services\RabbitMQService();
    $mqService->publish($message);
    return view('welcome');
});

Bước cuối kiểm tra thôi nào

Để kiểm tra, chúng ta sẽ bắt đầu với một consumer cmd, sau đó điều hướng đến trang chủ và sau đó gửi thông báo tùy chỉnh của chúng ta. Nếu mọi thứ hoạt động, một tin nhắn sẽ được gửi đến console dành cho consumer.

Khởi động lại ứng dụng bằng cách chạy lệnh sau.

php artisan serve

Sau đó hãy mở terminal window hoặc tab, hãy chạy lệnh bên dưới để bắt đầu cho consumer:

php artisan mq:consume

Bạn sẽ nhận được một thông báo như bên dưới.

Bây giờ, hãy đến trang chủ của bạn tại http://localhost:8000 và gửi một tin nhắn tùy chỉnh. Bạn sẽ thấy điều này trước khi gửi tin nhắn.

Và bạn sẽ thấy như sau sau khi gửi tin nhắn.

Như các bạn có thể thấy ở trên cùng bên phải. Nó báo tin nhắn đã được gửi đi. Bây giờ chúng ta hãy nhìn vào consumers của chúng ta. Đây là những gì nó sẽ in ra.

Nếu mọi việc suôn sẻ, bạn sẽ nhận được một cái gì đó tương tự như thế này. Xin chúc mừng, bạn đã có một pub/sub hoạt động đầy đủ trong Laravel. Tùy thuộc vào tin nhắn được gửi, giờ đây bạn có thể thực hiện thao tác bạn muốn trong ứng dụng consumer của mình.

Ok vậy là xong rồi đó là phần giới thiệu nhanh về RabbitMQ và cách sử dụng nó với Laravel

Kết luận

Trong hướng dẫn này, chúng ta đã giới thiệu cách cài đặt RabbitMQ trên một dự án Laravel. Chúng ta cũng đã học cách kết nối với máy client từ xa bằng cách tận dụng gói miễn phí của CloudAMQP để xây dựng ứng dụng pub/sub RabbitMQ hoạt động đầy đủ. Tôi hy vọng bạn đã học cách sử dụng RabbitMQ và sẽ sử dụng nó trong dự án tiếp theo của bạn. 

Thank you

 
 
 

Bình luận (0)

Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough

Bài viết liên quan

Learning English Everyday