Signaling Server — là thành phần máy chủ của hạ tầng WebRTC, cho phép trao đổi siêu dữ liệu giữa các peer để thiết lập và kết thúc kết nối. Không giống như lưu lượng phương tiện, tín hiệu có thể được truyền qua bất kỳ giao thức nào — WebSocket, HTTP, XMPP hoặc SIP. Theo MDN Web Docs, 2024, tín hiệu là thành phần bắt buộc của bất kỳ ứng dụng WebRTC nào, vì giao thức không định nghĩa phương pháp cụ thể để trao đổi thông điệp tín hiệu.
Những điểm chính
Signaling Server — là dịch vụ mạng chịu trách nhiệm điều phối quá trình thiết lập kết nối WebRTC giữa hai hoặc nhiều peer. Nó không truyền dữ liệu phương tiện (âm thanh, video, dữ liệu DataChannel), mà chỉ truyền thông tin điều khiển cần thiết để khám phá peer và đàm phán tham số kết nối. Sau khi thiết lập thành công kênh P2P, Signaling Server có thể không còn cần thiết, nhưng trong một số kiến trúc, nó vẫn tồn tại để trao đổi tín hiệu sau đó (ví dụ: kết thúc cuộc gọi, thêm người tham gia).
Kiến trúc tín hiệu bao gồm ba thành phần: Signaling Server, Signal Channel (giao thức vận chuyển giữa máy khách và máy chủ) và API máy khách (thường được tích hợp trong ngăn xếp WebRTC của trình duyệt). Đặc tả WebRTC (W3C, 2024) cố tình không chuẩn hóa giao thức tín hiệu — nhà phát triển có thể chọn bất kỳ phương thức vận chuyển nào phù hợp với ứng dụng của họ. Cách tiếp cận linh hoạt này cho phép sử dụng WebSocket cho ứng dụng web, XMPP cho hệ thống trò chuyện hoặc SIP để tích hợp với hạ tầng viễn thông.
Trước khi thiết lập kết nối WebRTC, các peer phải trao đổi ba loại thông điệp: mô tả phiên (offer và answer), ứng viên ICE và thông tin kết thúc/sửa đổi phiên. Signaling Server định tuyến các thông điệp này giữa các peer bằng cách sử dụng định danh phòng hoặc người dùng để định địa chỉ. Mô hình tiêu chuẩn là tạo một “phòng” nơi hai người tham gia kết nối và máy chủ chuyển tiếp thông điệp từ mỗi người tham gia chỉ đến đối tác của họ.
Signaling Server triển khai giao thức thiết lập kết nối WebRTC điển hình sau. Các peer kết nối đến máy chủ qua WebSocket (hoặc phương thức vận chuyển khác) và đăng ký vào một phòng. Peer A (người khởi tạo) tạo offer (mô tả SDP của luồng phương tiện gửi đi) qua RTCPeerConnection.createOffer(), đặt nó làm mô tả cục bộ và gửi đến Signaling Server. Máy chủ chuyển tiếp offer đến Peer B. Peer B nhận offer, đặt nó làm mô tả từ xa, tạo answer qua createAnswer(), đặt nó làm mô tả cục bộ và gửi lại qua máy chủ. Quá trình này được gọi là SDP Offer/Answer.
Song song với trao đổi SDP, mỗi peer thu thập các ứng viên ICE (host, srflx, relay) và gửi chúng qua Signaling Server đến peer kia. Peer từ xa thêm các ứng viên nhận được qua RTCPeerConnection.addIceCandidate(). Quá trình ICE kiểm tra tất cả các tổ hợp ứng viên để tìm đường dẫn hoạt động. Khi tìm thấy đường dẫn hoạt động (thường trong vòng 1–5 giây), lưu lượng phương tiện bắt đầu chảy trực tiếp giữa các peer và Signaling Server không còn tham gia truyền dữ liệu nữa — vai trò của nó kết thúc cho đến sự kiện điều khiển tiếp theo (kết thúc cuộc gọi, thay đổi chất lượng luồng).
Để định địa chỉ thông điệp, Signaling Server sử dụng cơ chế phòng hoặc kênh. Mỗi phiên WebRTC mới tạo một phòng duy nhất với định danh (thường là UUID). Người khởi tạo tạo phòng và chờ peer thứ hai kết nối. Peer thứ hai tham gia phòng bằng ID nhận được qua kênh bên ngoài (ví dụ: liên kết mời). Máy chủ duy trì bản đồ các phòng, nơi mỗi ID tương ứng với danh sách máy khách đã kết nối. Khi số lượng người tham gia đạt hai, máy chủ bắt đầu chuyển tiếp thông điệp tín hiệu giữa họ.
Signaling Server có thể sử dụng các giao thức vận chuyển khác nhau, mỗi giao thức có ưu điểm và nhược điểm riêng. Việc chọn giao thức phụ thuộc vào loại ứng dụng, hạn chế hạ tầng và yêu cầu tương thích. Dưới đây là các giao thức phổ biến nhất và đặc điểm của chúng.
| Giao thức | Vận chuyển | Ưu điểm | Nhược điểm |
|---|---|---|---|
| WebSocket | TCP | Song công toàn phần, độ trễ thấp, tích hợp trong trình duyệt | Phức tạp mở rộng, chặn proxy |
| HTTP/SSE | TCP | Tương thích với mọi hạ tầng, dễ triển khai | Chỉ một chiều (máy chủ-máy khách), cần thăm dò |
| XMPP | TCP | Tiêu chuẩn hóa, hỗ trợ xác thực, mở rộng được | Quá mức cho kịch bản đơn giản, chi phí XML |
| SIP | UDP/TCP | Tích hợp với hạ tầng VoIP và điện thoại | Phức tạp, không phải bản địa cho trình duyệt |
| MQTT | TCP | Nhẹ, hoạt động trong môi trường IoT, publish/subscribe | Cần broker, độ trễ bổ sung |
WebSocket là giao thức phổ biến nhất cho Signaling Server trong ứng dụng web. Nó cung cấp giao tiếp song công toàn phần, quan trọng cho việc trao đổi bất đồng bộ các ứng viên SDP và ICE, và được hỗ trợ bản địa bởi tất cả trình duyệt hiện đại qua WebSocket API. Triển khai máy chủ WebSocket có sẵn trên tất cả nền tảng phổ biến (Node.js, Python, Java, Go). Cho ứng dụng với hàng triệu người dùng, các giải pháp WebSocket có thể mở rộng dựa trên Redis Pub/Sub hoặc Kafka được sử dụng để đồng bộ giữa các phiên bản Signaling Server.
Hãy xem xét một triển khai đơn giản của Signaling Server trong Node.js sử dụng thư viện ws (WebSocket) và máy chủ HTTP tích hợp. Máy chủ hỗ trợ đăng ký người dùng, tạo phòng và chuyển tiếp thông điệp giữa người tham gia.
const WebSocket = require("ws");
const server = new WebSocket.Server({ port: 8080 });
const rooms = new Map();
server.on("connection", (ws) => {
ws.roomId = null;
ws.on("message", (data) => {
const msg = JSON.parse(data);
switch (msg.type) {
case "join":
handleJoin(ws, msg.roomId);
break;
case "offer":
case "answer":
case "ice-candidate":
relayToPeer(ws, msg);
break;
case "leave":
handleLeave(ws);
break;
}
});
ws.on("close", () => handleLeave(ws));
});
function handleJoin(ws, roomId) {
if (!rooms.has(roomId)) {
rooms.set(roomId, []);
}
const room = rooms.get(roomId);
room.push(ws);
ws.roomId = roomId;
if (room.length === 2) {
room[0].send(JSON.stringify({ type: "peer-joined" }));
room[1].send(JSON.stringify({ type: "peer-joined" }));
}
}
function relayToPeer(sender, msg) {
const room = rooms.get(sender.roomId);
if (!room) return;
room.forEach(peer => {
if (peer !== sender && peer.readyState === WebSocket.OPEN) {
peer.send(JSON.stringify(msg));
}
});
}
function handleLeave(ws) {
if (!ws.roomId) return;
const room = rooms.get(ws.roomId);
if (!room) return;
const idx = room.indexOf(ws);
if (idx !== -1) room.splice(idx, 1);
if (room.length === 0) rooms.delete(ws.roomId);
}
Signaling Server này triển khai chức năng cơ bản: kết nối đến phòng, chuyển tiếp thông điệp WebRTC (offer, answer, ice-candidate) giữa hai peer và quản lý ngắt kết nối. Máy chủ sử dụng Map để lưu trữ các phòng với máy khách WebSocket đã kết nối. Hàm relayToPeer gửi thông điệp đến tất cả người tham gia trong phòng trừ người gửi. Cho sản xuất, bạn cần thêm xác thực loại thông điệp, xử lý lỗi phân tích JSON và cơ chế heartbeat để phát hiện kết nối bị đứt.
Phía máy khách, Signaling Server được tích hợp qua WebSocket API của trình duyệt. Máy khách thiết lập kết nối với máy chủ, gửi yêu cầu tham gia phòng, sau đó xử lý các thông điệp WebRTC đến bằng cách chuyển chúng đến RTCPeerConnection qua setRemoteDescription() và addIceCandidate(). Mã máy khách cũng gửi các ứng viên SDP và ICE của riêng nó đến máy chủ, nhận được từ RTCPeerConnection qua sự kiện onicecandidate và sau khi tạo offer/answer.
Signaling Server truyền hai loại siêu dữ liệu chính: SDP (Session Description Protocol) và ứng viên ICE. SDP mô tả tham số luồng phương tiện — codec, tần số lấy mẫu, số kênh, hướng truyền (sendrecv, sendonly, recvonly, inactive). Ứng viên ICE chứa địa chỉ mạng (cục bộ, lấy từ STUN, relay từ TURN) qua đó peer có thể được truy cập để kết nối.
SDP được trình bày dưới dạng văn bản chứa các phần phiên và phương tiện. Phần phiên mô tả tham số chung (ID phiên, phiên bản, tên), trong khi phần phương tiện mô tả từng luồng phương tiện (âm thanh, video, DataChannel) với codec, cổng và giao thức của nó. Ứng viên ICE chứa foundation (định danh nhóm), ưu tiên, địa chỉ IP, cổng, loại (host, srflx, relay) và giao thức (UDP, TCP). Mỗi ứng viên cũng bao gồm thuộc tính ufrag (phần tên người dùng) liên kết nó với một quá trình ICE cụ thể.
Trickle ICE tăng tốc đáng kể việc thiết lập kết nối WebRTC. Thay vì chờ thu thập đầy đủ tất cả ứng viên ICE (có thể mất 2–10 giây trong mạng phức tạp), mỗi ứng viên được gửi đến Signaling Server ngay sau khi khám phá. Peer từ xa nhận ứng viên và ngay lập tức bắt đầu kiểm tra kết nối qua framework ICE. Điều này giảm thời gian thiết lập kết nối xuống còn 500–1500 ms trong hầu hết các trường hợp.
Câu hỏi thường gặp
Signaling Server — là “người điều phối” trước cuộc gọi. Nó giúp hai thiết bị tìm thấy nhau và thỏa thuận cách chúng sẽ giao tiếp. Sau khi các thiết bị đã “gặp nhau” và thỏa thuận, máy chủ không còn cần thiết nữa — chúng giao tiếp trực tiếp.
WebRTC không định nghĩa giao thức tín hiệu để nhà phát triển có thể chọn phương thức vận chuyển phù hợp nhất. Trình duyệt không có cơ chế tích hợp để khám phá người dùng khác — nhiệm vụ này do Signaling Server thực hiện. Nó hoạt động như “người đưa thư”, chuyển lời mời và cài đặt kết nối giữa những người tham gia cuộc gọi.
WebSocket — là lựa chọn tối ưu cho hầu hết ứng dụng web: song công toàn phần, trình duyệt hỗ trợ bản địa và dễ triển khai. Để tích hợp với hạ tầng VoIP hiện có, chọn SIP. Cho ứng dụng trò chuyện giàu tính năng, sử dụng XMPP. Cho kịch bản IoT, sử dụng MQTT.
Để mở rộng Signaling Server, sử dụng mở rộng ngang với đồng bộ qua Redis Pub/Sub hoặc Kafka. Mỗi phiên bản máy chủ xử lý phần kết nối WebSocket của riêng mình và một bus dữ liệu chung được sử dụng để định tuyến thông điệp giữa các máy chủ. Cách tiếp cận này cho phép xử lý hàng triệu phiên tín hiệu đồng thời.
Signaling Server chỉ quan trọng trong giai đoạn thiết lập kết nối. Nếu máy chủ tạm thời không khả dụng, các cuộc gọi WebRTC đang hoạt động vẫn tiếp tục — lưu lượng phương tiện chảy trực tiếp giữa các peer. Vấn đề chỉ phát sinh khi cố gắng thiết lập kết nối mới. Để đảm bảo độ tin cậy, sử dụng cụm máy chủ và kênh tín hiệu dự phòng.
Tóm tắt
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm