Trong thế giới số hóa nhanh chóng ngày nay, nhu cầu về các hệ thống tin nhắn mạnh mẽ và đáng tin cậy chưa bao giờ quan trọng hơn. Khi các doanh nghiệp và các nhà phát triển cố gắng tạo ra các ứng dụng có thể mở rộng và hiệu quả, tầm quan trọng của việc truyền thông suôn sẻ giữa các phần khác nhau của một ứng dụng không thể bị phớt lờ. RabbitMQ, một phần mềm môi giới tin nhắn mã nguồn mở, đã nổi lên như một công cụ mạnh mẽ để giải quyết các nhu cầu này, cung cấp một giải pháp linh hoạt và đáng tin cậy cho truyền thông tin nhắn.

RabbitMQ là gì?

RabbitMQ là một phần mềm môi giới tin nhắn dựa trên giao thức AMQP (Advanced Message Queuing Protocol). Được phát triển bởi công ty Rabbit Technologies Ltd và hiện thuộc sở hữu của VMware, RabbitMQ đã trở thành một trong những hệ thống môi giới tin nhắn phổ biến nhất trên thế giới. Nó cho phép các ứng dụng giao tiếp với nhau thông qua việc gửi và nhận tin nhắn, giúp các thành phần khác nhau của một hệ thống có thể làm việc cùng nhau một cách mượt mà và hiệu quả.

Tìm hiểu về RabbitMQ

Tại sao RabbitMQ lại quan trọng?

Để trả lời cho câu hỏi này, chúng ta cùng tìm hiểu một vài tính năng quan trọng của RabbitMQ:

Tính mở rộng và hiệu suất cao

Một trong những lý do chính khiến RabbitMQ được ưa chuộng là khả năng mở rộng và hiệu suất cao. RabbitMQ có thể xử lý hàng triệu tin nhắn mỗi giây, làm cho nó trở thành một lựa chọn lý tưởng cho các ứng dụng yêu cầu xử lý lượng lớn dữ liệu trong thời gian ngắn. Hơn nữa, với khả năng mở rộng theo chiều ngang, RabbitMQ cho phép các hệ thống mở rộng dễ dàng khi nhu cầu tăng lên, đảm bảo hiệu suất không bị ảnh hưởng.

RabbitMQ có khả năng xử lý lượng tin nhắn khổng lồ một cách nhanh chóng

Đáng tin cậy và bền bỉ

RabbitMQ được thiết kế để đảm bảo tính đáng tin cậy và bền bỉ của tin nhắn. Nó hỗ trợ nhiều cơ chế để đảm bảo rằng tin nhắn không bị mất mát trong quá trình truyền tải, chẳng hạn như xác nhận tin nhắn và cơ chế lưu trữ tin nhắn. Điều này rất quan trọng đối với các ứng dụng đòi hỏi tính toàn vẹn của dữ liệu và đảm bảo rằng tất cả các tin nhắn đều được xử lý đúng cách.

RabbitMQ đảm bảo tin nhắn không bị mất trong quá trình truyền tải 

Dễ dàng tích hợp

RabbitMQ cung cấp khả năng tích hợp dễ dàng với nhiều ngôn ngữ lập trình và nền tảng khác nhau, từ Java, Python, đến .NET và nhiều ngôn ngữ khác. Điều này giúp các nhà phát triển dễ dàng tích hợp RabbitMQ vào các ứng dụng hiện có mà không gặp quá nhiều khó khăn. Hơn nữa, RabbitMQ cũng hỗ trợ nhiều giao thức truyền thông khác nhau như AMQP, MQTT và STOMP, giúp linh hoạt hơn trong việc lựa chọn giao thức phù hợp cho từng ứng dụng cụ thể.

Tính năng phong phú

RabbitMQ đi kèm với nhiều tính năng mạnh mẽ, bao gồm khả năng định tuyến tin nhắn phức tạp, hỗ trợ nhiều kiểu trao đổi tin nhắn, và các cơ chế bảo mật mạnh mẽ. Các tính năng này giúp RabbitMQ không chỉ là một hệ thống môi giới tin nhắn đơn giản mà còn là một công cụ linh hoạt có thể đáp ứng nhiều nhu cầu khác nhau của các ứng dụng hiện đại.

RabbitMQ có nhiều tính năng hỗ trợ mạnh mẽ như định tuyến, bảo mật,… 

Cách thức hoạt động của RabbitMQ

RabbitMQ hoạt động dựa trên mô hình publish-subscribe, trong đó các nhà sản xuất (producers) gửi tin nhắn tới các hàng đợi (queues), và các nhà tiêu thụ (consumers) nhận tin nhắn từ các hàng đợi này. Các nhà sản xuất không gửi tin nhắn trực tiếp tới các nhà tiêu thụ mà thông qua các hàng đợi, giúp tách biệt các thành phần của hệ thống và tăng tính linh hoạt.

Một yếu tố quan trọng trong hoạt động của RabbitMQ là các trao đổi (exchanges). Trao đổi là nơi nhận tin nhắn từ các nhà sản xuất và quyết định gửi tin nhắn tới các hàng đợi nào dựa trên các quy tắc định tuyến. Có nhiều loại trao đổi khác nhau trong RabbitMQ, bao gồm:

  • Direct Exchange: Gửi tin nhắn tới hàng đợi có khóa định tuyến (routing key) khớp với khóa của tin nhắn.
  • Producer (P) gửi tin nhắn với các khóa định tuyến khác nhau đến Direct Exchange.
  • Direct Exchange định tuyến tin nhắn đến các hàng đợi dựa trên khóa định tuyến cụ thể.
  • Hàng đợi Q1 nhận tin nhắn với khóa định tuyến “orange” và chuyển tiếp đến người tiêu thụ C1.
  • Hàng đợi Q2 nhận tin nhắn với các khóa định tuyến “black” và “green”, và chuyển tiếp đến người tiêu thụ C2.
  • Fanout Exchange: Gửi tin nhắn tới tất cả các hàng đợi liên kết mà không cần quan tâm tới khóa định tuyến.

Trong Fanout Exchange, tin nhắn từ nhà sản xuất (Producer) được gửi tới tất cả các hàng đợi (Queues) liên kết mà không quan tâm đến khóa định tuyến (routing key). Hình ảnh cho thấy tin nhắn từ nhà sản xuất được gửi đến cả hai hàng đợi Q1 và Q2 thông qua trao đổi fanout (X).

  • Topic Exchange: Gửi tin nhắn tới hàng đợi dựa trên sự khớp mẫu của khóa định tuyến, cho phép định tuyến tin nhắn linh hoạt hơn.

Trong ví dụ này, chúng ta sẽ gửi các tin nhắn mô tả về các loài động vật. Các tin nhắn sẽ được gửi với một khóa định tuyến gồm ba từ (hai dấu chấm). Từ đầu tiên trong khóa định tuyến sẽ mô tả speed, từ thứ hai mô tả colour  và từ thứ ba mô tả species: “<speed>.<colour>.<species>”.

Chúng tôi đã tạo ba kết nối ràng buộc: Q1 được ràng buộc với khóa ràng buộc “.orange.” và Q2 với “..rabbit” và “lazy.#”.

Các kết nối ràng buộc này có thể được tóm tắt như sau:

Q1 quan tâm đến tất cả các loài động vật màu cam. Q2 muốn nhận tất cả các tin nhắn về thỏ, và tất cả các tin nhắn về các lazy.

Một tin nhắn với khóa định tuyến được đặt là “quick.orange.rabbit” sẽ được chuyển đến cả hai hàng đợi. Tin nhắn “lazy.orange.elephant” cũng sẽ đi đến cả hai hàng đợi này. Mặt khác, “quick.orange.fox” sẽ chỉ đến hàng đợi đầu tiên, và “lazy.brown.fox” chỉ đến hàng đợi thứ hai. “lazy.pink.rabbit” sẽ được chuyển đến hàng đợi thứ hai chỉ một lần, mặc dù nó khớp với hai kết nối ràng buộc. “quick.brown.fox” không khớp với bất kỳ kết nối ràng buộc nào nên sẽ bị loại bỏ.

Điều gì xảy ra nếu chúng ta phá vỡ quy tắc và gửi một tin nhắn với một hoặc bốn từ, chẳng hạn như “orange” hoặc “quick.orange.new.rabbit”? Những tin nhắn này sẽ không khớp với bất kỳ kết nối ràng buộc nào và sẽ bị mất!

Mặt khác, “lazy.orange.new.rabbit”, mặc dù có bốn từ, sẽ khớp với kết nối ràng buộc cuối cùng và sẽ được chuyển đến hàng đợi thứ hai.

Topic exchange rất mạnh mẽ và có thể hoạt động giống như các loại exchange khác.

Khi một hàng đợi được ràng buộc với khóa “#” (hash) – nó sẽ nhận tất cả các tin nhắn, bất kể khóa định tuyến là gì – giống như trong fanout exchange.

Khi các ký tự đặc biệt “*” (sao) và “#” (hash) không được sử dụng trong các kết nối ràng buộc, topic exchange sẽ hoạt động giống như direct exchange.

  • Headers Exchange: Gửi tin nhắn dựa trên các thuộc tính header của tin nhắn thay vì khóa định tuyến.

  • Producer: Nhà sản xuất (Producer) gửi một tin nhắn với các thuộc tính header cụ thể, ví dụ như {“key1”: “value1”}.
  • Headers Exchange: Tin nhắn này được gửi đến Headers Exchange, nơi sẽ kiểm tra các thuộc tính header để xác định hàng đợi nào sẽ nhận tin nhắn.
  • Queues: Có ba hàng đợi được ràng buộc với Headers Exchange, mỗi hàng đợi có các thuộc tính ràng buộc khác nhau:
  1. Hàng đợi đầu tiên có điều kiện ràng buộc {“x-match”: “any”, “key1”: “value1”, “key2”: “value2”}. Điều này có nghĩa là tin nhắn sẽ được gửi đến hàng đợi này nếu bất kỳ thuộc tính nào trong số các thuộc tính được liệt kê khớp với tin nhắn.
  2. Hàng đợi thứ hai có điều kiện ràng buộc {“x-match”: “any”, “key3”: “value3”, “key4”: “value4”}. Điều này có nghĩa là tin nhắn sẽ được gửi đến hàng đợi này nếu bất kỳ thuộc tính nào trong số các thuộc tính được liệt kê khớp với tin nhắn.
  3. Hàng đợi thứ ba có điều kiện ràng buộc {“x-match”: “any”, “key1”: “value1”, “key2”: “value2”}. Điều này có nghĩa là tin nhắn sẽ được gửi đến hàng đợi này nếu bất kỳ thuộc tính nào trong số các thuộc tính được liệt kê khớp với tin nhắn.
  • Consumers: Các hàng đợi này sau đó sẽ chuyển tiếp tin nhắn đến các người tiêu thụ (Consumers) tương ứng.

Ứng dụng thực tiễn của RabbitMQ

Trong thực tế, RabbitMQ được ứng dụng trong các hệ thống TMĐT (Thương mại điện tử), IoT, tài chính, ngân hàng,…

Và chúng ta sẽ cùng tìm hiểu ngay sau đây:

Hệ thống thương mại điện tử

Trong các hệ thống thương mại điện tử, RabbitMQ có thể được sử dụng để xử lý các giao dịch mua bán, quản lý giỏ hàng và thông báo cho người dùng về trạng thái đơn hàng. Việc sử dụng RabbitMQ giúp đảm bảo rằng tất cả các giao dịch đều được xử lý một cách tin cậy và nhanh chóng.

RabbitMQ được sử dụng để thông báo trạng thái đơn hàng 

Ứng dụng IoT

RabbitMQ cũng có thể được sử dụng trong các ứng dụng Internet of Things (IoT) để thu thập và xử lý dữ liệu từ các thiết bị cảm biến. Khả năng xử lý lượng lớn tin nhắn của RabbitMQ giúp các hệ thống IoT có thể hoạt động mượt mà và hiệu quả.

Hệ thống ngân hàng và tài chính

Trong lĩnh vực ngân hàng và tài chính, RabbitMQ có thể được sử dụng để xử lý các giao dịch tài chính, quản lý dữ liệu khách hàng và cung cấp các dịch vụ thanh toán trực tuyến. Tính đáng tin cậy và bảo mật của RabbitMQ giúp đảm bảo rằng tất cả các giao dịch tài chính đều được xử lý một cách an toàn và chính xác.

RabbitMQ được sử dụng để cung cấp các dịch vụ thanh toán trực tuyến 

Hướng dẫn thực hành ứng dụng RabbitMQ 

Lý thuyết có thể khiến bạn cảm thấy khó hiểu một chút. Vì vậy, hãy cùng mình thực hiện một demo nhỏ để làm rõ hơn vấn đề này. Trong bài demo này, chúng ta sẽ xử lý một số lượng lớn yêu cầu từ phía client bằng cách sử dụng RabbitMQ với .NET 8 API. Cụ thể, client sẽ gửi 1000 yêu cầu đơn giản, và chúng sẽ được đưa vào hàng đợi của RabbitMQ để xử lý lần lượt.

Trong bài demo này, chúng ta sẽ sử dụng loại exchange “direct” để định tuyến các thông điệp đến các hàng đợi cụ thể. Bạn sẽ thấy cách RabbitMQ giúp quản lý hàng đợi và xử lý các yêu cầu một cách hiệu quả hơn, đảm bảo rằng không có yêu cầu nào bị bỏ sót và mọi yêu cầu đều được xử lý theo thứ tự.

*Lưu ý: Máy phải cài docker trước nhé

Xây dựng chương trình demo

Bước 1: Chạy lệnh tải về và chạy container RabbitMQ

Chạy lệnh sau: docker run -d –name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:management

-d: Chạy container dưới chế độ tách nền (detached mode).

–name rabbitmq: Đặt tên cho container là rabbitmq.

-p 5672:5672: Mở cổng 5672 để ứng dụng của bạn có thể kết nối với RabbitMQ.

-p 15672:15672: Mở cổng 15672 để truy cập giao diện quản lý web của RabbitMQ.

rabbitmq:management: Sử dụng image RabbitMQ có sẵn với plugin quản lý (management plugin).

Cụ thể về docker mình sẽ có một bài viết riêng ở những phần sau nhé! 

Bước 2: Tạo project 

Và bây giờ chúng ta tạo project ASP.NET Core Web Api theo cấu trúc ở trên.

Lưu ý bỏ Configure for HTTPS cho đơn giản nhé! 

Bước 3: Cài đặt thư viện để chuẩn bị cho việc xây dựng và triển khai ứng dụng

+ Microsoft.EntityFrameworkCore (8.0.7):

Thư viện này cung cấp ORM (Object-Relational Mapper) để làm việc với cơ sở dữ liệu trong .NET.

+ Microsoft.EntityFrameworkCore.SqlServer (8.0.7):

Thư viện này cung cấp các nhà cung cấp cụ thể cho SQL Server để sử dụng với Entity Framework Core.

+ Microsoft.EntityFrameworkCore.Tools (8.0.7):

Thư viện này cung cấp các công cụ dòng lệnh để quản lý và tạo cơ sở dữ liệu cho Entity Framework Core.

+    Microsoft.Extensions.Hosting (8.0.0):

Thư viện này hỗ trợ tạo và cấu hình các ứng dụng console và dịch vụ nền trong .NET.

+ Newtonsoft.Json (13.0.3):

Thư viện phổ biến để xử lý JSON trong .NET, hỗ trợ serializing và deserializing dữ liệu JSON.

+ RabbitMQ.Client (6.8.1):

Thư viện này cung cấp các công cụ để tương tác với RabbitMQ từ ứng dụng .NET, hỗ trợ việc gửi và nhận thông điệp qua hàng đợi.

Bước 4: Thêm connectString SqlServer và rabbitmq trong appsetting.json

* Các bạn nhớ đổi lại connectString phù hợp với máy local của bạn nhé

Bước 5: Tạo model Order (Thư mục Models)

Bước 6: Tạo class DatabaseContext.cs (Thư mục Models)

Bước 7: Tạo class RabbitMqSettings.cs (Thư mục Models)

Bước 8: Tạo interface IRabbitMqService (Thư mục interfaces)

Bước 9: Tạo RabbitMqService (Thư mục Services)

Triển khai giao diện IRabbitMqService. Lớp này chịu trách nhiệm tạo kết nối và quản lý kênh giao tiếp với RabbitMQ.

Bước 10: Tạo class OrderWorker

Lớp OrderWorker là một dịch vụ nền (background service) được triển khai từ lớp BackgroundService trong .NET. Nó chịu trách nhiệm lắng nghe thông điệp từ hàng đợi RabbitMQ và xử lý các đơn hàng.

Bước 11: Tạo OrderController

Lớp OrderController là một bộ điều khiển (controller) trong ASP.NET Core được sử dụng để xử lý các yêu cầu HTTP liên quan đến các đơn hàng.

Bước 12: Tạo Program.cs

Thiết lập các cấu hình và dịch vụ cần thiết cho ứng dụng ASP.NET Core, bao gồm cấu hình RabbitMQ, đăng ký dịch vụ điều khiển, kết nối cơ sở dữ liệu, dịch vụ RabbitMQ và dịch vụ nền OrderWorker.

Tiến hành chạy thử và kiểm tra

Mở postman lên và làm theo hướng dẫn bên dưới để test nhé!

Đầu tiên, chúng ta sẽ tạo một collections mới như hướng dẫn trong hình:

Mình đặt tên như bên dưới cho dễ quản lý:

  • GET ALL ORDER

  • CREATE AN ORDER

Chọn raw để test. Với cách này thì chỉ test với 1 đơn hàng được tạo ra thôi nhé.

Để test 1000 đơn hàng hãy làm như sau:

+ Chọn run collection

+    Bỏ chọn GET ALL ORDER

+    Iterations chọn 1000 nhé

+    Cho delay khoảng 300ms để dễ quan sát

Quan sát màn hình console chúng ta thấy kết quả từng đơn hàng lần lượt sẽ được đưa vào queue và sử lý lần lượt như hình bên dưới:

Xem video bên dưới để hình dung rõ hơn toàn bộ phần tạo, chạy thử và test chương trình:

Kết luận

RabbitMQ đã chứng tỏ mình là một công cụ mạnh mẽ và linh hoạt cho truyền thông tin nhắn trong các ứng dụng hiện đại. Với khả năng mở rộng, tính đáng tin cậy, và tính năng phong phú, RabbitMQ không chỉ đáp ứng được các nhu cầu hiện tại mà còn sẵn sàng cho các thách thức trong tương lai. Đối với các nhà phát triển và doanh nghiệp, việc sử dụng RabbitMQ có thể giúp tạo ra các ứng dụng mạnh mẽ, hiệu quả và đáng tin cậy.

Lê Tuấn Xuyên | Giảng viên FPT Aptech 

FPT Aptech trực thuộc Tổ chức Giáo dục FPT có hơn 25 năm kinh nghiệm đào tạo lập trình viên quốc tế tại Việt Nam, và luôn là sự lựa chọn ưu tiên của các sinh viên và nhà tuyển dụng.
0981578920
icons8-exercise-96