Vấn đề truyền nhận trong Azure service bus

Vấn đề truyền nhận trong Azure service bus

December 11, 2020 2 By Nam Vu

Microservice chắc chắn không ai còn xa lạ gì nữa, và vấn đề communication trong nội bộ các service của hệ thống microservice cũng là một vấn đề quan trọng mà chắc mình cũng không cần phải đề cập lại.

Nhưng với bài viết này mục đích là mình take note lại issue trong vấn đề truyền nhận dữ liệu với dung lượng lớn, hi vọng bạn đọc có thể hiểu và tránh được trong quá trình implement.

Chuyện rằng mình có 2 service Transaction dùng để xử lý logic business của dự án, và Communication để xử lý tác vụ gửi push notification, sms hay email. 

Vấn đề xảy ra là khi xử lý logic mình có một tập hợp các file attachment cần gửi email cho một tập đối tượng nào đó. 

Cách xử lý thông thường thì bạn cứ xử lý logic, check điều kiện hay validation các kiểu thôi, sau đó bạn lấy được loạt file theo điều kiện đó. Do Communication không dính dáng gì đến business nên bạn cứ get toàn bộ file rồi băm thành Stream hay Base64Content, combine chúng lại và fire event pub/sub để có thể gửi tín hiệu cho từ Transaction tới Communication để bên Communication thực hiện tác vụ gửi mail có chưa list attachment đó. 

Điều đáng nói là file attachment có dung lượng khá là lớn và khi bạn băm chúng ra gửi qua đường truyền Azure service bus thì nó sẽ văng một cái lỗi giới hạn dung lượng kiểu như này.

Microsoft.Azure.ServiceBus.MessageSizeExceededException: The received message (delivery-id:0, size:1055838 bytes) exceeds the limit (262144 bytes) currently allowed on the link. at Microsoft.Azure.ServiceBus.Core.MessageSender.OnSendAsync(IList`1 messageList) at Microsoft.Azure.ServiceBus.RetryPolicy.RunOperation(Func`1 operation, TimeSpan operationTimeout) at Microsoft.Azure.ServiceBus.RetryPolicy.RunOperation(Func`1 operation, TimeSpan operationTimeout) at Microsoft.Azure.ServiceBus.Core.MessageSender.SendAsync(IList`1 messageList) at MassTransit.Azure.ServiceBus.Core.Transport.ServiceBusSendTransport.SendPipe`1.Send(SendEndpointContext clientContext)

Vậy bạn nên làm gì trong trường hợp này.

Mình nảy ra một ý tưởng là mình lưu các danh sách file attachment đã validate theo logic và sau khi băm thành Base64Content lên Redis với một key nhất định theo logic. Sau đó fire event pub/sub như bình thường với key redis đó. Bên nhận được event thì mình dựa trên key redis để lookup list file attachment ra và gửi mail đi. Khá là đơn giản để xử lý bài toán này đúng không?

Tuy nhiên redis không phải là toàn năng, nó cũng có giới hạn về dung lượng và mặt khác thì quá trình truyền nhận redis đó khiến cho performance bị ảnh hưởng, chưa kể parser dữ liệu đó qua lại. 

Cái khó ló cái khôn, khi này mình thấy rằng các file attachment của mình hiện tại được lưu hết trên Azure Blob Storage rồi, mình sẽ kiểm tra điều kiện các thứ ở bên Transaction (nơi xử lý logic) và lưu danh sách các link Azure blob uri lại thay vì lưu Base64Content để truyền đi qua bên Communication. Khi này dung lượng của bạn sẽ giảm đi rất rất nhiều và bạn vẫn đảm bảo được nhiệm vụ của từng service. Khi Communication service nhận được event mình sẽ lên Azure Blob Storage lấy tất cả các file attachment dựa trên uri được gửi thông qua event. 

Thật đơn giản, mình đã xử lý được bài toán này rồi.

#Good job