Gateway
閘道鎖定
原因
- 只有一個閘道程序可擁有一個狀態目錄;若要執行其他閘道,請使用彼此隔離的設定檔、狀態目錄、設定與連接埠。
- 即使發生當機或 SIGKILL,也不會留下過期的鎖定檔案。
- 當另一個閘道已占用該連接埠時,立即失敗並顯示明確錯誤。
三層機制
啟動程序會依序透過三個步驟強制執行擁有權:
- 狀態擁有權鎖定會取得以標準狀態目錄為鍵的鎖定。每個閘道都會參與,包括以
OPENCLAW_ALLOW_MULTI_GATEWAY=1啟動的閘道,因此具破壞性的 SQLite 維護作業不會與運作中的擁有者發生競爭。 - 設定鎖定會取得既有的個別設定鎖定,並記錄執行階段連接埠。多閘道模式會略過此設定單例限制,但仍保留狀態擁有權鎖定。
- 通訊端繫結會將 HTTP/WebSocket 接聽器(預設為
ws://127.0.0.1:18789)繫結為獨占 TCP 接聽器。
每一層都可能獨立失敗,並擲回各自的 GatewayLockError。
狀態與設定鎖定
-
鎖定是否仍有效,是根據記錄的 PID、平台程序啟動識別資訊(若有),以及閘道程序識別資訊來判定。經驗證的擁有者在啟動期間仍具有決定權,即使其連接埠尚未開始接聽也是如此。
-
專用的 SQLite 協調器會依序處理中繼資料檢查、過期擁有者回收及鎖定替換。若擁有該鎖定的程序當機,其獨占交易會自動釋放。
-
如果鎖定檔案不存在,或記錄的擁有者程序已結束,啟動程序會回收鎖定並繼續。
-
如果任一鎖定正被占用,啟動程序會重試最多 5 秒(預設值),然後放棄:
text GatewayLockError("閘道已在執行(pid <pid>);鎖定在 <ms>ms 後逾時")
通訊端繫結
-
發生
EADDRINUSE時,啟動程序會以 500ms 的間隔重試繫結最多 20 次(總計約 10 秒),以等待最近結束的程序所造成的TIME_WAIT時段結束。 -
如果重試後連接埠仍在使用中:
text GatewayLockError("另一個閘道執行個體已在 ws://127.0.0.1:<port> 上接聽") -
其他繫結失敗:
text GatewayLockError("無法在 ws://127.0.0.1:<port> 上繫結閘道通訊端:<cause>")
關閉時,閘道會關閉 HTTP/WebSocket 伺服器,並移除其狀態與設定鎖定檔案。
操作注意事項
- 如果連接埠被其他非閘道程序占用,錯誤訊息也會相同;請釋放該連接埠,或使用
openclaw gateway --port <port>選擇另一個連接埠。 OPENCLAW_ALLOW_MULTI_GATEWAY=1允許多個設定/執行階段執行個體,但不允許共用可變狀態。每個執行個體仍需要唯一的OPENCLAW_STATE_DIR。- 在服務監督程式下,遇到上述任一錯誤的新閘道程序會先探測現有程序上的
/healthz。如果該程序運作正常,新程序會讓其繼續掌控,而不會失敗。在 systemd 上,新程序會以代碼78結束;單元的RestartPreventExitStatus=78會防止Restart=always因鎖定或EADDRINUSE衝突而循環。如果現有程序始終未恢復正常,健康狀態探測的重試會受時間限制,之後啟動程序會以上述鎖定錯誤失敗,而不會無限循環。 - macOS 應用程式會在產生閘道程序前保留自己的輕量級 PID 防護;上述檔案鎖定與通訊端繫結才是實際的執行階段強制機制。
相關內容
Was this useful?