
Làm việc dữ liệu Real-time với SignalR
June 21, 2025Tiếp tục bài viết trước về mình viết riêng chủ đề cách làm việc với SignalR, cùng mình nhắc lại một số kiến thức nhé!
SignalR là gì?
SignalR trong ASP.NET Core là một thư viện mã nguồn mở giúp đơn giản hóa việc tích hợp tính năng real-time web (giao tiếp thời gian thực) vào ứng dụng. Với SignalR, bạn có thể cho phép server chủ động đẩy dữ liệu đến client ngay khi có thay đổi, mà không cần client phải gửi yêu cầu liên tục để kiểm tra.
Cơ chế hoạt động và các loại kết nối
SignalR hỗ trợ nhiều hình thức truyền dữ liệu thời gian thực, sắp xếp theo thứ tự fallback khi môi trường không hỗ trợ kỹ thuật tối ưu nhất:
- WebSockets: giao thức full-duplex lý tưởng nhất cho real-time, cho phép server và client giao tiếp hai chiều qua một kết nối TCP duy nhất. WebSocket là một giao thức độc lập hoạt động trên nền TCP, cho phép giao tiếp hai chiều liên tục (full-duplex) giữa client và server. Một khi kết nối WebSocket được thiết lập thành công thông qua quá trình bắt tay (handshake), dữ liệu có thể được truyền đi theo cả hai chiều bất kỳ lúc nào, mà không cần tái thiết lập kết nối như HTTP. Ưu điểm lớn của WebSocket là dữ liệu truyền đi cực kỳ nhẹ vì không mang theo header HTTP, giúp giảm độ trễ và tăng tốc độ phản hồi. Giao thức này hỗ trợ truyền cả dạng văn bản (string) lẫn nhị phân (binary), phù hợp với các ứng dụng yêu cầu thời gian thực cao như hệ thống chat, game trực tuyến, bảng điều khiển live dashboard, hoặc các nền tảng giao dịch tài chính với dữ liệu stream.
- Server-Sent Events (SSE): kênh giao tiếp một chiều, từ server đến client, hoạt động qua kết nối HTTP. SSE là một kỹ thuật giao tiếp một chiều, nơi client mở một kết nối HTTP duy nhất và giữ kết nối này mở trong thời gian dài. Khác với Polling hay Long Polling, ở SSE, server chủ động đẩy dữ liệu về phía client mỗi khi có sự kiện mới xảy ra, mà không cần client phải gửi yêu cầu liên tục. Tuy nhiên, SSE chỉ cho phép truyền dữ liệu từ server về client, không hỗ trợ chiều ngược lại trong cùng một kết nối. SSE rất phù hợp với các ứng dụng thời gian thực đơn giản như hệ thống thông báo (notifications), truyền dữ liệu dạng luồng (streaming), hoặc cập nhật bảng giá. Tuy nhiên, do tính chất một chiều, SSE không đáp ứng được các yêu cầu giao tiếp hai chiều như ứng dụng chat hoặc trò chơi nhiều người chơi (multiplayer game).
- Long Polling: server giữ kết nối mở cho đến khi có dữ liệu mới hoặc timeout, sau đó client gửi yêu cầu mới ngay lập tức. Polling là một kỹ thuật đơn giản trong các ứng dụng web, nơi client sẽ định kỳ gửi HTTP request lên server (ví dụ mỗi giây một lần) để kiểm tra xem có dữ liệu mới hay không. Nếu có dữ liệu, server sẽ phản hồi lại; nếu không, server vẫn bắt buộc phải trả về một response, kể cả là rỗng. Cách tiếp cận này gây lãng phí tài nguyên đáng kể, đặc biệt là khi không có dữ liệu mới, vì server vẫn phải xử lý hàng loạt request không cần thiết, dẫn đến việc HTTP traffic bị quá tải và ảnh hưởng đến hiệu suất tổng thể của hệ thống. Để cải thiện vấn đề đó, HTTP Long Polling được ra đời như một biến thể tối ưu hơn. Với Long Polling, client vẫn gửi request như bình thường, nhưng nếu server chưa có dữ liệu để phản hồi, thay vì trả về ngay, server sẽ giữ kết nối mở và chỉ trả về response khi có dữ liệu mới hoặc khi timeout xảy ra. Sau khi client nhận được dữ liệu, nó lập tức gửi một request mới để tiếp tục duy trì kết nối. Mặc dù hiệu quả hơn so với polling truyền thống, Long Polling vẫn mang nhược điểm là phải thiết lập lại kết nối sau mỗi lần nhận dữ liệu, vì bản chất của nó vẫn dựa trên HTTP và không hỗ trợ giao tiếp hai chiều thực sự (full-duplex).
Tóm lại, mỗi kỹ thuật đều có điểm mạnh và giới hạn riêng. Trong khi Polling và Long Polling phù hợp với hệ thống đơn giản, SSE thích hợp cho luồng dữ liệu một chiều, thì WebSocket là giải pháp toàn diện cho các ứng dụng real-time phức tạp. SignalR trong ASP.NET Core chính là một thư viện mạnh mẽ giúp tự động hóa việc lựa chọn kỹ thuật tối ưu này, cho phép bạn xây dựng ứng dụng thời gian thực mà không cần lo lắng về các tầng giao thức bên dưới.

Hubs trong SignalR
SignalR sử dụng Hub để giao tiếp giữa client và server. Hub là một pipeline cấp cao, cho phép client gọi phương thức từ server và ngược lại. SignalR tự động xử lý việc truyền tải qua biên máy chủ (machine boundary), giúp việc gọi phương thức trở nên đơn giản như gọi hàm trong nội bộ.
SignalR hỗ trợ hai loại giao thức Hub:
- JSON-based protocol – dạng văn bản, dễ debug và phổ biến.
- MessagePack – giao thức dạng nhị phân, giúp giảm kích thước message.
Kiến trúc triển khai SignalR
Khi sử dụng SignalR, mỗi kết nối phải được gắn với một tiến trình cụ thể của server. Điều này gây khó khăn khi bạn triển khai ứng dụng theo kiến trúc server farm. Trong mô hình này, mỗi server chỉ biết đến các kết nối của chính nó.
Giải pháp:
- Sticky Session (hay còn gọi là session affinity): đảm bảo tất cả request của một kết nối đều đến cùng một server.
- Nếu bạn chỉ sử dụng WebSockets và bật cấu hình
SkipNegotiation
thì có thể tránh được Sticky Session. - Ngoài ra, có thể dùng Redis Backplane để chia sẻ kết nối giữa các node trong cluster.
Tham khảo: https://docs.microsoft.com/en-us/aspnet/core/signalr/redis-backplane
Lưu ý khi triển khai
- Nên tách SignalR ra khỏi ứng dụng web chính nếu có thể, để tránh tranh chấp tài nguyên giữa các ứng dụng.
- Tránh dùng SignalR trên cùng server xử lý các API nặng nếu không kiểm soát được memory usage.
Cài đặt và cấu hình
Thêm SignalR vào DI container:
services.AddSignalR()
.AddStackExchangeRedis("<Redis_Connection_String>");
Client JS sử dụng thư viện:
@microsoft/signalr@latest
@microsoft/signalr-protocol-msgpack
Mẫu mã JS đơn giản:
var hubUrl = "<http://localhost:5007/signalr>";
var connection = new signalR.HubConnectionBuilder().withUrl(hubUrl).build();
connection.on("ReceiveMessage", function (user, message) {
// xử lý message
});
connection.start().then(function () {
connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));
}).catch(err => console.error(err.toString()));
Tích hợp xác thực (authentication) trong SignalR:
Azure SignalR Service
Azure SignalR Service là một dịch vụ được quản lý, hoạt động như một proxy và backplane cho các ứng dụng sử dụng SignalR. Khi client kết nối, nó sẽ được chuyển hướng tới Azure SignalR, giúp giảm tải cho server và dễ dàng mở rộng.
Khái niệm:
- Instance: Môi trường sử dụng SignalR.
- Unit: Một “đơn vị” xử lý kết nối và message.
Ví dụ:
- FREE plan chỉ có 1 unit với 20 kết nối đồng thời.
- STANDARD plan có thể dùng đến 100 units, mỗi unit xử lý được 1.000 kết nối đồng thời.
Tham khảo pricing: https://azure.microsoft.com/en-us/pricing/details/signalr-service/
Tài liệu & Source code
- GitHub source: https://github.com/dotnet/AspNetCore/tree/main/src/SignalR
- Hướng dẫn chính thức: https://docs.microsoft.com/en-us/aspnet/core/signalr/introduction?view=aspnetcore-5.0
SignalR là một công cụ mạnh mẽ để xây dựng các ứng dụng tương tác thời gian thực. Dù bạn đang xây dựng chat app, live dashboard, hay notification system, việc hiểu rõ cách hoạt động của SignalR, cách cấu hình và mở rộng đúng cách là yếu tố then chốt để xây dựng hệ thống hiệu quả và dễ bảo trì.