Nhịp Tim
Chú ý: Ứng dụng kết nối dài phải thêm nhịp tim, nếu không, kết nối có thể bị các nút định tuyến ngắt mạnh mẽ do không có liên lạc trong thời gian dài.
Chức năng của nhịp tim chủ yếu có hai điểm:
-
Khách hàng định kỳ gửi dữ liệu đến máy chủ để ngăn chặn việc kết nối bị đóng do không có liên lạc trong thời gian dài bởi tường lửa của một số nút mạng.
-
Máy chủ có thể thông qua nhịp tim để xác định xem khách hàng có trực tuyến hay không, nếu khách hàng không gửi bất kỳ dữ liệu nào trong thời gian quy định, thì coi như khách hàng đã ngoại tuyến. Như vậy, có thể phát hiện sự kiện khách hàng bị ngoại tuyến do các tình huống cực đoan (mất điện, mất mạng, v.v.).
Khoảng thời gian nhịp tim đề xuất:
Đề xuất khách hàng gửi nhịp tim với khoảng thời gian nhỏ hơn 60 giây, ví dụ 55 giây.
Định dạng dữ liệu nhịp tim không có yêu cầu, máy chủ chỉ cần nhận diện được.
Ví dụ Nhịp Tim
<?php
use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// Khoảng thời gian nhịp tim 55 giây
define('HEARTBEAT_TIME', 55);
$worker = new Worker('text://0.0.0.0:1234');
$worker->onMessage = function(TcpConnection $connection, $msg) {
// Tạm thời thiết lập thuộc tính lastMessageTime cho connection, để ghi lại thời gian nhận được thông điệp cuối cùng
$connection->lastMessageTime = time();
// Các logic kinh doanh khác...
};
// Sau khi tiến trình khởi động, thiết lập một bộ đếm sẽ chạy mỗi 10 giây
$worker->onWorkerStart = function($worker) {
Timer::add(10, function()use($worker){
$time_now = time();
foreach($worker->connections as $connection) {
// Có thể connection chưa nhận được thông điệp nào, nên lastMessageTime sẽ được thiết lập bằng thời gian hiện tại
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// Nếu khoảng thời gian giữa lần giao tiếp trước đó lớn hơn khoảng thời gian nhịp tim, thì coi như khách hàng đã ngoại tuyến, ngắt kết nối
if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
$connection->close();
}
}
});
};
Worker::runAll();
Cấu hình trên cho biết nếu khách hàng không gửi bất kỳ dữ liệu nào đến máy chủ sau 55 giây, thì máy chủ sẽ coi như khách hàng đã ngoại tuyến, ngắt kết nối và kích hoạt onClose.
Tái Kết Nối (Quan Trọng)
Dù là khách hàng gửi nhịp tim hay máy chủ gửi nhịp tim, kết nối vẫn có thể bị ngắt. Ví dụ, Javascript bị tạm dừng khi trình duyệt bị thu nhỏ, Javascript bị tạm dừng khi chuyển sang tab khác, máy tính vào chế độ ngủ, thiết bị di động chuyển mạng, tín hiệu yếu, màn hình điện thoại tắt, ứng dụng điện thoại chuyển về nền, lỗi định tuyến, ngắt kết nối chủ động trong kinh doanh, v.v. Đặc biệt là trong môi trường Internet phức tạp, nhiều nút định tuyến sẽ làm sạch kết nối không hoạt động trong vòng 1 phút, đó cũng là lý do mà khoảng thời gian nhịp tim được đề xuất dưới 1 phút.
Kết nối dễ dàng bị ngắt trong môi trường Internet, vì vậy tái kết nối là chức năng cần thiết cho ứng dụng kết nối dài (tái kết nối chỉ có thể được thực hiện bởi khách hàng, máy chủ không thể thực hiện). Ví dụ, WebSocket trong trình duyệt cần lắng nghe sự kiện onclose, khi xảy ra onclose thì thiết lập một kết nối mới (để tránh cần phải cố gắng kết nối lại). Cũng cần nghiêm ngặt hơn, máy chủ cũng nên thường xuyên gửi dữ liệu nhịp tim, và khách hàng cần theo dõi dữ liệu nhịp tim của máy chủ xem có quá thời gian quy định hay không, nếu không nhận được dữ liệu nhịp tim của máy chủ trong thời gian quy định thì cần coi như kết nối đã bị ngắt, cần thực hiện close để ngắt kết nối và thiết lập một kết nối mới.