Soyo

Facebook Messenger - Workflow

Ở phần trước mình đã tổng quan sơ qua cách làm việc tốt nhất khi làm hệ thống chat và workflow cơ bản.
Hôm nay mình sẽ đi vào chi tiết hơn để đảm bảo hệ thống không down và scale tốt.

Câu hỏi đầu tiên là làm thế nào để nhận/gởi tin nhắn hiệu quả. Chắc có lẽ mọi người cũng biết sơ qua về hệ thống chat. Chúng ta thường dùng websocket để nhận và gởi tin realtime.
Cách làm việc của websocket là khi user online, sẽ tạo một kết nối TCP vững chãi đến server. Cả server và client đều có thể gởi tin nhắn cho nhau bất kỳ lúc nào (full duplex communication). Việc kết nối TCP đó được tạo ra gọi là handshake và tồn tại đến khi nào một trong hai bên chấm dứt kết nối.

Screen-Shot-2019-09-30-at-11.24.14-PM

Câu hỏi đặt ra thứ hai là làm thế nào server có thể quản lý nhiều kết nối cùng một lúc và chuyển tin nhắn hiệu quả? Server có thể lưu bảng băm (hash table) với khoá (key) là UserId còn giá trị (value) là thông tin của kết nối được tạo khi handshake thành công. Khi có tin nhắn gởi đến user thì chỉ cần tìm kết nối với O(1) time và gởi tin nhắn đến kết nối.

Câu hỏi thứ ba là nếu user không online thì sao? Khi nhận được tin nhắn chúng ta cần lưu lại trong db, lúc có kết nối thì client có thể gọi request HTTP bình thường để lấy tin nhắn chưa đọc và tiếp tục chat nếu user kia cũng online.

Câu hỏi thứ tư, chúng ta cần bao nhiêu server? Giả định có 500 triệu kết nối cùng lúc. Một server có thể xử lý tầm 50k kết nối. Như vậy cần ít nhất 10k server (này chắc startup thành công lắm =))) và thêm Load Balancer để điều phối kết nối dựa vào UserID chẳng hạn. Có thể tham khảo AWS EC2 để biết thêm chi tiết.
https://aws.amazon.com/ec2/instance-types/

Câu hỏi cuối, làm sao để biết tin nhắn nào trước tin nhắn nào sau? Chúng ta quản lý thêm timestamp của tin nhắn khi server nhận được. Tuy nhiên có thể xày ra tình trạng sau:
User1 gởi tin nhắn M1 đến server cho User2
Server nhận được M1 ở thời gian T1
Ngay lúc đó, User2 gởi tin M2 đến server cho User1
Server nhận được tin nhắn M2 tại T2, T2 > T1
Server gởi tin nhắn M2 đến User1, M1 đến User2

User1 sẽ thấy M1->M2, mà User2 thấy M2->M1
Để giải quyết việc này chúng ta cần lưu thêm sắp xếp tin nhắn cho từng user, khi user login vào device nào thì cũng có cùng thứ tự.

Mình kết thúc phần 2 ở đây, phần sau mình sẽ phân tích tiếp cách thiết kế DB và quản lý trạng thái online user có LB.

Thân. Happy coding.

Comments