Go言語でサーバのGraceful Shutdown
Go言語のサーバで Graceful Restart をするにあたり go-server-starter を使ってみようかなと思ったので、そのために必要なライブラリを調査してみました。
Graceful Restart
今回の主題とは別件ですが、Go言語の Graceful Restart のためのライブラリでは、os.StartProcess
や exec.Command
によって自分自身の子プロセスを起動し、ファイルディスクリプタ経由でソケットを渡して、再起動時は子プロセスのみを停止・起動するものがあります。
今回はこれらのライブラリについては触れません。
Graceful Shutdown
もう一方で、Graceful Shutdown の機能だけを提供するものがあります。
これらの場合では go-server-starter や circus などがソケットを保持して子プロセスを起動し、ファイルディスクリプタ経由で子プロセスにソケットを渡すことになります。
go-server-starter
go-server-starter を使って Graceful Shutdown の各ライブラリを使ったサンプルを実装してみました。ソースコード全体は github.com/najeira/grace_samples をご覧ください。
※ 前述のリポジトリ内にある facebookgo_httpdown のみ、リスナーを外部から渡せないので go-server-starter に対応したものではなく、単独でのサンプルです。今回は関係ありません。
試してみる
go get
go get github.com/lestrrat/go-server-starter/cmd/start_server
go get github.com/najeira/grace_samples/braintree_manners
go get github.com/najeira/grace_samples/shogo_gracedown
go get github.com/najeira/grace_samples/tylerb_graceful
go build
braintree_manners を試す場合。
cd $GOPATH/src/github.com/najeira/grace_samples/braintree_manners
go build
run
サーバを起動します。
$GOPATH/bin/start_server --port 8080 --pid-file app.pid -- ./braintree_manners &
HTTPリクエストを送ってみます。
curl http://localhost:8080/
going to sleep 100ms with pid 2880
slept 100ms with pid 2880
restart
サーバの再起動は HUP
です。
kill -HUP `cat app.pid`
received HUP (num_old_workers=TODO)
spawning a new worker (num_old_workers=TODO)
starting new worker 2899
new worker is now running, sending TERM to old workers:2880
sleep 0 secs
killing old workers
old worker 2880 died, status:0
stop
サーバの停止は TERM
です。
kill -TERM `cat app.pid`
負荷をかけてみる
シグナル HUP
を送り続けて再起動させ続けます。
while true; do kill -HUP `cat app.pid`; sleep 1; done
ab
別のセッションで ab
で負荷をかけてみます。
ab -r -n 100000 -c 1000 http://localhost:8080/
Results
braintree_manners
Concurrency Level: 1000
Time taken for tests: 12.580 seconds
Complete requests: 100000
Failed requests: 22
(Connect: 0, Receive: 0, Length: 22, Exceptions: 0)
Write errors: 0
Total transferred: 15798424 bytes
HTML transferred: 6099200 bytes
Requests per second: 7949.39 [#/sec] (mean)
Time per request: 125.796 [ms] (mean)
Time per request: 0.126 [ms] (mean, across all concurrent requests)
Transfer rate: 1226.44 [Kbytes/sec] received
shogo_gracedown
Concurrency Level: 1000
Time taken for tests: 12.898 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 15801082 bytes
HTML transferred: 6100306 bytes
Requests per second: 7753.17 [#/sec] (mean)
Time per request: 128.980 [ms] (mean)
Time per request: 0.129 [ms] (mean, across all concurrent requests)
Transfer rate: 1196.37 [Kbytes/sec] received
tylerb_graceful
Concurrency Level: 1000
Time taken for tests: 12.472 seconds
Complete requests: 100000
Failed requests: 0
Write errors: 0
Total transferred: 15800474 bytes
HTML transferred: 6100183 bytes
Requests per second: 8017.95 [#/sec] (mean)
Time per request: 124.720 [ms] (mean)
Time per request: 0.125 [ms] (mean, across all concurrent requests)
Transfer rate: 1237.18 [Kbytes/sec] received
Environment
- go version go1.6.2 linux/amd64
- Amazon EC2 c4.large
- Linux version 4.4.11-23.53.amzn1.x86_64
Conclusion
braintree_manners で取りこぼしがあるようです。
他、おすすめの Shutdown ライブラリがあれば、ぜひ教えてください!
参考
See: https://shogo82148.github.io/blog/2015/11/23/golang-graceful-restart-2nd/
この記事はQiitaの記事をエクスポートしたものです
Discussion