0
0
Lập trình
TT

Xây dựng Hệ Thống Hợp Tác Thời Gian Thực cho Công Cụ Vẽ Sơ Đồ

Đăng vào 4 ngày trước

• 6 phút đọc

Giới thiệu

Khi bắt đầu xây dựng Modeldraw, một nền tảng vẽ sơ đồ hợp tác, tôi biết rằng việc hỗ trợ hợp tác thời gian thực là điều thiết yếu. Nhiều người dùng cần có khả năng chỉnh sửa cùng một sơ đồ đồng thời mà không gặp phải xung đột, thấy vị trí con trỏ của nhau trong thời gian thực và mọi thứ phải hoạt động liền mạch, bất kể họ đang đăng nhập hay truy cập qua liên kết chia sẻ.

Dù có vẻ đơn giản ban đầu, nhưng nó đã trở thành một trong những thách thức kỹ thuật phức tạp nhất của toàn bộ dự án. Đây là cách tôi giải quyết vấn đề này.

Các yêu cầu

Hệ thống hợp tác thời gian thực cần xử lý:

  • Trộn thay đổi đồng thời — Khi hai người dùng chỉnh sửa cùng một phần tử đồng thời.
  • Theo dõi con trỏ trực tiếp — Hiển thị vị trí làm việc của người khác với các hoạt động mượt mà.
  • Xác thực linh hoạt — Hỗ trợ cả người dùng đã xác thực và người xem ẩn danh với các liên kết chia sẻ.
  • Đồng bộ hóa đáng tin cậy — Đảm bảo trạng thái sơ đồ luôn nhất quán trên tất cả các máy khách.

SignalR vs. WebSockets: Lựa chọn nền tảng phù hợp

Quyết định lớn đầu tiên là chọn giữa WebSockets thô và SignalR. Mặc dù cả hai đều cho phép giao tiếp thời gian thực, nhưng SignalR cung cấp những trừu tượng quan trọng giúp tiết kiệm hàng tuần thời gian phát triển:

Tính linh hoạt trong giao thông

WebSockets chỉ hoạt động khi cả máy chủ và máy khách đều hỗ trợ chúng, và các trung gian mạng như proxy hoặc tường lửa có thể chặn kết nối. SignalR tự động chọn phương thức giao thông tốt nhất có sẵn và tự động điều chỉnh. Ứng dụng của bạn hoạt động đáng tin cậy trên các trình duyệt, thiết bị và điều kiện mạng khác nhau mà không cần logic fallback thủ công.

Trải nghiệm phát triển

Với WebSockets thô, bạn phải quản lý kết nối, định dạng tin nhắn, tuần tự hóa và logic kết nối lại. Mô hình hub của SignalR cho phép máy khách gọi các phương thức của máy chủ và ngược lại, gần như giống như các cuộc gọi phương thức thông thường. Mô hình tư duy đơn giản này giảm thiểu đáng kể độ phức tạp.

Độ bền tích hợp sẵn

Khi kết nối WebSocket bị ngắt, bạn phải phát hiện lỗi và triển khai logic kết nối lại. SignalR xử lý việc kết nối lại tự động với các chiến lược thử lại có thể tùy chỉnh ngay từ đầu.

Tính năng mở rộng

WebSockets yêu cầu các triển khai tùy chỉnh để theo dõi khách hàng và phát sóng tin nhắn. SignalR cung cấp nhóm và phát sóng một cách tự nhiên, giúp việc gửi cập nhật đến tất cả người dùng đang xem một sơ đồ cụ thể trở nên dễ dàng.

Tích hợp ASP.NET Core

SignalR tích hợp liền mạch với các hệ thống xác thực, ủy quyền và tiêm phụ thuộc của ASP.NET Core. Ở phía trước, gói @microsoft/signalr cung cấp API thân thiện với TypeScript.

Quyết định trở nên rõ ràng: SignalR sẽ cung cấp nền tảng mà chúng tôi cần.

Giải quyết vấn đề chỉnh sửa đồng thời

Thách thức khó khăn nhất là trộn các thay đổi đồng thời. Khi Người dùng A và Người dùng B đều sửa đổi cùng một sơ đồ đồng thời, hệ thống cần có khả năng giải quyết xung đột thông minh cả ở cấp độ hình và cấp độ thuộc tính.

Dưới đây là logic trộn tôi đã triển khai:

Thêm thuộc tính

Nếu Người dùng A thêm thuộc tính P1 và lưu của Người dùng B không bao gồm nó, giữ lại sự thêm của A. Các thuộc tính mới từ người dùng đầu tiên sẽ được bảo tồn.

Sửa đổi thuộc tính

Nếu cả hai người dùng đều sửa đổi thuộc tính P2, so sánh giá trị của B với giá trị gốc. Nếu B thực sự không thay đổi, giữ lại sự sửa đổi của A. Điều này ngăn một người dùng vô tình ghi đè lên các thay đổi có chủ ý của người khác.

Xóa thuộc tính

Nếu Người dùng A xóa thuộc tính P3 và Người dùng B cố gắng lưu với nó, sự xóa sẽ thắng. Điều này đảm bảo rằng các thao tác dọn dẹp không bị đảo ngược.

Quy tắc này ngăn ngừa xung đột trong khi tôn trọng ý định của người dùng — điều quan trọng để duy trì niềm tin trong việc chỉnh sửa hợp tác.

Phát sóng thay đổi đến các máy khách kết nối

Khi một sơ đồ được lưu, tất cả người dùng kết nối cần nhận cập nhật ngay lập tức. Tôi đã sử dụng các nhóm SignalR, trong đó mỗi sơ đồ tạo ra một nhóm được xác định bởi ID của nó:

csharp Copy
private async Task DispatchAsync(Element diagramElement, string eventName, object data)
{
    await _hubContext.Clients
        .Group(diagramElement.Id.ToString())
        .SendAsync(eventName, data);
}

Điều này phát sóng đến tất cả mọi người đang xem sơ đồ đó — cả người dùng đã xác thực và người xem ẩn danh sử dụng các liên kết chia sẻ. Sự trừu tượng nhóm làm cho điều này trở nên đáng kể đơn giản.

Áp dụng cập nhật trên giao diện người dùng

Khi giao diện người dùng nhận sự kiện cập nhật, nó phải trộn các thay đổi đến với trạng thái hiện tại mà không làm gián đoạn công việc của người dùng. Quy trình:

  1. Phân tích cấu trúc sơ đồ đến
  2. Xác định các hình nào đã thay đổi
  3. Tái sử dụng các thể hiện hình hiện có khi có thể (giữ nguyên trạng thái UI)
  4. Áp dụng cập nhật thuộc tính theo cùng một quy tắc trộn
  5. Kích hoạt lại việc vẽ lại chỉ cho các phần tử bị ảnh hưởng

Cách tiếp cận cập nhật chọn lọc này giữ cho tương tác mượt mà ngay cả trong các phiên hợp tác tích cực.

Các bài học rút ra

Xây dựng hợp tác thời gian thực đã dạy tôi một số bài học quý giá:

Bắt đầu với các trừu tượng đúng

Việc chọn SignalR thay vì WebSockets thô đã tiết kiệm hàng tuần thời gian phát triển và cung cấp các giải pháp đã được kiểm chứng cho các vấn đề phức tạp như kết nối lại và fallback giao thông.

Giải quyết xung đột yêu cầu quy tắc rõ ràng

Nếu không có logic trộn rõ ràng, các chỉnh sửa đồng thời nhanh chóng trở nên hỗn loạn. Định nghĩa quy tắc của bạn từ sớm và kiểm tra chúng kỹ lưỡng.

Trải nghiệm người dùng quan trọng hơn sự thanh lịch kỹ thuật

Hệ thống cần phải “chỉ hoạt động” cho người dùng, ngay cả khi điều đó có nghĩa là thêm độ phức tạp trong việc triển khai.

Kết luận

Hợp tác thời gian thực trong Modeldraw hiện hỗ trợ các nhóm tạo ra sơ đồ UML, biểu đồ luồng và quy trình làm việc linh hoạt cùng nhau một cách liền mạch. Người dùng có thể thấy con trỏ của nhau, thực hiện các chỉnh sửa đồng thời và tin tưởng rằng các thay đổi của họ sẽ không bị mất — tất cả đều nhờ vào nền tảng mạnh mẽ của SignalR và logic giải quyết xung đột cẩn thận.

Bạn có thể xem nó trong hành động tại modeldraw.com.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào