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

Ticker

20/recent/ticker-posts

Lời Nguyền Project 03

Bài viết đã được Fsoft Potato Tech Mag mua bản quyền


Đã 3 tháng nay, cả Fsoft xôn xao về những cái chết bí ẩn của member thuộc dự án 03.
Huy, PM đầu tiên của dự án, đã qua đời trong một tai nạn giao thông rất bi thảm. Bị ngã xe, đầu đập xuống đất, sọ não vỡ làm đôi. Rồi tiếp đó là Đức, solution architect của dự án, anh bị ngã từ trên tầng 6 của tòa F-Complex, toàn thân dập nát, chết ngay tại chỗ. Kỳ lạ thay, cả 2 đều chết cùng một ngày thứ 6, ngày 13 và tại chính tòa nhà F-Complex….
Thế rồi, người ta cứ đồn thổi, thêu dệt những câu chuyện ma quỷ về những cái chết đó. Người mê tín thì cho rằng có oan hồn của một coder nào không siêu thoát được nên cứ luẩn quất trong tòa nhà F-Complex. Người tin vào khoa học thì chỉ cho rằng đó là chuyện trùng hợp ngẫu nhiên. Fsofter nghe đến dự án 03 đều sợ xanh mặt, dù cho sếp cho treo thưởng F-coin cao đến mấy cũng không dám tham gia. Riêng tối, vốn chẳng tin vào chuyện ma quỷ, nên quyết định xin BUL tham gia dự án với role Solution Architect.
Đó là một đêm trăng rằm Tết trung thu, lúc đó đã là 12h đêm. Tôi phải ngồi lại 1 mình ở công ty để xử lý hết đống bug để kịp deliver vào ngày mai, và trùng hợp thay, lại một ngày thứ 6 ngày 13…
Trời mưa rơi tầm tã, từng cơn gió rít lạnh buốt đến tận xương. F-Complex không một bóng người, trong ánh chớp nhập nhòe, tôi bỗng thấy một bóng trắng ngoài cửa sổ. Lấy hết can đảm, tôi đi ra xem sao thì trời ơi, đó là một cái xác người treo cổ. Cái mái tóc đen dài che kín nửa khuôn mặt, cái áo trắng toát che khuất không thấy cả đôi chân, dù dưới cái ánh sáng lập lòe của ánh chớp nhưng tôi vẫn có thể nhìn rõ nửa mặt bên kia của nó. Cái khuôn mặt trắng bệch, nổi lên từng cọng gân xanh, đầu nó ngã nghiêng sang phải, con mắt sâu hun hút, đen ngòm nhìn trừng trừng vào tôi, ánh mắt thì đầy lạnh lẽo, chết chóc chả khác gì cơn gió lúc nãy
Trên tay cái xác, vẫn cầm mảnh giấy được viết bằng máu. Tôi lấy hết can đảm cầm lấy tờ giấy đọc và chợt hiểu ra câu chuyện…
Project 03 là một dự án migration từ kiến trúc monolithic sang nền tảng microservice. Đó là một công việc đầy thử thách do xây dựng và quản lý một hệ thống phân tán là vô cùng khó khăn. Lan, nữ PM đầu tiên của dự án, do không chịu nổi áp lực từ phía khách hàng và ban lãnh đạo, cô đã treo cổ tự vẫn ngay tại khoang làm việc này. Trước khi chết, cô đã để lại một lời nguyền chết chóc “PM hay SA nào tham gia dự án 03, mà không migrate được hệ thống sang microservice thành công sẽ phải đón nhận cái chết thảm khốc vào thứ 6, ngày 13…”
Đọc xong mảnh giấy, tôi đã biết mình đã mắc phải lời nguyền, muốn thoát khỏi nó, phải đưa ra được chiến lược migration hiệu quả. Tôi quyết đinh đưa ra giải pháp của mình đó là áp dụng mô hình Event Sourcing
Event Sourcing là gì??
Hãy tưởng tượng trong một hệ thống microservice bao gồm 2 service như sau. Mỗi service thực hiện một task vụ duy nhất gọi là Single Responsibly Service (SRS)


  • Cursed SRS lưu trữ thông tin lời nguyền trong database (cursed Id, thông tin của người bị nguyền rủa)
  • Death SRS thực thi lời nguyền (ban cái chết cho kẻ bị nguyền rủa)

Tuy nhiên, trong kiến trúc Microservice, các service sở hữu database riêng, data model riêng, deploy độc lập trên các server instance riêng. Chúng là deployable và independent.
Như vậy với mô hình trên, khi Cursed SRS tạo 1 record thông tin lời nguyền vào trong DB, thì Death SRS không biết gì cả. Dẫn tới việc lời nguyền được tạo ra nhưng không có ai bị trừng phạt. Dẫn tới việc data inconsistency trong cả hệ thống
Hơn nữa do Cursed SRS làm thay đổi trạng thái hệ thống nên cần phải có cách lưu hoạt động của nó dưới dạng log. Thông thường trong các hệ thống cho doanh nghiệp thì việc ghi log là rất cần thiết. Nhờ hệ thống log có thể xác định lại trạng thái của hệ thống tại một thời điểm nào đó trong quá khứ. Qua đó giúp xác định được nguyên nhân gây ra những thay đổi trong hệ thống.
Do đó cần có cơ chế để Cursed SRS có thể lưu trữ và gửi 1 event thông báo cho toàn hệ thống biết là đã có sự kiện một lời nguyền được tạo và cần có kẻ bị trừng phạt.
Nguyên tắc hoạt động
Mô hình event sourcing giải quyết được vấn đề này.
Nguyên tắc hoạt động như sau


  • Cursed SRS khi tạo ra 1 lời nguyền (thay đổi trạng thái hệ thống)
  • Cursed published một domain event là CursedCreated vào 1 event store để thông báo cho các service khác. 
  • Death SRS subscribed domain event này
  • Khi nhận được event từ Cursed SRS sẽ cập nhật vào database Deadth 


Trong sơ đồ trên, Event Store hoạt động giống như một database lưu luôn các trạng thái thay đổi của hệ thống tại từng thời điểm để tiện track back sau này. Event Store cung cấp các API để có thể thêm vào và lấy ra các domain event. Nó còn hoạt động giống như một message broker để các service khác có thể publish/subcribed message  
Event Sourcing (ES) giúp mô hình hóa trạng thái hệ thống thành 1 chuỗi các event thay vì chỉ là 1 trạng thái tĩnh tại 1 thời điểm
Event Sourcing được sử dụng rộng rãi trong các hệ thống tài chính, ngân hàng. Dữ liệu của một tài khoản sẽ được lưu thành một chuỗi các transaction đã thực hiện từ khi tài khoản được tạo. Nhờ vậy, bất kì khi nào có một sai lệch, hệ thống có thể trace back lại tại tận nguồn gốc gây ra thay đổi. Event Soucring cũng sử dụng trong các hệ thống audit của database như transaction log.
Implementation
Để implement mô hình trên, tôi quyêt định sử dụng Apache Kafka để build event store trong hệ thống
https://kafka.apache.org/images/kafka_diagram.png
Về cơ bản kafka là hệ thống message pub/sub phân tán mà có khả năng scale rất tốt. Message của kafka được lưu trên đĩa cứng, đồng thời được replicate trong cluster giúp phòng tránh mất dữ liệu. Kafka còn thể hiểu là một hệ thống logging, nhằm lưu lại các trạng thái của hệ thống, nhằm phòng tránh mất thông tin.
Related image


  • Kafka lưu, phân loại message theo topics
  • Kafka sử dụng producers để publish message vào các topics ở trên
  • Kafka sử dụng consumers để subscribe vào topics, sau đó xử lý các message lấy được theo một logic nào đó
  • Kafka thường được chạy dưới dạng cluster, khi đó mỗi server trong đó sẽ được gọi là broker
Việc cài đặt Kafka khá đơn giản, có thể cài đặt trên môi trường windows hoặc Linux đều ổn. Cần cài đặt môi trường Java và download bộ cài Kafka ở đây http://kafka.apache.org/
Khi down về giải nén sẽ thấy hai thư mục là Kafka và Zookeeper. Zookeeper quản lý toàn bộ quy trình (workflow) việc khởi động (start) và dừng (stop) các nodes khác nhau trong cluster của Kafka
Đối với dự án này, tôi setup Kafka trên môi trường Linux
Khởi động Zookeeper
bin/zookeeper-server-start.sh config/zookeeper.properties
Sau đó mới khỏi động Kafka
bin/kafka-server-start.sh config/server.properties
Như vậy Kafka đã được setup thành công và running ở localhost:2181
Hai Microservice ở trên được implement bằng NodeJS để tận dụng sức mạnh của ngôn ngữ JavaScript.


  • Cursed service publish event topic ‘cursed-death’ vào Kafka 
  • Death service subscribed event trên
  • Death service nhận được event từ cursed service sẽ thực hiện business logic tương ứng
Kafka cung cấp thư viện nodejs kafka-node cho phép developer giao tiếp với Kafka
Khai báo thư viện
var kafka = require('kafka-node');
var HighLevelProducer = kafka.HighLevelProducer;
var KeyedMessage = kafka.KeyedMessage;
var Client = kafka.Client;


Khởi tạo Kafka client
var client = new Client('localhost:2181', 'my-client-id', {
   sessionTimeout: 300,
   spinDelay: 100,
   retries: 2
 });
 
 // For this demo we just log client errors to the console.
 client.on('error', function(error) {
   console.error(error);
 });


Cursed Service produce một event vào Kafka
// Create a new payload
var payload = [{
   topic: 'cursed-death’ ',
   messages: 'you will die',
   attributes: 1 /* Use GZip compression for the payload */
 }];

 //Send payload to Kafka and log result/error
 producer.send(payload, function(error, result) {
   console.info('Sent payload to Kafka: ', payload);
   if (error) {
     console.error(error);
   } else {
     var formattedResult = result[0]
     console.log('result: ', result)
   }
 });
});


Death Service consume message từ Cursed Service
Death Service cũng khởi tạo Kafka client tương tự như Cursed Service. Nó subscribed topics cursed-death ở trên.
var consumer = new HighLevelConsumer(client, topics, options);
consumer.on('message', function(message) {  
 console.log(decodedMessage);
 // execute the curse
});



Như vậy mỗi khi Cursed Service publish event với topic cursed-death, Death Service sẽ nhận được event, extract data từ message và thực hiện lời nguyền. Đảm bảo dữ liệu đồng nhất
Các event trên được lưu trữ trong Kafka, mỗi khi hệ thống bị trục trặc, admin có thể kiểm tra thông tin event để tìm lỗi của hệ thống…
Sau khi áp dụng mô hình Event Sourcing với Kafka vào dự án, Tôi đã deliver thành công cho khách hàng và chắc mẩm mình đã thoát khỏi lời nguyền…
3 tháng trôi qua kể từ ngày deliver cho khách hàng, mọi thứ đều diễn ra êm đẹp. Không còn ai nhắc đến lời nguyền project 03 nữa,
Đêm ấy, tôi lại ngồi OT, trời lại mưa tầm tã. Cơn gió bên ngoài cứ thổi làm cho hai cái cửa sổ đập vào nhau chang chát, đèn trong khoang làm việc bỗng phụt tắt. Ngoài cửa sổ, một cái bóng trắng treo cổ đong đưa theo gió, trên áo hiện lên dòng chữ bằng máu
Tôi chết lặng người, chợt trên tường tiếng chuông điểm 12h đêm báo hiệu ngày mới.
Thứ 6 ngày 13….

Đăng nhận xét

1 Nhận xét