- vừa được xem lúc

Message broker là gì? Sơ lược về RabbitMQ và ứng dụng demo

0 0 49

Người đăng: Nguyen Van Son

Theo Viblo Asia

Trong kiến trúc cloud (hay microservices), các ứng dụng được chia thành những khối độc lập nhỏ hơn để có thể dễ dàng develop, deploy và maintain. Hãy thử tưởng tượng bạn có một kiến trúc cloud có nhiều service và nhiều request mỗi giây, bạn 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 đó cũng như phải đảm bảo rằng các service giao tiếp với nhau một cách trơn tru và hiệu quả.

Vậy bạn làm thế nào? Câu trả lời đó chính là Message Broker!

Message broker là gì?

Message broker (hay còn gọi là integration broker hoặc interface engine) là một module trung gian trung chuyển message từ người gửi đến người nhận. Nó là một mô hình kiến trúc (architentural pattern) để kiểm tra, trung chuyển và điều hướng message; làm trung gian giữa các ứng dụng với nhau, tối giản hóa giao tiếp giữa các ứng dụng đó và để tăng hiệu quả tối đa cho việc tách ra các khối nhỏ hơn. Nhiệm vụ chính của một Message broker là tiếp nhận những message từ các ứng dụng và thực hiện một thao tác nào đó. Hãy cùng nhìn vào sequence diagram dưới đây:

Message Broker pattern sequence diagram

Như ta có thể thấy, trong quá trình Initialize, Service1Sevice2 init, rồi sau đó load proxyregister đến Broker. Từ đó, Broker sẽ trung chuyển các message đến với proxy đã được register từ trước. Pattern này sẽ có những lợi ích sau:

  • Service1Service2 không cần phải biết nhau. Nó chỉ việc gửi message đến proxy, rồi từ đó proxy sẽ forward message đến Broker. Rồi từ đó Broker sẽ forward message đến Service1Service2 mà chúng đã đăng kí nhận message từ trước.
  • Service1Service2 giao tiếp trung gian qua Broker nên dù có khác nhau về ngôn ngữ thì vẫn giao tiếp thành công.
  • Với design pattern này, chúng ta có thể setup cơ chế bất đồng bộ (asynchronous). Đối với Service1 thì nó không cần quan tâm khi nào message đến tay Service2 hay khi nào Service2 xử lý xong, nó chỉ cần đấy message đến Message Broker là xong việc. Service2 sẽ lấy message bất cứ khi nào 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.

Hiện tại có rất nhiều các message broker software có thể kể đến như: Amazon Web Services (AWS) Simple Queue Service (SQS), Apache Kafka, Apache ActiveMQ. Nhưng phổ biến nhất trong số những cái tên kể trên đó là RabbitMQ!

RabbitMQ là gì?

RabbitMQ là một Message broker open-source, ban đầu được dùng cho Advanced Message Queuing Protocol (AMQP), sau đó đã được phát triển để hỗ trợ Streaming Text Oriented Messaging Protocol (STOMP), Message Queuing Telemetry Transport (MQTT), và những giao thức khác. Tuy nhiên, trong bài viết này thì mình sẽ không đi sâu vào các protocol nói trên. RabbitMQ được viết bằng Erlang, một ngôn ngữ không phổ biến nhưng khá phù hợp với các công việc của Message Broker.

RabbitMQ và trong messaging nói chung sử dụng những thuật như sau:

  • Producing có nghĩa đơn giản là gửi. Ứng dụng gửi message được gọi là Producer.

  • Queue là một post box nằm trong RabbitMQ. Message di chuyển qua RabbitMQ và ứng dụng của bạn nhưng chúng chỉ có thể được lưu trong queue. Queue được giới hạn trong memorydisk của host. Về bản chất, nó là một bộ nhớ đệm message với dữ liệu lớn. Nhiều producer có thể gửi message vào một queue và nhiều consumer có thể nhận data từ một queue:

  • Consuming có nghĩa tương tự như nhận. Consumer là một ứng dụng chủ yếu chờ để nhận message:

Lưu ý rằng producer, consumerbroker không cần phải phụ thuộc vào cùng một host. Trên thực tế rất hiếm có những ứng dụng như vậy. Một ứng dụng cũng có thể vừa là producer và vừa là consumer.

Hello World!

Trong bài viết này, chúng ta sẽ dùng Bunny Ruby Client để làm ví dụ về một producer gửi message và một consumer nhận message và in ra màn hình. Trong hình dưới đây, PproducerCconsumer, box ở giữa là một queue:

Đầu tiên, ta cài đặt Bunny:

gem install bunny --version ">= 2.13.0"

Sending

Chúng ta sẽ viết message producer trong sender.rbmessage consumer trong receiver.rb. producer sẽ kết nối đến RabbitMQ, gửi một message rồi exit.

#!/usr/bin/env ruby require "bunny" connection = Bunny.new(hostname: "rabbit.local")
connection.start

connection sẽ lấy một socket connection, xử lý version của protocol, xác thực và những thứ khác. Trong ví dụ này, ta sẽ connect đến local, nếu muốn connect đến một host khác thì chỉ cần dùng option :hostname và chỉ định domain name hoặc địa chỉ IP của nó. Tiếp đến, chúng ta tạo một channel, một queue để gửi message:

channel = connection.create_channel # tạo một channel queue = channel.queue("hello") # tạo queue tên là "hello" channel.default_exchange.publish("Hello World!", routing_key: queue.name)
puts " [x] Sent \"Hello World!\""

queue sẽ chỉ được tạo nếu như nó chưa tồn tại, message là một byte array nên bạn có thể truyền bất cứ thứ gì bạn muốn. Cuối cùng, ta close connecion:

connection.close

Receiving

Giờ, consumer sẽ listen message từ RabbitMQ. Khác với producer, consumer sẽ chạy để listen message và in chúng ra màn hình.

Tương tự như producer, ta mở connectionchannel, khai báo queue, lưu ý rằng tên của queue phải giống queue bên sender.rb:

#!/usr/bin/env ruby require "bunny" connection = Bunny.new(hostname: "rabbit.local")
connection.start channel = connection.create_channel # tạo một channel queue = channel.queue("hello") # tạo queue với tên giống với sender.rb

Ở đây, ta cũng khai báo queue để chắc chắn rằng queue đã tồn tại trước khi consumer message.

Bunny::Queue#subscribe sẽ deliver message từ queue và nó cũng là một callback được thực thi khi RabbitMQ đẩy message đến consumer một cách bất đồng bộ:

begin puts " [*] Waiting for messages. To exit press CTRL+C" queue.subscribe(block: true) do |_delivery_info, _properties, body| puts " [x] Received #{body}" end
rescue Interrupt => _ connection.close exit(0)
end

Ở đây, để tránh trường hợp receiver.rb kết thúc ngay lập tức, Bunny::Queue#subscribe dùng một block để chờ thread được thực thi.

Bây giờ, chạy consumer:

ruby receiver.rb

sau đó chạy sender:

ruby sender.rb

consumer sẽ in message nó nhận được từ producer thông qua RabbitMQ. Consumer sẽ vẫn tiếp tục chạy để chờ message.

Hãy thử chạy producer trên một terminal khác để hiểu rõ hơn nhé!

Tài liệu tham khảo

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 500

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 376

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 701

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 335

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 421

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 414