DevDevデブ!!

プログラミングのこととか書きます。多分。。。

echoでgraceful restart

ちょろっとググっても見つからなかったので書いておく。

分かってると思うけど、golangのWAFのechoです。

go-server-starterを使う

github.com

使い方は下記の記事を参考にした。

shogo82148.github.io

net/httpをそのまま使うのであれば、上記の記事の通りに使えば完了なのだが、echoの場合、go-server-starter/listenerを使って得られるnet.Listenerインターフェイスの(実装)インスタンスをどこに差し込むのかという話になる。

まあ、echoのgodoc読めばすぐ分かるんだけどもね

type Echo struct {
    Server           *http.Server
    TLSServer        *http.Server
    Listener         net.Listener
    TLSListener      net.Listener
    AutoTLSManager   autocert.Manager
    DisableHTTP2     bool
    Debug            bool
    HideBanner       bool
    HTTPErrorHandler HTTPErrorHandler
    Binder           Binder
    Validator        Validator
    Renderer         Renderer
    // Mutex            sync.RWMutex
    Logger Logger
    // contains filtered or unexported fields
}

と、上記のようにEcho構造体のメンバ、Listenerは外部から差し替えられるので、そこに差し込めばよい

e.Listener = l

という感じに

(もちろんeはEcho構造体のインスタンスで、lはnet.Listenerのインスタンス)

あとは、公式cookbookのgraceful shutdownのページにある通りにすればよい

echo.labstack.com

注意点として、net.Listenerにすでにポート番号を指定しているので、echoサーバを開始するときにはポート番号を指定しないようにすること。(上記のリンク中では指定している)

e.start("")

のように空文字を指定する。

あとは、ビルドしてできたバイナリをstart_serverコマンド経由で起動する。

start_serverコマンドは本家のperl版のServer::Starterと同じなので適当にググって

簡単な例だと以下のような感じ(appはechoで作ったサーバのバイナリ名として)

start_server --port="任意のポート番号" --pid-file=/tmp/app.pid --status-file=/tmp/app.status -- app

pid-fileとstatus-fileのpathも任意です。

そして、supervisorとかでstart_serverプロセスを管理する。

graceful restartさせたい場合、start_serverのプロセスにHUPシグナルを発行するか、以下のようにする。

start_server --pid-file=/tmp/app.pid --status-file=/tmp/app.status --restart

pid-fileとstatus-fileのパスは、プロセスを立ち上げたときに指定したのと同じものを指定する。

facebook/graceとかじゃダメなん?

echoの公式でもfacebook/graceを使っていたので、これでいんじゃね?と思ったのだけど、facebook/graceだとプロセスIDが変わってしまうのだとか?

supervisorで管理したかったので、それは避けたかった

Server::Starterの場合、supervisorで直接管理するのはstart_serverプロセスで、greceful restartしたい対象のプロセスはstart_serverプロセスが管理するような形になる。

start_server管理下のプロセスはgraceful restartでプロセスIDが変わる(というか新規に立ち上げる)のだけど、start_serverプロセスのプロセスID自体は変わらないので、そのままsupervisorで管理できる。