Giaosucan's blog - Chia sẻ kiến thức theo cách bá đạo

Ticker

20/recent/ticker-posts

Mô hình Message Queue trong Microservice

Bản quyền thuộc về FSoft Potato Tech Mag


Trong kiến trúc microservices, ứng dụng phần mềm được cấu thành từ các dịch vụ độc lập. Để hoàn thành một tác vụ của người dùng trên phần mềm, kết nối và giao tiếp giữa các microservices là cần thiết vì một tác vụ gồm nhiều tác động khác nhau lên các services. Vì vậy, giao tiếp giữa các microservices là một vấn đề cực kì quan trọng.

Hãy xem xét một ví dụ cụ thể sau
Service Order và Payment exposed các API để client hoặc các service khác gọi đến nó
Payment Microservice
Khi client call REST API request để thực hiện một Order. Order service nhận request xử lý business logic rồi gọi tới Payment Service qua API để thực hiện Payment.
Mô hình trên là loại mô hình kết nối Point-To-Point, các service kết nối trực tiếp với nhau thông qua API end-point. Tuy nhiên, mô hình này chỉ áp dụng với hệ thống có số lượng service nhỏ. Nếu số lượng service tăng, giao tiếp kiểu này sẽ trở nên rắc rối phức tạp, khó quản lý
Để giải quyết vấn đề trên, Microservice sử dụng mô hình Message Queue để giao tiếp giữa các service
Message queue in Microservice
Trong mô hình này, các Microservice không giao tiếp trực tiếp với nhau mà thông qua hệ thống Message Queue, giao tiếp bất đồng bộ

  • Order Microservice publish một message đến Message queue theo một topic nào đó.
  • Payment Microservice và các Microservice sẽ subscribe các message theo một topic cụ thể. Ví dụ Payment Microservice subscribe message topic “ABC” thì chỉ khi Order Microservice gửi message ABC thì nó mới nhận.
Cơ chế này tương tự như cách bạn gửi thư từ A đến B. A sẽ không đem thư đến tận nơi cho B mà gửi qua bưu điện, ghi rõ địa chỉ người nhận. Bưu điện đóng vai trò như một Message Broker để phát thư đến người nhận theo địa chỉ đã cho.
Cách này tách biệt người gửi và người nhận, và người truyền tin trung gian sẽ lưu tin nhắn đến khi người nhận có thể xử lý.
Giao tiếp giữa người gửi/ người nhận được tạo ra bởi message broker qua các tiêu chuẩn truyền tin bất đồng bộ như AMQP, MQTT.

Advance message queue protocol (AMQP)

Image result for AMQP
AMQP một giao thức internet mở và được chuẩn hóa để truyền message tin cậy giữa các ứng dụng hoặc tổ chức. AMQP giúp các chuyên gia CNTT xây dựng một hệ sinh thái tin nhắn đồng nhất, đa dạng, kết nối các hệ thống một cách tương tác và hợp tác.
https://www.amqp.org/sites/amqp.org/files/business-drivers.png
AMQP kết nối qua:

  • Tổ chức - ứng dụng trong các tổ chức khác nhau
  • Công nghệ - ứng dụng trên các nền tảng khác nhau
  • Thời gian: Hỗ trợ giao tiếp bất đồng bộ
  • Không gian - hoạt động ở khoảng cách xa hoặc trên các mạng nghèo nàn
Ngoài ra AMQP được thiết kế với các đặc điểm chính sau
AMQP properties

Ứng dụng của AMQP trong Microservice

Vì những ưu thế của AMQP, nên nó đã được sử dụng trong Microservice để thực hiện communication giữa các service
Phần này sẽ hướng dẫn bạn phát triển một service đơn giản dung AMQP

Cài đặt môi trường

Trong ví dụ này, mình sử dụng Service Broker là RabitMQ.  Một message broker dùng nền tảng AMQP khá phổ biến.
Download bộ cài RabitMQ tại đây. RabitMQ hỗ trợ cả Windows, Linux. Bài này mình sử dụng môi trường Windows
Sau khi cài đặt xong, vào thư mục cài đặt của RabitMQ
C:\Program Files (x86)\RabbitMQ Server\rabbitmq_server-3.3.4\sbin
Chạy command dưới để enable rabbitMQ plugin
rabbitmq-plugins.bat enable rabbitmq_management
Khởi động RabitMQ
rabbitmq-service.bat stop  
rabbitmq-service.bat install  
rabbitmq-service.bat start
Sau đó bạn có thể truy cập vào RabitMQ theo link sau http://localhost:15672/mgmt. Enter login guest/guest
RabbitMQ
Màn hình quản lý RabbitMQ hiển thị như ở dưới
RabbitMQ GUI

Implementation

Ở đây, mình sẽ implement 2 service. Một service đóng vai trò là producer để gửi message đến queue, service kia là consumer để nhận message này. Ngôn ngữ sử dụng là .Net core
Tạo 2 project console application .NET core tên là Producer và Consumer. Mình sử dụng package RabbitMQ.Client để giao tiếp với RabitMQ server

Producer

(P) -> [|||]
Producer sẽ send một message là hello đến RabitMQ
Tạo một connection đến RabitMQ server. Trong trường hợp này RabitMQ là local server
           var factory = new ConnectionFactory() { HostName = "localhost" };
           using (var connection = factory.CreateConnection())


Khai báo Queue
channel.QueueDeclare(queue: "hello",
                                    durable: true,
                                    exclusive: false,
                                    autoDelete: false,                                     
                                    arguments: null);


Một số tham số cần chú ý

  • Durable: true (Queue vẫn tồn tại nếu nhưng RabitMQ khởi động lại)
  • Exclusive: Được sử dụng bởi chỉ một connection và queue sẽ bị xóa khi connection đó kết thúc
  • Auto-delete: Queue sẽ bị xóa nếu như consumer cuối cùng hủy subscribe
Thực hiện publish message
channel.BasicPublish(exchange: "",
        routingKey: "hello",
        basicProperties: null,
        body: body);
Consumer
[|||] -> (C)
Consumer sẽ chạy liên tục là lắng nghe trên queue, để nhận message từ producer
Consumer cũng phải tạo connection và queue tương tự như Producer
 var factory = new ConnectionFactory() { HostName = "localhost" };
           using (var connection = factory.CreateConnection())
           using (var channel = connection.CreateModel())
           {
               channel.QueueDeclare(queue: "hello",
                                    durable: true,
                                    exclusive: false,
                                    autoDelete: false,
                                    arguments: null);
Consumer subscribe message từ Producer, khi có message đến, Event Consumer_Received sẽ được call, extract data và thực hiện business logic tương ứng
   var consumer = new EventingBasicConsumer(channel);
               consumer.Received += Consumer_Received;
               channel.BasicConsume(queue: "hello",
                   autoAck: true,
                   consumer: consumer);


 private static void Consumer_Received(object sender, BasicDeliverEventArgs e)
       {
           var body = e.Body;
           var message = Encoding.UTF8.GetString(body);
           Console.WriteLine(" [x] Received {0}", message);
       }


Chạy chương trình , bạn sẽ thấy message từ Hello World được send từ Procedure đến Consumer thông qua RabitMQ
Trên RabitMQ server, sẽ thấy queue hello được tạo ra như hình dưới
Trên đây là một demo đơn giản thể hiện việc communication giữa các Microservice với nhau thông qua Message Queue, dùng cơ chế bất đồng bộ. Thực tế, Microservice còn có nhiều hình thức communicate nữa như RPC, Rest API HTTP…
Còn rất nhiều kiến thức kĩ thuật về thế giới Microservice mà chúng ta cần phải tìm hiểu.

Đăng nhận xét

0 Nhận xét