Gateway
การล็อก Gateway
เหตุผล
- กระบวนการ Gateway เพียงกระบวนการเดียวเท่านั้นที่ควรเป็นเจ้าของการกำหนดค่าและพอร์ตหนึ่งชุดบนโฮสต์ หากต้องการเรียกใช้ Gateway เพิ่มเติม ให้ใช้โปรไฟล์ที่แยกจากกันและพอร์ตที่ไม่ซ้ำกัน
- ทำงานต่อได้แม้เกิดการขัดข้องหรือ
SIGKILLโดยไม่ทิ้งไฟล์ล็อกที่ค้างอยู่ - หยุดทำงานทันทีพร้อมข้อผิดพลาดที่ชัดเจน เมื่อ Gateway อื่นเป็นเจ้าของพอร์ตอยู่แล้ว
การป้องกันสองชั้น
เมื่อเริ่มทำงาน ระบบจะบังคับให้มีเจ้าของอินสแตนซ์เดียวผ่านสองขั้นตอนที่เป็นอิสระต่อกันตามลำดับ:
- การล็อกไฟล์ จะครอบครองไฟล์ล็อกสำหรับแต่ละการกำหนดค่าในไดเรกทอรีล็อกของสถานะ ระหว่างการครอบครอง ระบบจะตรวจสอบพอร์ตที่กำหนดค่าไว้ว่ามีตัวรับฟังที่ทำงานอยู่หรือไม่ เพื่อระบุเจ้าของล็อกที่ค้างอยู่จากการขัดข้อง
- การผูกซ็อกเก็ต จะผูกตัวรับฟัง HTTP/WebSocket (ค่าเริ่มต้นคือ
ws://127.0.0.1:18789) ให้เป็นตัวรับฟัง TCP แบบเอกสิทธิ์
แต่ละชั้นอาจล้มเหลวได้อย่างเป็นอิสระและจะส่ง GatewayLockError ของตนเอง
การล็อกไฟล์
-
หากไม่มีไฟล์ล็อก กระบวนการเจ้าของที่บันทึกไว้สิ้นสุดไปแล้ว หรือการตรวจสอบพอร์ตของเจ้าของไม่พบตัวรับฟังที่ทำงานอยู่ ระบบเริ่มต้นจะยึดล็อกคืนและทำงานต่อ
-
หากล็อกยังถูกครอบครองอยู่และไม่เข้าเงื่อนไขข้างต้น ระบบเริ่มต้นจะลองใหม่เป็นเวลาสูงสุด 5 วินาที (ค่าเริ่มต้น) ก่อนยอมแพ้:
text GatewayLockError("gateway already running (pid <pid>); lock timeout after <ms>ms")
การผูกซ็อกเก็ต
-
เมื่อเกิด
EADDRINUSEระบบเริ่มต้นจะลองผูกซ็อกเก็ตใหม่สูงสุด 20 ครั้ง โดยเว้นช่วงครั้งละ 500 มิลลิวินาที (รวมประมาณ 10 วินาที) เพื่อรอให้พ้นช่วงTIME_WAITหลังจากกระบวนการเพิ่งสิ้นสุด -
หากพอร์ตยังคงถูกใช้งานหลังจากลองใหม่แล้ว:
text GatewayLockError("another gateway instance is already listening on ws://127.0.0.1:<port>") -
การผูกซ็อกเก็ตล้มเหลวด้วยสาเหตุอื่น:
text GatewayLockError("failed to bind gateway socket on ws://127.0.0.1:<port>: <cause>")
เมื่อปิดการทำงาน Gateway จะปิดเซิร์ฟเวอร์ HTTP/WebSocket และลบไฟล์ล็อก
หมายเหตุด้านการปฏิบัติงาน
- หากพอร์ตถูกใช้งานโดยกระบวนการอื่นที่ไม่ใช่ Gateway ข้อผิดพลาดจะเหมือนกัน ให้ทำให้พอร์ตว่างหรือเลือกพอร์ตอื่นด้วย
openclaw gateway --port <port> - ภายใต้ตัวควบคุมบริการ กระบวนการ Gateway ใหม่ที่พบข้อผิดพลาดอย่างใดอย่างหนึ่งข้างต้นจะตรวจสอบ
/healthzของกระบวนการเดิมก่อน หากกระบวนการนั้นทำงานเป็นปกติ กระบวนการใหม่จะปล่อยให้กระบวนการเดิมควบคุมต่อไปแทนที่จะล้มเหลว บน systemd กระบวนการใหม่จะออกด้วยรหัส78โดยRestartPreventExitStatus=78ของยูนิตจะป้องกันไม่ให้Restart=alwaysวนซ้ำเมื่อเกิดข้อขัดแย้งด้านล็อกหรือEADDRINUSEหากกระบวนการเดิมไม่กลับมาทำงานเป็นปกติ การลองตรวจสอบสถานะซ้ำจะมีการจำกัดเวลา จากนั้นการเริ่มต้นจะล้มเหลวด้วยข้อผิดพลาดด้านล็อกข้างต้นแทนที่จะวนซ้ำตลอดไป - แอป macOS มีตัวป้องกัน PID แบบเบาของตัวเองก่อนสร้างกระบวนการ Gateway ส่วนการล็อกไฟล์และการผูกซ็อกเก็ตข้างต้นเป็นกลไกบังคับใช้จริงขณะทำงาน
เนื้อหาที่เกี่ยวข้อง
- Gateway หลายอินสแตนซ์ - การเรียกใช้หลายอินสแตนซ์ด้วยพอร์ตที่ไม่ซ้ำกัน
- การแก้ไขปัญหา - การวินิจฉัย
EADDRINUSEและข้อขัดแย้งของพอร์ต