Ghi Chú Phát Triển (11): Dịch Vụ Phát Đa Điểm
Gần đây công ty vừa tuyển thêm 5 lập trình viên mới, trước khi họ chính thức nhận việc, tôi muốn dành thời gian tập trung vào việc xây dựng kiến trúc nền tảng thay vì sa đà vào các chi tiết triển khai game. Ngoài việc bảo trì các đoạn mã cũ và sửa chữa những lỗi phát sinh, tôi dự định sẽ hoàn thiện thêm một số module cơ sở. Những module này tuy không bắt buộc phải có ngay lập tức, nhưng khi hoàn thiện sẽ dễ dàng tích hợp vào hệ thống hiện tại, đồng thời giúp phân chia công việc rõ ràng hơn cho các thành viên mới.
Một trong những module quan trọng là cơ chế phát đa điểm (multicast) giữa các server.
Trước tiên, hãy cùng ôn lại kiến trúc server đã đề cập trước đây (Skynet), vốn đã giải quyết tốt bài toán định danh các node và khả năng truyền tin giữa các node. Nếu giữ nguyên giao thức hiện tại, phương pháp đơn giản nhất để triển khai multicast là tạo một node đặc biệt đóng vai trò quản lý nhóm, đảm nhận việc chuyển tiếp tin nhắn đến tất cả thành viên trong nhóm.
Cơ chế này tương tự nguyên lý phát đa điểm trong mạng LAN theo giao thức UDP. Khi còn làm tại NetEase, tôi đã từng triển khai một dịch vụ tương tự, có thể tham khảo tại bài blog này. Tuy nhiên lần này việc xây dựng trên một kiến trúc mới đòi hỏi một số điều chỉnh nhỏ.
Vấn đề cốt lõi nằm ở việc quản lý nhóm (thêm/xóa thành viên) và cách phân biệt các nhóm với nhau. Về mặt lý thuyết, quản lý nhóm và việc phát đa điểm nên chia sẻ cùng một nguồn dữ liệu (danh sách thành viên). Để đảm bảo tính nhất quán giữa giao diện và thực thể vật lý, tốt nhất nên tích hợp cả hai chức năng này vào cùng một node nhóm. Tuy nhiên giải pháp này đòi hỏi phải sửa đổi API khung mạng hiện tại, nên tôi đã loại bỏ phương án này.
Phương án tự nhiên hơn là tập trung toàn bộ logic quản lý nhóm tại một dịch vụ có tên định danh. Bất kỳ node nào cũng có thể gửi yêu cầu tạo nhóm mới, thêm các node thành viên và đặt tên cho nhóm. Sau đó, mọi tin nhắn gửi đến tên nhóm này sẽ được tự động phát đa điểm đến tất cả thành viên. Ưu điểm của cách làm này là thống nhất cách thức gửi tin nhắn đơn điểm và đa điểm, tuy nhiên sẽ dẫn đến tình trạng tên nhóm và tên dịch vụ quản lý nhóm là hai thực thể khác nhau. Nếu tuân thủ nguyên tắc “giao diện phản ánh bản chất”, hai thành phần này nên tồn tại trên hai node riêng biệt. Nhưng với API Skynet hiện tại, việc giao tiếp giữa chúng gặp nhiều khó khăn.
Bạn đồng nghiệp Niên Ngưu đã thuyết phục tôi rằng phát đa điểm là một hạ tầng quan trọng nên được tích hợp vào tầng底层 như một phần của hệ thống. Dù có phần “bẩn” một chút nhưng sẽ hiệu quả hơn. Theo đó, về mặt giao diện nó sẽ xuất hiện như một dịch vụ độc lập, nhưng thực chất là một phần của hệ thống lõi. Tôi quyết định chấp nhận phương án này để không làm chậm tiến độ phát triển.
Với hạ tầng này, các module như dịch vụ cảnh báo, API quản lý đội nhóm, hay hệ thống chat sẽ trở nên đơn giản hơn nhiều. Trong khi chưa tích hợp chính thức vào khung truyền thông, chúng ta có thể tạm thời dùng hook ở thư viện Lua để bắt các lệnh phát đa điểm, sau đó mỗi node tự động gửi tin nhắn đến các thành viên nhóm một cách mô phỏng.