LoginSignup
23
18

More than 5 years have passed since last update.

Goji のアプリケーションサーバーを Circus で管理する

Last updated at Posted at 2015-07-14

Goji には graceful shutdown は標準で用意されているのですが、 graceful restart がありません。
調べていたところ Circus というものを見つけたので、以下の記事を参考にやってみました。

Go で書いたサーバーを管理するには circus が便利

Goji でアプリケーションサーバーを書く

まず、 Goji でシンプルなアプリケーションサーバーを書きます。

package main

import (
    "fmt"
    "net/http"

    "github.com/zenazn/goji"
    "github.com/zenazn/goji/web"
)

func helloWorld(c web.C, w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, world!")
}

func main() {
    goji.Get("/", helloWorld)
    goji.Serve()
}

Goji はデフォルトだと 8000 を使うので HTTPie だと以下のようにリクエストを送れます。
(curl など他の HTTP クライアントでも構いません)

$ http GET :8000
HTTP/1.1 200 OK
Content-Length: 13
Content-Type: text/plain; charset=utf-8
Date: Mon, 14 Jul 2015 09:04:21 GMT

Hello, world!

Hello, world! が返ってきました。

Circus 化する

Circus で管理するためにはコードに手を加える必要があります。 Socket の listen は Circus に任せて、アプリケーションは Circus から受け取ったファイルディスクリプタ (FD) を使うからです。

修正後の main は以下のようになります。

func main() {
    goji.Get("/", hello)

    fd := flag.Uint("fd", 0, "File descriptor to listen and serve.")
    flag.Parse()

    if *fd != 0 {
        listener, err := net.FileListener(os.NewFile(uintptr(*fd), ""))
        if err != nil {
            panic(err)
        }
        goji.ServeListener(listener)
    } else {
        goji.Serve()
    }
}

fd フラグで Circus から FD を受け取ります。 Listener を作成したら ServeListener() に渡して listen を開始します。
fd を受け取らなかった場合は Serve() でデフォルト Listener を使用します。 (ポート 8000)

Circus でサーバーを管理する

Circus の設定ファイルを書きます。

[circus]
statsd = 1

[watcher:webapp]
cmd = goji-with-circus --fd $(circus.sockets.web)
stop_signal = SIGINT
numprocesses = 1
use_sockets = True
copy_env = True

[socket:web]
host = 0.0.0.0
port = 8000

cmd が実行されるコマンドです。fd フラグに渡している circus.sockets.web が下の方で定義している socket:web になります。注意点として、 stop_signal に SIGINT を設定しないと Goji は graceful shutdown しません。デフォルトでは SIGTERM が使われるためです。
では実行してみましょう。

$ circusd circus.ini 
2015-07-14 09:13:01 circus[3617] [INFO] Starting master on pid 3617
2015-07-14 09:13:01 circus[3617] [INFO] sockets started
2015-07-14 09:13:01 circus[3617] [INFO] Arbiter now waiting for commands
2015-07-14 09:13:01 circus[3617] [INFO] webapp started
2015/07/14 09:13:01.716297 Starting Goji on 0.0.0.0:8000
2015-07-14 09:13:01 circus[3617] [INFO] circusd-stats started
2015-07-14 09:13:01 circus[3621] [INFO] Starting the stats streamer

これで Circus を使う前と同じようにリクエストを送ることができます。

$ http GET :8000
HTTP/1.1 200 OK
Content-Length: 13
Content-Type: text/plain; charset=utf-8
Date: Tue, 14 Jul 2015 09:14:18 GMT

Hello, world! 

Circus をモニターする

Circus には 2 つのコマンドラインツールが用意されています。そのひとつが circus-top です。

$ circus-top

Circus Top
------------------------------------------------------------------------------------
circus
   PID                      CPU (%)             MEMORY (%)          AGE (s)
  4245 (circusd-stats)       2.60                0.10                77.16
  3617 (circusd)             0.00                0.10                954.12
                             1.30 (avg)          0.20 (sum)          954.12 (older)

sockets
   ADDRESS                  HITS
  0.0.0.0:8000                 0
                               0 (sum)

webapp
   PID                      CPU (%)             MEMORY (%)          AGE (s)
  4244                       0.00                0.00                77.15
                             0.00 (avg)          0.00 (sum)          77.15 (older)

------------------------------------------------------------------------------------

名前のとおり top の Circus 版という位置付けです。プロセスの CPU 使用率などを見ることができます。

Circus を操作する

もうひとつは circusctl です。こちらは Circus に対して様々な操作を行うことができます。

  • watcher の一覧

    $ circusctl list
    circusd-stats,webapp
    
  • watcher に属するプロセスの一覧

    $ circusctl list webapp
    4244
    
  • watcher に属するプロセスの増減

    $ circusctl incr webapp
    ok
    $ circusctl list webapp
    4244,4735
    $ circusctl decr webapp
    ok
    $ circusctl list webapp
    4735
    
  • お待ちかねの graceful restart

    $ circusctl reload
    ok
    

また、 circusctl には REPL も用意されています。

$ circusctl
circusctl 0.12.0
circusd-stats: active
webapp: active
(circusctl) list
circusd-stats,webapp
(circusctl) reload
ok

参考

今回のコードは GitHub にあります。

tchssk/goji-with-circus

23
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
18