Làm Thế Nào Để Đồng Bộ Thời Gian Mạng Chính Xác Hơn?
Vào cuối tuần này, một ý tưởng khác lại nảy ra trong đầu tôi, bắt nguồn từ một câu hỏi quan trọng chưa có lời giải.
Chuyện bắt đầu từ việc chúng tôi muốn mô phỏng môi trường mạng phức tạp trên mạng nội bộ để thử nghiệm. Một đồng nghiệp tại Công ty Quái vật khi gỡ lỗi client vào cuối tuần đã thay đổi cổng mạng máy tính của mình, cố ý thêm độ trễ giả lập để kiểm tra hiệu ứng mạng. Điều kỳ lạ là kết nối client không bị ngắt khi chuyển đổi cổng. Độ trễ vẫn xảy ra theo đúng kỳ vọng.
Chúng tôi cùng phân tích hiện tượng này và nhận thấy rằng độ trễ giả lập này mang tính đơn hướng. Khi server game gửi gói tin về máy tính cá nhân, vì server và máy tính nằm trong cùng một mạng LAN nên gói tin được chuyển trực tiếp mà không qua cổng mạng đã được thay đổi. Kết nối TCP cũng không bị ngắt dù đường đi của gói tin đã thay đổi.
Loại mô phỏng này không mang lại hiệu quả mong muốn. Giải pháp đúng đắn nên là đồng thời thay đổi địa chỉ IP của máy tính hoặc cấp thêm một địa chỉ IP thuộc mạng LAN giả lập, dùng địa chỉ mới này để thiết lập lại kết nối TCP. Hoặc có thể thực hiện NAT trên cổng mạng giả lập. Có nhiều cách khả thi nhưng tôi xin phép không đi sâu vào chi tiết. Chỉ cần nhớ rằng chỉ khi mô phỏng được độ trễ hai chiều (hoặc độ bất ổn mạng) một cách chính xác thì mới thu được kịch bản gần sát thực tế.
Tuy nhiên, sai sót này lại gợi mở cho tôi một suy nghĩ mới: Liệu có xảy ra hậu quả nghiêm trọng nào nếu độ trễ đường lên và đường xuống của kết nối TCP chênh lệch lớn? Phản ứng đầu tiên của tôi là: “Làm sao đồng bộ thời gian mạng chính xác đây?”
Giao thức đồng bộ thời gian truyền thống thường dựa trên giả định: Thời gian gói tin từ máy tính cá nhân đến server gần bằng thời gian gói tin từ server về máy tính cá nhân. Theo đó, tổng thời gian vòng đời của gói tin (round-trip time) chia đôi sẽ cho ta độ trễ một chiều, và từ đó hiệu chỉnh thời gian máy tính theo thời gian của server.
Nhưng khi độ trễ hai chiều chênh lệch lớn, giả định này sụp đổ, dẫn đến sai lệch nghiêm trọng trong hiệu chỉnh thời gian.
Làm sao để đo chính xác độ trễ một chiều từ điểm A đến điểm B? Nếu chỉ tồn tại A và B, có lẽ ta sẽ không bao giờ có được kết quả chính xác. Ta rất khó xác định độ trễ từ A đến B có bằng độ trễ từ B đến A hay không, trừ khi tổng thời gian hai chiều cực ngắn (ít nhất một lần cực nhanh) thì sai số sẽ không vượt quá thời gian vòng đời đó. Trong trường hợp cực đoan, A đến B rất chậm nhưng B đến A lại tức thì - tương tự tình huống tôi đã gặp, khi A đến B qua cổng mạng giả lập độ trễ còn B đến A lại đi đường khác trong LAN, về ngay lập tức.
Tôi cho rằng có thể cải thiện độ chính xác bằng cách bổ sung thêm các đường dẫn gián tiếp. Giả sử ta có thêm các server C, D, E: Khi A gửi gói tin, các server này lập tức chuyển tiếp đến B; ngược lại khi B gửi gói tin, chúng cũng chuyển tiếp ngay về A.
Như vậy sẽ tạo ra nhiều đường dẫn gián tiếp khác nhau giữa A và B. Nếu giả định rằng trên internet, độ trễ hai chiều giữa hai IP thường gần bằng nhau (trừ các trường hợp ngoại lệ), ta có thể gửi gói đồng bộ thời gian qua nhiều đường dẫn khác nhau từ A đến B, ước tính độ trễ một chiều của từng đường dẫn (coi là một nửa độ trễ hai chiều).
Khi A đồng thời gửi gói qua nhiều đường dẫn đến B, B sẽ nhận được các gói tin này theo từng thời điểm khác nhau do độ trễ từng đường dẫn khác nhau. Nếu giả định ban đầu đúng, ta có thể so sánh chéo các gói tin nhận được để loại bỏ những đường dẫn không ổn định, từ đó tính toán gần đúng thời gian một chiều trên đường dẫn trực tiếp giữa A và B.
Đây chỉ là suy nghĩ vu vơ cuối tuần, mong mọi người đừng quá nghiêm túc nhé :)