Socket Daemon
最後更新
core/daemon 讓所有開啟同一資料目錄的 process 共用一個 unix socket;本頁說明 daemon.New 如何決定該 process 成為 server 或 client。
滿足的需求
| # | 需求 | 做法 |
|---|---|---|
| 1 | 每個 ToriiDB 位置一個共用 socket | 第一個 process 開啟唯一的 Store,其他 process 透過 socket 與它溝通 |
| 2 | 不同位置使用不同 socket | Socket 名稱是解析後絕對目錄的 hash |
| 3 | 同位置重複 New 共用 socket |
New 先撥號;socket 存活即為 client 模式 |
| 4 | 呼叫端不必判斷角色 | Get/Set/Del/... 在兩種模式行為一致 |
傳輸是 unix socket,搭配自訂的長度前綴 JSON frame,不使用 HTTP。
模式判定
daemon.New(dir, apiKey...) 依序執行:
- 拒絕空的
dir。 resolveDir:CheckDir(dir, true)→filepath.Abs→filepath.EvalSymlinks。resolveSocket:/tmp/toriidb-<uid>-<hex(sha256(realDir)[:8])>.sock。probeSocket:net.DialTimeout("unix", path, 500ms)。
| 探測結果 | 模式 | New 的動作 |
|---|---|---|
| 撥號成功 | ModeClient |
建立連線池 client,不開啟 store |
ECONNREFUSED 或 ENOENT |
ModeServer |
開啟 store.New(realDir, apiKey...) |
| 其他撥號錯誤 | 錯誤 | 回傳 probe socket <path>: ... |
| 設計規則 | 原因 |
|---|---|
Socket 目錄固定為 /tmp |
os.TempDir() 讀 $TMPDIR,socket 會變成取決於環境而非位置 |
路徑必須經過 EvalSymlinks |
macOS 的 /tmp 是 /private/tmp 的 symlink;relx、./relx、/tmp/relx/、/private/tmp/relx 與 symlink 必須收斂 |
存活只以撥號判定,不用 os.Stat |
kill -9 會留下 socket 檔;殘留檔案不能阻止新 server 啟動 |
檔名含 uid |
/tmp 由多個使用者共用 |
New 吃 dir 而非 *store.Store |
探測必須在開啟 store 之前;client 不可對同一目錄再開一個 store |