Gateway

การล็อก Gateway

เหตุผล

  • ควรมีโปรเซส Gateway เพียงโปรเซสเดียวที่เป็นเจ้าของไดเรกทอรีสถานะ หากต้องการเรียกใช้ Gateway เพิ่มเติม ให้ใช้โปรไฟล์ ไดเรกทอรีสถานะ การกำหนดค่า และพอร์ตที่แยกจากกัน
  • ทำงานต่อได้หลังเกิดข้อขัดข้อง/SIGKILL โดยไม่ทิ้งไฟล์ล็อกที่ค้างอยู่
  • ล้มเหลวทันทีพร้อมข้อผิดพลาดที่ชัดเจนเมื่อ Gateway อื่นเป็นเจ้าของพอร์ตอยู่แล้ว

สามชั้น

การเริ่มต้นระบบบังคับใช้ความเป็นเจ้าของตามลำดับสามขั้นตอนดังนี้:

  1. ล็อกความเป็นเจ้าของสถานะ จะขอล็อกที่ผูกกับไดเรกทอรีสถานะแบบมาตรฐาน Gateway ทุกตัวมีส่วนร่วม รวมถึง Gateway ที่เริ่มต้นด้วย OPENCLAW_ALLOW_MULTI_GATEWAY=1 เพื่อไม่ให้การบำรุงรักษา SQLite ที่ทำลายข้อมูลเกิดภาวะแข่งขันกับเจ้าของที่กำลังทำงานอยู่
  2. ล็อกการกำหนดค่า จะขอล็อกต่อการกำหนดค่าแบบเดิมและบันทึกพอร์ตรันไทม์ โหมดหลาย Gateway จะข้ามซิงเกิลตันการกำหนดค่านี้ แต่ยังคงใช้ล็อกความเป็นเจ้าของสถานะ
  3. การผูกซ็อกเก็ต จะผูกตัวรับฟัง HTTP/WebSocket (ค่าเริ่มต้น ws://127.0.0.1:18789) เป็นตัวรับฟัง TCP แบบเอกสิทธิ์

แต่ละชั้นอาจล้มเหลวได้โดยอิสระและจะโยน GatewayLockError ของตนเอง

ล็อกสถานะและการกำหนดค่า

  • การตรวจสอบว่าล็อกยังทำงานอยู่พิจารณาจาก PID ที่บันทึกไว้ ข้อมูลระบุเวลาเริ่มต้นของโปรเซสบนแพลตฟอร์มเมื่อมี และข้อมูลระบุโปรเซส Gateway เจ้าของที่ผ่านการตรวจสอบแล้วยังคงมีสิทธิ์ขาดระหว่างการเริ่มต้นระบบก่อนที่พอร์ตจะเริ่มรับฟัง

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

  • หากไฟล์ล็อกหายไปหรือโปรเซสเจ้าของที่บันทึกไว้ไม่ทำงานแล้ว การเริ่มต้นระบบจะเรียกคืนล็อกและดำเนินการต่อ

  • หากล็อกใดล็อกหนึ่งถูกถือครองอยู่ การเริ่มต้นระบบจะลองใหม่เป็นเวลาสูงสุด 5 วินาที (ค่าเริ่มต้น) ก่อนยุติความพยายาม:

    text
    GatewayLockError("Gateway กำลังทำงานอยู่แล้ว (pid <pid>); หมดเวลารอล็อกหลังจาก <ms>ms")

การผูกซ็อกเก็ต

  • เมื่อเกิด EADDRINUSE การเริ่มต้นระบบจะลองผูกใหม่สูงสุด 20 ครั้ง โดยเว้นช่วงครั้งละ 500ms (รวมประมาณ 10 วินาที) เพื่อรอให้พ้นช่วง TIME_WAIT หลังจากโปรเซสเพิ่งสิ้นสุด

  • หากพอร์ตยังคงถูกใช้งานหลังจากลองใหม่:

    text
    GatewayLockError("อินสแตนซ์ Gateway อื่นกำลังรับฟังอยู่แล้วบน ws://127.0.0.1:<port>")
  • ความล้มเหลวอื่นในการผูก:

    text
    GatewayLockError("ไม่สามารถผูกซ็อกเก็ต Gateway บน ws://127.0.0.1:<port>: <cause>")

เมื่อปิดระบบ Gateway จะปิดเซิร์ฟเวอร์ HTTP/WebSocket และลบไฟล์ล็อกสถานะ และการกำหนดค่าของตน

หมายเหตุด้านการปฏิบัติงาน

  • หากพอร์ตถูกใช้งานโดยโปรเซสอื่นที่ไม่ใช่ Gateway ข้อผิดพลาดจะเหมือนกัน ให้คืนพอร์ตหรือเลือกพอร์ตอื่นด้วย openclaw gateway --port <port>
  • OPENCLAW_ALLOW_MULTI_GATEWAY=1 อนุญาตให้มีอินสแตนซ์การกำหนดค่า/รันไทม์หลายอินสแตนซ์ ไม่ใช่การใช้สถานะที่เปลี่ยนแปลงได้ร่วมกัน แต่ละอินสแตนซ์ยังคงต้องมี OPENCLAW_STATE_DIR ที่ไม่ซ้ำกัน
  • เมื่อทำงานภายใต้ตัวควบคุมบริการ โปรเซส Gateway ใหม่ที่พบข้อผิดพลาดใดข้อผิดพลาดหนึ่งข้างต้นจะตรวจสอบ /healthz ของโปรเซสที่มีอยู่ก่อน หากโปรเซสนั้นทำงานเป็นปกติ โปรเซสใหม่จะปล่อยให้โปรเซสเดิมควบคุมต่อไปแทนที่จะล้มเหลว บน systemd โปรเซสจะออกด้วยรหัส 78; RestartPreventExitStatus=78 ของยูนิตจะป้องกันไม่ให้ Restart=always วนซ้ำเมื่อเกิดข้อขัดแย้งด้านล็อกหรือ EADDRINUSE หากโปรเซสที่มีอยู่ไม่กลับมาทำงานเป็นปกติ การลองตรวจสอบสถานะจะถูกจำกัดเวลา จากนั้นการเริ่มต้นระบบจะล้มเหลวด้วยข้อผิดพลาดด้านล็อกข้างต้นแทนที่จะวนซ้ำตลอดไป
  • แอป macOS มีตัวป้องกัน PID แบบเบาของตนเองก่อนสร้างโปรเซส Gateway โดยไฟล์ล็อกและการผูกซ็อกเก็ตข้างต้นเป็นกลไกบังคับใช้จริงขณะรันไทม์

ที่เกี่ยวข้อง

  • หลาย Gateway - การเรียกใช้หลายอินสแตนซ์ด้วยพอร์ตที่ไม่ซ้ำกัน
  • การแก้ไขปัญหา - การวินิจฉัย EADDRINUSE และข้อขัดแย้งของพอร์ต
Was this useful?
On this page

On this page