Menu

exit
28/02/2022 - Java

Giới thiệu về RabbitMQ

Author Avatar
Quy NT

- 2 months ago

Tổng quan

Hiện nay, các ứng dụng rất lớn và liên tục được update. Với kiến trúc monolith, việc gom toàn bộ ứng dụng vào một cục làm việc nâng cấp trở nên khó khăn và mất thời gian.

Để giải quyết, lập trình viên bắt đầu tách dần ứng dụng lớn ra thành các service nhỏ. Mỗi service quản lý một cơ sở dữ liệu riêng, nằm trên một server riêng, tách biệt hoàn toàn với nhau. Kiến trúc microservice ra đời từ đó. 

Microservices with Spring

 

Nhưng với việc tách thành các service nhỏ thì việc giao tiếp giữa các service là vô cùng lớn và phức tạp. Hãy tưởng tượng, hiện bạn đang có một web service, phải nhận rất rất nhiều request mỗi giây, mà lại phải đảm bảo rằng không có bất cứ một request nào bị mất. Và web service của bạn luôn luôn sẵn sàng tiếp nhận request mới thay vì locked bởi đang xử lí request trước đó. 

kafka là gì

Vậy ý tưởng ở đây là đặt chúng vào một queue giữa web service và processing service. Lúc này sẽ đảm bảo rằng 2 process sẽ hoàn toàn tách rời nhau. Ngoài ra, queue sẽ lưu trữ những request, không bị thiếu sót request nào khi số lượng của chúng trở nên vô cùng lớn.

mess-queue

Và hôm nay chúng ta sẽ đi tìm hiểu về một trong những Message Queue phổ biến nhất hiện nay - RabbitMQ

1. RabbitMQ là gì?

- RabbitMQ là một message Broker (MOM – Message-Oriented Middleware), sử dụng giao thức AMQP (Advanced Message Queue Protocol).

- RabbitMQ được viết bằng ngôn ngữ Erlang.

- RabbitMQ là một phần mềm trung gian được sử dụng để trao đổi dữ liệu giữa các process, application, system hoặc server. RabbitMQ sẽ nhận message đến từ các thành phần khác nhau trong hệ thống, lưu trữ chúng an toàn trước khi đẩy đến đích.

- RabbitMQ chạy trên nhiều OS, Cloud và cung cấp một loạt các công cụ dành cho nhà phát triển với hầu hết các ngôn ngữ phổ biến.

- RabbitMQ không phải là một JMS Provider, nhưng nó cung cấp plugin cần thiết hỗ trợ mô hình JMS Queue và JMS Topic.

2.Tại sao sử dụng RabbitMQ?

2.1 Vấn đề

○ Đối với các hệ thống sử dụng kiến trúc microservice thì việc gọi chéo giữa các service khá nhiều, khiến cho luồng xử lý khá phức tạp.

○ Mức độ trao đổi data giữa các thành phần tăng lên khiến cho việc lập trình trở nên khó khăn hơn (vấn đề maintain khá đau đầu).

○ Khi phát triển ứng dụng làm sao để các lập trình viên tập trung vào các domain, business logic thay vì các công việc trao đổi ở tầng infrastructure.

○ Với các hệ thống phân tán, khi việc giao tiếp giữa các thành phần với nhau đòi hỏi chúng cần phải biết nhau. Nhưng điều này gây rắc rối cho việc viết code. Một thành phần phải biết quá nhiều dẫn đến rất khó maintain, debug.

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

- Producer: Ứng dụng gửi message.

- Consumer: Ứng dụng nhận message.

- Queue: Lưu trữ messages.

- Message: Thông tin truyền từ Producer đến Consumer qua RabbitMQ.

- Exchange: Là nơi nhận message được publish từ Producer và đẩy chúng vào queue dựa vào quy tắc của từng loại Exchange. Để nhận được message, queue phải được nằm (binding) trong ít nhất 1 Exchange.

- Binding: là quy tắc (rule) mà Exchange sử dụng để định tuyến Message đến Queue. Đảm nhận nhiệm vụ liên kết giữa Exchange và Queue.

- Routing key: Một key mà Exchange dựa vào đó để quyết định cách để định tuyến message đến queue. Có thể hiểu nôm na, Routing key là địa chỉ dành cho message.

2.3 Các tính năng

Transparency: Một producer không cần phải biết consumer. Nó chỉ việc gửi message đến các queue trong message broker. Consumer chỉ việc đăng ký nhận message từ các queue này.

Many Client: Vì producer giao tiếp với consumer trung gian qua message broker nên dù producer và consumer có khác biệt nhau về ngôn ngữ thì giao tiếp vẫn thành công. Hiện nay rabbitmq đã hỗ trợ rất nhiều ngôn ngữ khác nhau.

Asynchronous (bất đồng bộ): Producer không thể biết khi nào message đến được consumer hay khi nào message được consumer xử lý xong. Đối với producer, đẩy message đến message broker là xong việc. Consumer sẽ lấy message về khi nó muốn. Đặc tính này có thể được tận dụng để xây dựng các hệ thống lưu trữ và xử lý log.

Flexible Routing: message được định tuyến (route) thông qua Exchange trước khi đến Queue. RabbitMQ cung cấp một số loại Exchange thường dùng, chúng ta cũng có thể định nghĩa riêng Exhange cho riêng mình.

Lightweight, Multiple message protocol, Cluster,...

3. RabbitMQ hoạt động như thế nào ?

Picture1

 

  1. Producer đẩy message vào Exchange. Khi tạo Exchange, bạn phải mô tả nó thuộc loại gì. Các loại Exchange sẽ được giải thích phía dưới.
  2. Sau khi Exchange nhận Message, nó chịu trách nhiệm định tuyến message. Exchange sẽ chịu trách nhiệm về các thuộc tính của Message, ví dụ routing key, loại Exchange.
  3. Việc binding phải được tạo từ Exchange đến Queue (hàng đợi). Trong trường hợp này, ta sẽ có hai binding đến hai hàng đợi khác nhau từ một Exchange. Exchange sẽ định tuyến Message vào các hàng đợi dựa trên thuộc tính của của từng Message.
  4. Các Message nằm ở hàng đợi đến khi chúng được xử lý bởi một Consumer.
  5. Consumer xử lý Message nhận từ Queue.

4. Exchange và các loại Exchange

4.1 Exchange

Picture2

 

•Message không được publish trực tiếp vào Queue; thay vào đó, Producer gửi message đến Exchange.

•Exchange là nơi mà các message được gởi. Exchange nhận tin nhắn và định tuyến nó đến 0 hoặc nhiều Queue với sự trợ giúp của các ràng buộc (binding) và các khóa định tuyến (routing key)

•Thuật toán định tuyến được sử dụng phụ thuộc vào loại Exchange và quy tắc (còn gọi là ràng buộc hay binding).

•Có 4 loại Exchange: Direct, Fanout, Topic. Lựa chọn các exchange type khác nhau sẽ dẫn đến các đối xử khác nhau của message broker với tin nhắn nhận được từ producer. Exchange được bind (liên kêt) đến một số Queue nhất định.

4.2 Các loại Exchange

4.2.1 Direct Exchange

Picture3

Direct Exchange (trao đổi trực tiếp) định tuyến message đến Queue dựa vào routing key. Thường được sử dụng cho việc định tuyến tin nhắn unicast-đơn hướng (mặc dù nó có thể sử dụng cho định tuyến multicast-đa hướng):

•Một queue được ràng buộc với một direct exchange bởi một routing key K.

•Khi có một message mới với routing key R đến direct exchange. Message sẽ được chuyển tới queue đó nếu R=K.

Direct Exchange hữu ích khi muốn phân biệt các thông báo được publish cho cùng một exchange bằng cách sử dụng một mã định danh chuỗi đơn giản.

Ví dụ: nếu hàng đợi (Queue) gắn với một exchange có binding key là pdf_create, message được đẩy vào exchange với routing key là pdf_create sẽ được đưa vào hàng đợi này.

 

4.2.2 Fanout Exchange

Picture4

 

Fanout Exchange định tuyến message (copy message) tới tất cả queue mà nó được bind, với bất kể một routing key nào. Giả sử, nếu nó N queue được bind bởi một Fanout exchange, khi một message mới published, exchange sẽ định tuyến message đó tới tất cả N queues. Fanout exchange được sử dụng cho định tuyến message broadcast (quảng bá).

Fanout Exchange  hữu ích với trường hợp ta cần một dữ liệu được gửi tới nhiều ứng dụng khác nhau với cùng một message nhưng cách xử lý ở ứng dụng là khác nhau.

 

4.2.3 Topic Exchange

Picture5

 

Topic exchange định tuyến message tới một hoặc nhiều queue dựa trên sự trùng khớp giữa routing key pattern. Topic exchange thường sử dụng để thực hiện định tuyến thông điệp multicast.

•Một topic exchange sẽ sử dụng wildcard để gắn routing key với một routing pattern khai báo trong binding. Consumer có thể đăng ký những topic mà nó quan tâm.

Ví dụ:

   - agreements.*.headstore : Được đăng ký bởi tất cả những key với pattern bắt đầu bằng agreements, theo sau là một từ bất kỳ và kết thúc là headstore.

   - agreements.# : Được đăng ký bởi tất cả các key bắt đầu với agreements.

Sử dụng: Cập nhật tin tức liên quan đến một category hoặc gắn tag, điều phối các dịch vụ của các loại khác nhau trong cloud,...

5. Xây dựng ứng dụng với Spring Boot và RabbitMQ

- Tạo một ứng dụng Spring Boot với những dependencies sau:

Screenshot-2022-02-28-133606

 

- Cấu hình RabbitMQ trong file application.properties:

Screenshot-2022-02-28-133805


 - Tạo file RabbitConfiguration.java để cấu hình:

Screenshot-2022-02-28-134148

Ở đây chúng ta sẽ sử dụng Topic Exchange.

Đoạn code này có ý nghĩa là chúng ta sẽ tạo ra lần lượt queue có tên là “topic.queue.1” và “topic.queue.2” , một topic exchange tên là “topic.exchange” và các queue này sẽ được đăng kí nhận message từ exchange này qua  2 ROUTING có partern lần lượt là “topic.*.test” và  “#.topic”.

 - Tạo file ConsumerConfig.java để Listener:

Screenshot-2022-02-28-134731

 

- Tạo file RabbitMQProducer.java để tạo message:

Screenshot-2022-02-28-134939

 

- Sau khi khởi chạy chương trình thì Exchange và Queue sẽ được khởi tạo:

Screenshot-2022-02-28-135552

 

Screenshot-2022-02-28-135729

 

- Tạo Message bằng Postman:

Tạo Message với routing pattern #.topic

Screenshot-2022-02-28-135853

 

Tạo Message với routing pattern topic.*.test

Screenshot-2022-02-28-140052

 

- Message sẽ được đưa vào hàng đợi:

Screenshot-2022-02-28-140306

 

- Kiểm tra phía Consumer:

Screenshot-2022-02-28-140708

Vậy là Listener đã lắng nghe được khi mà message được push đến queue được đăng kí.

6.Tạm kết

Như vậy trong bài này mình đã chia sẻ về RabbitMQ, một bộ phận không thể thiếu trong các hệ thống lớn, các hệ thống sử dụng microservice.

Mọi người có thể tham khảo source code đầy đủ ở đây.

#Tag

Bình luận (2)

Avatar
Nội dung bình luận
Avatar
Lương Minh Trường 2 months ago

Bài viết thật bổ ích, cảm ơn admin 💕

Avatar
Lương Minh Trường 2 months ago

Quá ghê gớm, một bài viết phải nói là cực gắt, Nghĩa có người yêu

Bài viết nên đọc

Blog Image
January 22, 2022

Lộ trình bắt đầu học lập trình iOS

Bao gồm toàn bộ những công cụ, khoá học, roadmap để bắt đầu học lập trình iOS

Blog Image
March 07, 2022

Tìm hiểu về Flutter Linter và Flutter Static Analysis

Giới thiệu về Flutter Linter và Flutter Analyzer

Blog Image
March 23, 2022

Áp dụng nguyên lý SOLID trong iOS

SOLID là gì? Và cách áp dụng những nguyên tắc này trong lập trình Swift (iOS).

Blog Image
May 15, 2022

Hiệu ứng làm mờ background khi chụp ảnh trong ứng dụng iOS

Nếu chúng ta muốn sử dụng hiệu ứng làm mờ background phía sau khuôn mặt vào custom camera trong một ứng dụng iOS thì chúng ta phải làm như thế nào?