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

Ticker

20/recent/ticker-posts

Logging service - Part 2

 3.2.2. Logging — EdgeX documentation


Tiếp tục phần 1, bài này tiếp tục trình bày giải pháp logging service chi tiết hơn về deployment và implementation

Sau khi lựa chọn giải pháp implement service log, team nghiên cứu architect của service logging. Một số pattern architect được xem xét như MVC, Clean Architect, controller service repository. Các technical stack cũng được thử nghiệm như Java, .Netcore, .nodejs 

Sau nhiều đánh giá, team quyết định sử dụng clean architect và .netcore cho service logging. 

Architect

Nói sơ qua về kiến trúc Clean Architect, đây là mô hình gồm các layer từ Web, Controller, Uses Cases, Entities phụ thuộc theo hướng từ ngoài vào trong, từ cao xuống thấp

Clean Architecture: Đứng trên vai những gã khổng lồ


Ví dụ Entities là business logic là lõi core, ko phụ thuộc vào layer nào.

Uses cases phụ thuộc vào entities only

Các layer ngoài cùng cũng tương tự như vậy.

Mấy kiến thức lý thuyết thì độc giả cứ lên GG tra cứu.

Còn giải thích theo kiểu giaosucan’s blog thì hiểu đơn giản thế này

Clean Architect cũng giống như cái nhà nhiều tầng từ 1 đến 4. Thì tầng 1 là tầng core business, tầng 4 là tầng web.

Rõ ràng tầng 1 là quan trọng nhất vì nó đỡ cả 3 tầng trên, muốn lên tầng 3 kiểu gì cũng phải đi qua tầng 1 rồi tầng 2 mới đến 3. Tức là tầng ngoài cùng dependency với các tầng dưới. 

Tầng 4 dependency với 1, 2, 3.

Tầng 3 dependency với tầng 1, 2

Tầng 2 dependency với tầng 1

Tầng 1 không dependency với tầng nào cả

Khi vào bài toán thực tế số tầng có thể thay đổi nhiều hơn hoặc ít hơn nhưng nguyên tắc dependency phải giữ nguyên.

Team thiết kế architect của service có 1 số điều chỉnh cho phù hợp với 3 tầng như dưới

Layer web define các api post log 

Core define entities, service để thực hiên log logging (push log vào rabbitmq)

Infrastructure xử lý giao tiếp với external như DB

Implementation

Về basic thì việc implement vẫn theo các pattern cơ bản, nên bài viết này không giải thích nhiều. Có 1 điểu khác biệt ở đây là cách xử lý api post log

Các app gọi đẩy log tới service log bằng gọi rest API kiểu như /api/v1/log rồi truyền body là json log data như env, log message, log type … 

Controller invoke tầng service để thực hiện push log vào rabbitmq (dùng rabbitmq API) rồi return kết quả

Tuy nhiên cách này sẽ có rủi ro như sau

Số lượng request API Logging service rất lớn, nếu mỗi lần gọi api lại push log rabbit như trên, trong trường hợp rabbitmq service bị lỗi, việc push log có thể bị timeout. Trong khi service log chưa hoàn thành việc push log thì log mới liên tục được các app đẩy vào có thể gây nghẽn cổ chai và mất log.

Giải pháp được đưa ra, đó là sử dụng một ConcurrentBag. Một dạng list thread-safe trong C#. Khi log được đẩy tới, log object sẽ được push thẳng vào conccurentbag này. Một thread background sẽ chạy ngầm làm việc take từng object ra để đẩy vào queue

image

Như vậy khi app call API logging, thực chất là push log vào bag, nên response sẽ rất nhanh, không bị nghẽn cổ chai. Background thread chạy get dần dần từng object logs ra để push vào queue
Về phần app, việc ghi log thực chất là gọi API restful request. Tuy nhiên không thể implement trực tiếp việc gọi API này trong app được vì lí do sau
Nếu có thay đổi gì về API ghi log (parameter, endpoint, payload etc…) phải sửa lại môt loạt trên các app
Duplicate code vi phạm DRY trong coding
...

Giải pháp đưa ra là implement một nudget library, một dạng wrapper việc call API rồi add vào từng project app như thư viện. Developer muốn ghi log thì chỉ việc gọi hàm hiểu log.debug(), log.info như các framework log thông thường là được


Deployment

Logging service được build thành docker rồi deploy lên K8S, dùng ingres controller

Bài tiếp theo sẽ trình giải pháp Logstash & RabbitMQ để lấy log từ rabbitmq đẩy vào ES



Đăng nhận xét

1 Nhận xét