一個軟體程式可能會用到其它的服務(service),例如網站應用程式會去使用到資料庫服務。當這類軟體程式運行的時候,如果它所使用到的外部服務還處於不可用的狀態的話,那麼這個軟體程式就很有可能在運行的時候出現問題。



上述的狀況很常發生在運行於Docker容器中的軟體程式,即便Docker Compose本身有提供depends_on的功能,可以讓一個容器在其它一個或多個容器被啟動之後才被啟動,但它並無法保證容器是在某個或是某些「服務」被啟動之後才啟動,因為啟動容器並不表示容器中的服務也立刻完成啟動程序了。

實際上已經有一個wait-for-it專案就是要來解決這樣的問題,使用Bash來實現,還蠻多人用的。然而wait-for-it只支援TCP服務,且一次只能夠等待一個服務,如果有多個服務要等待,就只能寫好幾個wait-for-it指令。此外,wait-for-it也不能夠直接讀取外部的設定值,因為有可能在不同執行環境下我們要等待的服務的位址是不一樣的,這就會讓wait-for-it用起來挺綁手綁腳的。wait-for-it也還需要有Bash環境才可以執行,在Windows作業系統上使用不易。

Wait Service

「Wait Service」是筆者用純Rust程式語言製作的工具,可以測試並且等待服務的可用性,當這些服務全都處於可用的狀態後,才去執行指定的指令。除了支援TCP服務之外,也支援UDS(Unix Domain Socket)的服務,也可以透過設定檔案來指定「Wait Service」要等待哪些服務。

GitHub:

https://github.com/magiclen/wait-service

使用 Wait Service

建議在您軟體程式的運行環境上編譯出「Wait Service」的執行檔,以達到最輕量的結果。可以使用以下指令來編譯並安裝wait-service指令工具,當然還要有Rust編譯環境才能執行。

cargo install wait-service

wait-service指令工具的用法很簡單。使用wait-service -h可以查看用法。

wait-service

下面以幾個wait-service指令來進行說明:

wait-service --tcp localhost:27017 --tcp localhost:27018 -t 5 -- npm start

以上指令會等待(最多5秒)localhost:27017localhost:27018這兩個TCP服務啟動之後,才去執行npm start指令。

wait-service --tcp localhost:27017 --uds /var/run/app.sock -t 0 -- npm start

以上指令會等待(因為-t設為0,所以無時間上限)localhost:27017TCP服務和/var/run/app.sockUDS服務啟動之後,才去執行npm start指令。

wait-service --uds /var/run/app.sock --json /path/to/json -- npm start

以上指令會等待(無時間上限)/var/run/app.sockUDS服務和被定義在/path/to/json這個設定檔中的所有服務都啟動之後,才去執行npm start指令。

Wait Service 的設定檔

wait-service指令的--json參數可以傳入一個設定檔的檔案路徑,設定檔是JSON格式的純文字檔案,必須是一個JSON物件的陣列。陣列中的每個JSON物件表示一個要讓wait-service測試並等待的服務。

對於一個TCP服務,JSON物件的格式如下:

{
    "host": "example.com",
    "port": 443
}

對於一個UDS服務,JSON物件的格式如下:

{
    "uds": "/path/to/socket_file"
}