การส่งสัญญาณชีพ

注意:แอปพลิเคชันที่ใช้การเชื่อมต่อระยะยาวจำเป็นต้องมีการส่งสัญญาณชีพ มิฉะนั้นการเชื่อมต่ออาจถูก断开โดยโหนด路由เนื่องจากไม่มีการสื่อสารเป็นเวลานาน

การส่งสัญญาณชีพมีจุดประสงค์หลักสองประการ:

  1. คลายเอนต์จะส่งข้อมูลไปยังเซิร์ฟเวอร์เป็นระยะ เวลา เพื่อป้องกันไม่ให้การเชื่อมต่อถูกปิดโดยไฟร์วอลล์ของโหนดบางตัวเนื่องจากไม่มีการสื่อสารเป็นเวลานาน

  2. เซิร์ฟเวอร์สามารถใช้การส่งสัญญาณชีพเพื่อตรวจสอบว่า คลายเอนต์ออนไลน์หรือไม่ หากคลายเอนต์ไม่ส่งข้อมูลใด ๆ ภายในเวลาที่กำหนด จะถือว่าคลายเอนต์ออฟไลน์ ดังนั้นจึงสามารถตรวจจับเหตุการณ์ที่คลายเอนต์ออฟไลน์ได้จากสถานการณ์ที่รุนแรง (ไฟฟ้าดับ, ขาดการเชื่อมต่อเครือข่าย ฯลฯ)

ระยะเวลาการส่งสัญญาณชีพที่แนะนำ:

แนะนำให้คลายเอนต์ส่งสัญญาณชีพทุก ๆ 60 วินาที หรือน้อยกว่า เช่น 55 วินาที

รูปแบบข้อมูลของการส่งสัญญาณชีพไม่มีความจำเป็นต้องเป็นไปตามรูปแบบเฉพาะ เซิร์ฟเวอร์สามารถรู้จำได้เพียงพอ

ตัวอย่างการส่งสัญญาณชีพ

<?php
use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

// ระยะเวลาการส่งสัญญาณชีพ 55 วินาที
define('HEARTBEAT_TIME', 55);

$worker = new Worker('text://0.0.0.0:1234');

$worker->onMessage = function(TcpConnection $connection, $msg) {
    // ตั้งค่าคุณสมบัติ lastMessageTime ชั่วคราวสำหรับการเชื่อมต่อ เพื่อบันทึกเวลาที่รับข้อความล่าสุด
    $connection->lastMessageTime = time();
    // โลจิกทางธุรกิจอื่น ๆ...
};

// หลังจากเริ่มต้นกระบวนการ ให้ตั้งค่าตัวจับเวลาให้ทำงานทุก ๆ 10 วินาที
$worker->onWorkerStart = function($worker) {
    Timer::add(10, function() use($worker){
        $time_now = time();
        foreach($worker->connections as $connection) {
            // อาจเป็นไปได้ว่าการเชื่อมต่อนั้นยังไม่ได้รับข้อความ ดังนั้น lastMessageTime จึงตั้งค่าให้เป็นเวลาปัจจุบัน
            if (empty($connection->lastMessageTime)) {
                $connection->lastMessageTime = $time_now;
                continue;
            }
            // หากระยะเวลาที่ผ่านไปตั้งแต่การสื่อสารครั้งล่าสุดมากกว่าระยะเวลาการส่งสัญญาณชีพ จะถือว่าคลายเอนต์ออฟไลน์และปิดการเชื่อมต่อ
            if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
                $connection->close();
            }
        }
    });
};

Worker::runAll();

การตั้งค่านี้หมายความว่า หากคลายเอนต์ไม่ได้ส่งข้อมูลใด ๆ ไปยังเซิร์ฟเวอร์ภายใน 55 วินาที เซิร์ฟเวอร์จะถือว่าคลายเอนต์ออฟไลน์ และจะปิดการเชื่อมต่อพร้อมกับกระตุ้น onClose

การเชื่อมต่อใหม่หลังจากถูกตัด (สำคัญ)

ไม่ว่าคลายเอนต์จะส่งสัญญาณชีพหรือเซิร์ฟเวอร์จะส่งสัญญาณชีพ การเชื่อมต่ออาจถูกตัดได้ เช่น เมื่อเบราว์เซอร์ถูกย่อขนาดและ JS ถูกระงับ เบราว์เซอร์เปลี่ยนไปยังแท็บอื่นและ JS ถูกระงับ คอมพิวเตอร์เข้าสู่โหมดพัก และอื่น ๆ อุปกรณ์เคลื่อนที่ที่เปลี่ยนเครือข่าย สัญญาณอ่อนลง โทรศัพท์ดับหน้าจอ โทรศัพท์เข้าสู่โหมดทำงานเบื้องหลัง ปัญหาที่อาจเกิดขึ้นจาก路由การ断开 หรือธุรกิจ断开การเชื่อมต่ออย่างสมัครใจ เป็นต้น โดยเฉพาะในสภาพแวดล้อมเครือข่ายภายนอกที่ซับซ้อน โหนด路由จำนวนมากจะทำความสะอาดการเชื่อมต่อที่ไม่มีการใช้งานภายใน 1 นาที นี่คือเหตุผลที่แนะนำให้มีระยะเวลาการส่งสัญญาณชีพที่น้อยกว่า 1 นาที

การเชื่อมต่อในสภาพแวดล้อมเครือข่ายภายนอกมีแนวโน้มที่จะถูก断开 ดังนั้นการเชื่อมต่อใหม่หลังจาก断开จึงเป็นคุณลักษณะที่แอปพลิเคชันการเชื่อมต่อระยะยาวจะต้องมี (การเชื่อมต่อใหม่หลังจาก断开สามารถทำได้เฉพาะโดยคลายเอนต์ โดยเซิร์ฟเวอร์ไม่สามารถทำได้) ตัวอย่างเช่น การใช้ WebSocket ในเบราว์เซอร์จำเป็นต้องฟังเหตุการณ์ onclose และเมื่อเกิด onclose ให้สร้างการเชื่อมต่อใหม่ (เพื่อหลีกเลี่ยงการสร้างการเชื่อมต่อที่ล้มเหลว) ในกรณีที่เข้มงวดขึ้น เซิร์ฟเวอร์ควรส่งสัญญาณชีพอย่างสม่ำเสมอ และคลายเอนต์ควรตรวจสอบว่าข้อมูลสัญญาณชีพของเซิร์ฟเวอร์หมดอายุหรือไม่ หากไม่ได้รับข้อมูลสัญญาณชีพจากเซิร์ฟเวอร์ภายในเวลาที่กำหนด ควรถือว่าการเชื่อมต่อถูก断开 และจำเป็นต้องปิดการเชื่อมต่อและสร้างการเชื่อมต่อใหม่อีกครั้ง