หลักการรีสตาร์ทแบบราบรื่น

อะไรคือการรีสตาร์ทแบบราบรื่น?

การรีสตาร์ทแบบราบรื่นแตกต่างจากการรีสตาร์ททั่วไป โดยการรีสตาร์ทแบบราบรื่นสามารถทำได้โดยไม่กระทบต่อผู้ใช้ เพื่อที่จะโหลดโปรแกรม PHP ใหม่ทำการอัปเดตโค้ดธุรกิจ

การรีสตาร์ทแบบราบรื่นมักจะถูกใช้ในกระบวนการอัปเดตธุรกิจหรือการเผยแพร่เวอร์ชัน ซึ่งสามารถหลีกเลี่ยงผลกระทบที่เกิดจากการรีสตาร์ทบริการเนื่องจากการเผยแพร่โค้ดที่ทำให้บริการไม่สามารถใช้ได้ชั่วคราว

หมายเหตุ
ระบบ Windows ไม่สนับสนุนการโหลดใหม่ (reload)

หมายเหตุ
สำหรับธุรกิจเช่น long connection (เช่น websocket) การรีสตาร์ทแบบราบรื่นจะทำให้การเชื่อมต่อถูกตัดขาด ทางแก้ไขคือการใช้สถาปัตยกรรมที่คล้ายกับ gatewayWorker โดยมีการประมวลผลกลุ่มหนึ่งที่รับผิดชอบการเก็บรักษาการเชื่อมต่อและตั้งค่าคุณสมบัติ reloadable ของกลุ่มนี้เป็น false ในขณะที่โลจิกธุรกิจเริ่มทำงานด้วย worker processes นอกจากนี้ gateway และ worker processes จะสื่อสารกันผ่าน tcp หากธุรกิจต้องการเปลี่ยนแปลง เพียงแค่รีสตาร์ท worker processes เท่านั้น

ข้อจำกัด

หมายเหตุ: เฉพาะไฟล์ที่ถูกโหลดใน callback on{...} เท่านั้นที่จะอัปเดตอัตโนมัติหลังจากการรีสตาร์ทแบบราบรื่น ไฟล์ที่ถูกโหลดตรงๆ ในสคริปต์เริ่มต้นหรือโค้ดที่เขียนตายแล้ว จะไม่อัปเดตอัตโนมัติหากทำการโหลดใหม่

โค้ดต่อไปนี้จะไม่อัปเดตหลังจาก reload

$worker = new Worker('http://0.0.0.0:1234');
$worker->onMessage = function($connection, $request) {
    $connection->send('hi'); // โค้ดที่เขียนตายแล้วไม่สนับสนุนการอัปเดตแบบร้อน
};
$worker = new Worker('http://0.0.0.0:1234');
require_once __DIR__ . '/your/path/MessageHandler.php'; // ไฟล์ที่โหลดตรงจากสคริปต์เริ่มต้นไม่สนับสนุนการอัปเดตแบบร้อน
$messageHandler = new MessageHandler();
$worker->onMessage = [$messageHandler, 'onMessage']; // สมมุติว่าในคลาส MessageHandler มีเมธอด onMessage

โค้ดต่อไปนี้จะอัปเดตอัตโนมัติหลังจาก reload

$worker = new Worker('http://0.0.0.0:1234');
$worker->onWorkerStart = function($worker) { // onWorkerStart คือ callback ที่ถูกกระตุ้นหลังจากกระบวนการเริ่มต้น
    require_once __DIR__ . '/your/path/MessageHandler.php'; // ไฟล์ที่โหลดหลังจากกระบวนการเริ่มต้นสนับสนุนการอัปเดตแบบร้อน
    $messageHandler = new MessageHandler();
    $worker->onMessage = [$messageHandler, 'onMessage'];
};

หลังจากที่มีการเปลี่ยนแปลงใน MessageHandler.php ให้ทำการ php start.php reload เพื่อให้ MessageHandler.php ถูกโหลดใหม่ในหน่วยความจำเพื่อให้บรรลุการอัปเดตโลจิกธุรกิจ

คำแนะนำ
โค้ดข้างต้นเพื่อ方便การสาธิตใช้คำสั่ง require_once หากโปรเจ็กต์ของคุณสนับสนุนการโหลดอัตโนมัติ PSR-4 แล้ว ไม่มีความจำเป็นต้องเรียกใช้คำสั่ง require_once

หลักการรีสตาร์ทแบบราบรื่น

Workerman แบ่งออกเป็นกระบวนการหลักและกระบวนการย่อย กระบวนการหลักจะรับผิดชอบในการตรวจสอบการทำงานของกระบวนการย่อย และกระบวนการย่อยจะรับผิดชอบในการรับการเชื่อมต่อจากลูกค้าและข้อมูลคำขอที่ส่งมา การทำงานที่เกี่ยวข้องและส่งคืนข้อมูลให้กับลูกค้า เมื่อมีการอัปเดตโค้ดธุรกิจ จริงๆ แล้วเราต้องอัปเดตกระบวนการย่อยเพื่อบรรลุวัตถุประสงค์ในการอัปเดตโค้ด

เมื่อกระบวนการหลักของ Workerman ได้รับสัญญาณการรีสตาร์ทแบบราบรื่น กระบวนการหลักจะส่งสัญญาณให้กระบวนการย่อยหนึ่งทำการออกอย่างปลอดภัย (ให้กระบวนการที่เกี่ยวข้องจัดการคำขอปัจจุบันจนเสร็จสิ้นก่อนที่จะออก) หลังจากที่กระบวนการนี้ออก กระบวนการหลักจะสร้างกระบวนการย่อยใหม่ (กระบวนการนี้โหลดโค้ด PHP ใหม่) จากนั้นกระบวนการหลักจะส่งคำสั่งหยุดไปยังอีกกระบวนการเก่า ทำให้กระบวนการถูกรีสตาร์ททีละหนึ่งและต่อเนื่องจนกว่ากระบวนการเก่าทั้งหมดจะถูกแทนที่

เราจะเห็นว่าการรีสตาร์ทแบบราบรื่นจริงๆ แล้วทำให้กระบวนการธุรกิจเก่าถูกละทิ้งทีละตัว และสร้างกระบวนการใหม่ทีละตัว ด้วยเหตุนี้ ในการรีสตาร์ทแบบราบรื่นจำเป็นต้องไม่เก็บข้อมูลสถานะที่เกี่ยวข้องกับผู้ใช้ในกระบวนการ ซึ่งกระบวนการธุรกิจควรเป็น stateless เพื่อหลีกเลี่ยงการสูญหายของข้อมูลเนื่องจากการออกจากกระบวนการ