Realtime không chỉ dành cho ứng dụng chat. Thông báo đơn hàng, tiến độ xử lý file, bảng điều khiển vận hành và trạng thái cộng tác đều tốt hơn khi máy chủ có thể chủ động gửi thay đổi đến trình duyệt. Laravel Reverb cung cấp WebSocket server tích hợp với cơ chế event broadcasting quen thuộc của Laravel.
Bài viết này đi từ luồng dữ liệu, cài đặt và private channel đến những điểm dễ sai khi đưa Reverb lên production. Mục tiêu không chỉ là thấy sự kiện xuất hiện trên màn hình, mà là xây một luồng realtime có thể bảo mật, giám sát và mở rộng.
Khi nào nên dùng realtime?
WebSocket phù hợp khi người dùng cần nhận cập nhật trong vài giây mà không phải tải lại trang hoặc liên tục polling API.
- Thông báo đơn hàng, thanh toán hoặc ticket vừa thay đổi trạng thái.
- Hiển thị tiến độ import, export, xử lý video hoặc báo cáo chạy nền.
- Cập nhật dashboard vận hành, tồn kho hoặc số liệu trực tiếp.
- Presence channel cho biết ai đang trực tuyến trong một không gian cộng tác.
- Chat, bình luận trực tiếp và thông báo trong ứng dụng.
Không nên biến mọi thay đổi thành realtime. Dữ liệu ít quan trọng hoặc chỉ cần làm mới sau vài phút vẫn có thể dùng cache và polling đơn giản hơn.
Hiểu đúng luồng dữ liệu
- Ứng dụng Laravel phát một event triển khai
ShouldBroadcast. - Broadcast job thường được đưa vào queue để request chính không phải chờ.
- Laravel gửi payload đến Reverb bằng application credentials.
- Reverb chuyển message đến các client đang subscribe đúng channel.
- Laravel Echo ở trình duyệt nhận event và cập nhật giao diện.
Reverb là WebSocket server; queue worker vẫn là một mắt xích riêng. Nếu event dùng broadcast queue nhưng worker không chạy, kết nối WebSocket có thể khỏe mà người dùng vẫn không nhận được dữ liệu.
Cài Reverb và broadcasting
php artisan install:broadcasting
npm install
npm run build
Lệnh cài broadcasting tạo cấu hình cần thiết cho Reverb và phía frontend. Sau đó chạy server khi phát triển:
php artisan reverb:start
php artisan queue:work
Có thể thêm --debug để xem message khi chẩn đoán local, nhưng không nên bật log chi tiết liên tục trên production.
Phân biệt địa chỉ server và địa chỉ public
Một lỗi cấu hình phổ biến là dùng lẫn host mà tiến trình Reverb lắng nghe với host trình duyệt truy cập. Trong production, Reverb có thể chạy nội bộ ở cổng 8080, còn người dùng kết nối qua wss://ws.example.com cổng 443.
REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080
REVERB_HOST=ws.example.com
REVERB_PORT=443
REVERB_SCHEME=https
REVERB_SERVER_* điều khiển tiến trình lắng nghe. REVERB_HOST và REVERB_PORT cho Laravel biết địa chỉ public dùng để gửi broadcast. Các biến VITE_REVERB_* tương ứng được build vào frontend; sau khi đổi cần build lại asset.
Tạo một broadcast event gọn và rõ
final class OrderStatusChanged implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(public Order $order) {}
public function broadcastOn(): array
{
return [new PrivateChannel('orders.'.$this->order->id)];
}
public function broadcastWith(): array
{
return [
'id' => $this->order->id,
'status' => $this->order->status,
'updated_at' => $this->order->updated_at?->toIso8601String(),
];
}
}
broadcastWith() giúp kiểm soát payload. Không nên gửi toàn bộ model và relationship nếu client chỉ cần vài trường; payload nhỏ giảm băng thông và hạn chế lộ dữ liệu ngoài ý muốn.
Bảo vệ private channel bằng authorization
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId): bool {
return Order::query()
->whereKey($orderId)
->where('user_id', $user->id)
->exists();
});
Định nghĩa channel nằm trong routes/channels.php. Client có application key không đồng nghĩa được phép vào mọi private channel; callback authorization mới quyết định người dùng hiện tại có quyền subscribe hay không.
Lắng nghe bằng Laravel Echo
Echo.private(`orders.${orderId}`)
.listen('OrderStatusChanged', (event) => {
updateOrderStatus(event.status);
});
Giao diện nên xử lý cả trạng thái mất kết nối, reconnect và dữ liệu đến trễ. Khi reconnect, cách an toàn là gọi lại API để lấy snapshot mới nhất rồi tiếp tục nhận event, thay vì giả định mọi message trong lúc gián đoạn đều được phát lại.
Reverse proxy và TLS trên production
Thông thường Nginx hoặc web server public kết thúc TLS và proxy kết nối đến Reverb ở mạng nội bộ. Proxy phải giữ HTTP/1.1, chuyển các header Upgrade và Connection, đồng thời phục vụ cả đường dẫn WebSocket và API của Reverb.
Hãy giới hạn allowed_origins theo domain thực tế. Dùng wildcard thuận tiện khi thử nghiệm nhưng làm rộng bề mặt truy cập không cần thiết.
Quản lý tiến trình và deploy không gián đoạn
Reverb là tiến trình sống lâu nên phải được Supervisor, systemd hoặc nền tảng triển khai quản lý. Process manager cần tự khởi động lại khi crash và sau khi máy chủ reboot.
php artisan reverb:restart
Lệnh restart đóng kết nối mềm; process manager sau đó chạy lại server bằng code và cấu hình mới. Deployment cũng cần restart queue worker nếu broadcast event được xử lý qua queue.
Giám sát và mở rộng
Tích hợp Laravel Pulse có thể theo dõi số connection và message. Ngoài dashboard, nên cảnh báo theo tỷ lệ lỗi kết nối, reconnect bất thường, độ trễ broadcast, queue wait time, bộ nhớ và số file descriptor đang dùng.
Khi một node không đủ tải, Reverb hỗ trợ mở rộng ngang qua Redis pub/sub:
REVERB_SCALING_ENABLED=true
Các node Reverb phải dùng chung Redis và đứng sau load balancer. Trước khi scale, kiểm tra giới hạn file mở của hệ điều hành, event loop, cấu hình Nginx và process manager; mỗi WebSocket duy trì một kết nối lâu dài nên giới hạn này quan trọng hơn với HTTP request ngắn.
Checklist trước khi go-live
- Private và presence channel có authorization theo đúng đối tượng dữ liệu.
allowed_originschỉ chứa domain cần thiết.- Không broadcast secret, token hoặc toàn bộ model ngoài nhu cầu.
- Queue worker đang chạy và có cảnh báo wait time.
- Reverse proxy hỗ trợ WebSocket upgrade và timeout phù hợp.
- Reverb được process manager giám sát và restart trong deployment.
- Client có chiến lược reconnect và đồng bộ lại snapshot.
- Có dashboard cho connection, message, lỗi và tài nguyên hệ thống.




Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.