RabbitMQ Là Gì? Hướng Dẫn Chi Tiết Cho Người Mới Bắt Đầu

RabbitMQ là một message broker (trình môi giới tin nhắn) mã nguồn mở, hay còn gọi là phần mềm quản lý hàng đợi tin nhắn. Nó đóng vai trò trung gian, cho phép các ứng dụng giao tiếp với nhau bằng cách gửi và nhận tin nhắn. Hãy tưởng tượng RabbitMQ như một “hộp thư” trung tâm, nơi các ứng dụng có thể gửi tin nhắn đến và đi một cách đáng tin cậy.

Message Broker Là Gì?

Message broker là một phần mềm trung gian, chịu trách nhiệm xác thực, chuyển đổi và định tuyến tin nhắn giữa các ứng dụng. Nó giải quyết các nhu cầu giao tiếp phức tạp, đảm bảo tin nhắn được gửi đến đúng nơi, đúng thời điểm, và đúng định dạng.

RabbitMQ hoạt động như một hộp thư trung tâm để các ứng dụng gửi và nhận tin nhắnRabbitMQ hoạt động như một hộp thư trung tâm để các ứng dụng gửi và nhận tin nhắn

Message broker hoạt động theo cơ chế: ứng dụng gửi (producer) gửi tin nhắn đến message broker. Broker xử lý tin nhắn, bao gồm sắp xếp, định tuyến, chuyển đổi, lưu trữ và chuyển phát đến các ứng dụng nhận (consumer) phù hợp.

Có hai mô hình giao tiếp chính với message broker:

  • Publish và Subscribe (Topics): Ứng dụng gửi tin nhắn đến một chủ đề (topic), và các ứng dụng quan tâm đến chủ đề đó sẽ nhận được tin nhắn.
  • Point-to-Point (Queues): Ứng dụng gửi tin nhắn đến một hàng đợi (queue) cụ thể, và chỉ một ứng dụng nhận duy nhất sẽ lấy tin nhắn từ hàng đợi đó.

Tại Sao Nên Sử Dụng RabbitMQ?

RabbitMQ mang lại nhiều lợi ích, đặc biệt trong các hệ thống phức tạp:

  • Tăng tốc độ phản hồi: Thay vì phải xử lý các tác vụ tốn thời gian ngay lập tức, web server có thể nhanh chóng trả lời yêu cầu của người dùng bằng cách gửi tin nhắn đến RabbitMQ để xử lý sau.
  • Phân tán công việc: RabbitMQ cho phép phân tán tin nhắn đến nhiều người nhận, giảm tải cho các worker xử lý và tăng khả năng mở rộng.
  • Tích hợp hệ thống: Các ứng dụng khác nhau, thậm chí được viết bằng các ngôn ngữ lập trình khác nhau, có thể giao tiếp với nhau thông qua RabbitMQ.
  • Độ tin cậy: RabbitMQ đảm bảo tin nhắn được gửi và nhận một cách đáng tin cậy, ngay cả khi có lỗi xảy ra.

Ví dụ, một trang web tạo CV trực tuyến cho phép người dùng tạo file PDF. Khi hàng ngàn người dùng cùng lúc nhấn nút tạo PDF, server có thể bị quá tải. Sử dụng RabbitMQ, các yêu cầu tạo PDF sẽ được đưa vào hàng đợi. Một worker (consumer) sẽ lấy các yêu cầu này từ hàng đợi và xử lý, đảm bảo hệ thống hoạt động ổn định.

Quy trình hoạt động như sau:

  1. Người dùng gửi yêu cầu tạo PDF đến ứng dụng web.
  2. Ứng dụng web (producer) gửi một tin nhắn đến RabbitMQ, chứa thông tin cần thiết để tạo PDF (tên, email, số điện thoại,…).
  3. Một exchange (bộ định tuyến) đảm bảo tin nhắn được chuyển đến đúng hàng đợi tạo PDF.
  4. Một worker xử lý PDF (consumer) nhận tin nhắn và bắt đầu tạo PDF.

Cài Đặt RabbitMQ

Để cài đặt RabbitMQ trên Ubuntu hoặc các hệ điều hành Debian, bạn có thể sử dụng các lệnh sau:

echo "deb sentayho.com.vn/debian/ testing main" | sudo tee /etc/apt/sources.list.d/sentayho.com.vn > /dev/null
sudo wget sentayho.com.vn/sentayho.com.vn
sudo apt-key add sentayho.com.vn
sudo apt-get update
sudo apt-get install rabbitmq-server -y
sudo service rabbitmq-server start
sudo rabbitmq-plugins enable rabbitmq_management
sudo service rabbitmq-server restart

Giải thích các lệnh:

  • Thêm nguồn RabbitMQ vào danh sách nguồn phần mềm.
  • Tải về khóa đăng ký RabbitMQ.
  • Thêm khóa vào Ubuntu.
  • Cập nhật danh sách các nguồn phần mềm.
  • Cài đặt RabbitMQ server.
  • Khởi động RabbitMQ server.
  • Kích hoạt plugin quản lý RabbitMQ (cung cấp giao diện web để theo dõi RabbitMQ).
  • Khởi động lại RabbitMQ server để các thay đổi có hiệu lực.

Tên người dùng và mật khẩu mặc định là guest. Cổng mặc định là 5672.

Nếu bạn sử dụng hệ điều hành khác, hãy tham khảo hướng dẫn cài đặt chi tiết tại sentayho.com.vn/download.html.

Làm Việc Với RabbitMQ Bằng PHP

Sau khi cài đặt RabbitMQ, bạn cần cài đặt thư viện AMQP cho PHP để giao tiếp với RabbitMQ. AMQP (Advanced Message Queuing Protocol) là giao thức tiêu chuẩn để gửi tin nhắn.

Tạo một thư mục mới để chứa các file thử nghiệm RabbitMQ. Sau đó, tạo file sentayho.com.vn và thêm nội dung sau:

{
  "require": {
    "videlalvaro/php-amqplib": "2.2.*"
  }
}

Mở terminal, di chuyển đến thư mục vừa tạo và chạy lệnh composer install để cài đặt thư viện AMQP.

Tiếp theo, cài đặt Swiftmailer để gửi email. Chạy lệnh sau:

composer require swiftmailer/swiftmailer @stable

Gửi Tin Nhắn

Tạo một form để nhập thông tin email (tên người gửi, email người gửi, email người nhận, chủ đề và nội dung). Lưu file này với tên sentayho.com.vn:













    <?php if (isset($_GET['sent']) && $_GET['sent'] == 'true') { ?>

        Your message was sent!

    <?php } ?>

Tiếp theo, tạo file sentayho.com.vn để đẩy tin nhắn vào hàng đợi:

require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLibConnectionAMQPStreamConnection;
use PhpAmqpLibMessageAMQPMessage;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$channel->queue_declare('email_queue', false, false, false, false);

$data = json_encode($_POST);
$msg = new AMQPMessage($data, array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));
$channel->basic_publish($msg, '', 'email_queue');

header('Location: sentayho.com.vn?sent=true');

$channel->close();
$connection->close();
?>

Giải thích code:

  • require_once __DIR__ . '/vendor/autoload.php';: Tải các thư viện cần thiết.
  • use PhpAmqpLibConnectionAMQPStreamConnection;: Sử dụng class AMQPStreamConnection để tạo kết nối đến RabbitMQ.
  • use PhpAmqpLibMessageAMQPMessage;: Sử dụng class AMQPMessage để tạo tin nhắn.
  • $connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');: Tạo một kết nối mới đến RabbitMQ server.
    • host: Địa chỉ của RabbitMQ server (trong trường hợp này là localhost vì RabbitMQ và script PHP chạy trên cùng một máy). Trong môi trường thực tế, RabbitMQ có thể được cài đặt trên một server riêng, vì vậy bạn cần thay localhost bằng địa chỉ IP công cộng của server đó.
    • port: Cổng mà RabbitMQ server đang chạy (mặc định là 5672).
    • user: Tên người dùng để kết nối (mặc định là guest).
    • password: Mật khẩu của người dùng (mặc định là guest).
  • $channel = $connection->channel();: Tạo một channel để giao tiếp với RabbitMQ.
  • $channel->queue_declare('email_queue', false, false, false, false);: Khai báo một hàng đợi (queue) tên là email_queue.
    • name: Tên của hàng đợi.
    • passive: Kiểm tra xem hàng đợi đã tồn tại hay chưa.
    • durable: Xác định xem RabbitMQ có nên giữ hàng đợi này khi server bị sập hay không.
    • exclusive: Xác định xem hàng đợi này chỉ được sử dụng bởi một connection hay không.
    • auto_delete: Xác định xem hàng đợi này có bị xóa khi consumer cuối cùng hủy đăng ký hay không.
  • $data = json_encode($_POST);: Chuyển đổi dữ liệu POST (từ form) thành chuỗi JSON.
  • $msg = new AMQPMessage($data, array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));: Tạo một tin nhắn mới.
    • $data: Dữ liệu của tin nhắn (chuỗi JSON).
    • delivery_mode: Chế độ gửi tin nhắn. AMQPMessage::DELIVERY_MODE_PERSISTENT đảm bảo tin nhắn không bị mất khi RabbitMQ server gặp sự cố.
  • $channel->basic_publish($msg, '', 'email_queue');: Gửi tin nhắn đến hàng đợi email_queue.
    • $msg: Tin nhắn cần gửi.
    • exchange: Exchange (bộ định tuyến). Trong trường hợp này, chúng ta sử dụng exchange mặc định (chuỗi rỗng “”).
    • routing_key: Tên của hàng đợi mà tin nhắn sẽ được gửi đến.
  • header('Location: sentayho.com.vn?sent=true');: Chuyển hướng người dùng trở lại form.
  • $channel->close();: Đóng channel.
  • $connection->close();: Đóng kết nối.

Nhận Tin Nhắn

Tạo file sentayho.com.vn để nhận và xử lý tin nhắn từ hàng đợi:

require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLibConnectionAMQPStreamConnection;
use PhpAmqpLibMessageAMQPMessage;
use Swift_SmtpTransport;
use Swift_Mailer;
use Swift_Message;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$channel->queue_declare('email_queue', false, false, false, false);

echo ' [*] Waiting for messages. To exit press CTRL+C', "n";

$callback = function ($msg) {
    echo " [*] Message received", "n";
    $data = json_decode($msg->body, true);
    $from = $data['from'];
    $from_email = $data['from_email'];
    $to_email = $data['to_email'];
    $subject = $data['subject'];
    $message = $data['message'];

    $transporter = Swift_SmtpTransport::newInstance('smtp.gmail.com', 465, 'ssl')
        ->setUsername('YOUR_GMAIL_EMAIL')
        ->setPassword('YOUR_GMAIL_PASSWORD');

    $mailer = Swift_Mailer::newInstance($transporter);

    $message = Swift_Message::newInstance()
        ->setSubject($subject)
        ->setFrom([$from_email => $from])
        ->setTo([$to_email])
        ->setBody($message);

    $mailer->send($message);

    echo " [*] Message was sent", "n";
    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};

$channel->basic_qos(null, 1, null);
$channel->basic_consume('email_queue', '', false, false, false, false, $callback);

while (count($channel->callbacks)) {
    $channel->wait();
}

$channel->close();
$connection->close();

Giải thích code:

  • Tương tự như sentayho.com.vn, đoạn code này cũng khởi tạo kết nối và channel đến RabbitMQ.
  • echo ' [*] Waiting for messages. To exit press CTRL+C', "n";: In ra thông báo cho biết script đang chờ tin nhắn.
  • $callback = function ($msg) { ... };: Định nghĩa một callback function để xử lý tin nhắn khi nhận được.
    • echo " [*] Message received", "n";: In ra thông báo khi nhận được tin nhắn.
    • $data = json_decode($msg->body, true);: Giải mã chuỗi JSON thành mảng PHP.
    • Trích xuất thông tin từ mảng $data (tên người gửi, email, chủ đề, nội dung).
    • Sử dụng Swiftmailer để gửi email thông qua tài khoản Gmail. Lưu ý: Bạn cần thay thế YOUR_GMAIL_EMAILYOUR_GMAIL_PASSWORD bằng email và mật khẩu Gmail của bạn.
    • $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);: Gửi một acknowledgment (ACK) đến RabbitMQ, báo hiệu rằng tin nhắn đã được xử lý thành công.
  • $channel->basic_qos(null, 1, null);: Đảm bảo rằng consumer chỉ nhận một tin nhắn tại một thời điểm.
  • $channel->basic_consume('email_queue', '', false, false, false, false, $callback);: Bắt đầu tiêu thụ tin nhắn từ hàng đợi email_queue.
    • queue: Tên của hàng đợi.
    • consumer_tag: Một tag để phân biệt consumer (có thể để trống).
    • no_local: Nếu true, tin nhắn sẽ không được gửi đến cùng connection đã publish nó (thường là false).
    • no_ack: Nếu true, RabbitMQ sẽ tự động xóa tin nhắn sau khi gửi đến consumer (thường là false, chúng ta muốn đảm bảo tin nhắn được xử lý thành công trước khi xóa).
    • exclusive: Nếu true, chỉ consumer này mới có thể truy cập hàng đợi (thường là false).
    • nowait: Nếu true, hàm sẽ không chờ phản hồi từ server (thường là false).
    • callback: Callback function sẽ được gọi khi có tin nhắn mới.
  • while (count($channel->callbacks)) { $channel->wait(); }: Vòng lặp vô hạn để chờ tin nhắn.
  • $channel->close();: Đóng channel.
  • $connection->close();: Đóng kết nối.

Chạy Chương Trình

Mở terminal và chạy file sentayho.com.vn:

php sentayho.com.vn

Truy cập sentayho.com.vn trong trình duyệt, nhập thông tin email và nhấn nút gửi. Bạn sẽ thấy thông báo “Your message was sent!”. Kiểm tra terminal nơi bạn đang chạy sentayho.com.vn. Bạn sẽ thấy các thông báo “Message received” và “Message was sent” nếu email đã được gửi thành công.

Kết Luận

RabbitMQ là một công cụ mạnh mẽ để xây dựng các ứng dụng nhắn tin. Hướng dẫn này cung cấp một cái nhìn tổng quan về RabbitMQ và cách sử dụng nó trong PHP. Bạn có thể tìm hiểu thêm tại sentayho.com.vn/sentayho.com.vn để khám phá các tính năng nâng cao của RabbitMQ.

Nguồn: Wern Ancheta Blog

Xem thêm:

  • [PHP RFC: Thay đổi độ ưu tiên của toán tử ghép](đường dẫn đến bài viết liên quan)
  • [[Python cơ bản thường dùng trong công việc] Phần 12 : Kết nối RabbitMQ](đường dẫn đến bài viết liên quan)
  • [Message broker là gì? Sơ lược về RabbitMQ và ứng dụng demo](đường dẫn đến bài viết liên quan)