Mac OSのGoをNGINX Unitで動かしてみる
NGINX Unit
NGINX UnitがアプリケーションサーバとしてOSSで登場しました。
9/8(金)の夜に Mac OS
の Go
で試した作業ログと気付いた点などをまとめておきます。ぱっと調べたところ Mac OS
で実際に動かした人の情報は無さそうですね。
ドキュメントは GitHub - nginx/unit: An official read-only mirror of http://hg.nginx.org/unit/ を参考にしてください。
Go
から unit
パッケージを利用するには、現状だとまだ go get
で落としてくることは出来ないのでソースコードを落としてきてビルドする必要があります。
ちなみに余談ですが unit
ではなく nginxunit
など別のパッケージ名にした方が良かったのになぁと個人的には思いました。
それでは、実際に Go
でアプリケーションを動作させるまでの手順を最低限記載しておきますので興味のある人は、本ブログのままコピペで動かすところまでやってみてください。
2017/09/09の時点では、 Mac OS
上で Go
のアプリケーションを動作させることは出来ませんでした。但し Mac OS
で行った同じ手順を ubuntu
で行ったところ正常に動作したことを確認出来ました。以下の手順は Mac OS
と ubuntu
共通です。特に問題なければビルドから実行まで10分あれば試せますので是非いろいろ触ってみては如何でしょうか。
install
インストールは、以下の通り。
$ git clone https://github.com/nginx/unit
$ cd unit
$ ./configure
$ ./configure go
$ make all
$ make go-install
$ make install
これで $GOPATH
配下に unit
がインストールされ Go
で unit
を利用する準備が整いました。
起動
Mac OS
で起動するには make
したカレンドディレクトリの sbin
配下の unitd
を実行します。バージョンを確認してから起動しました。
ubuntu
の場合も sbin
配下の unitd
起動でも確認とれましたし、 sudo service unitd start
からでも起動から Go
アプリの実行まで確認出来ています。
$ ./sbin/unitd --version unit version: 0.1 configured as ./configure $./sbin/unitd
起動するとdefaultでカレントディレクトリに control.unit.sock
ファイルが生成されます。参照 https://github.com/nginx/unit#configuration
起動オプション
$ ./sbin/unitd --help unit options: --version print unit version and configure options --no-daemon run unit in non-daemon mode --control ADDRESS set address of control API socket default: "unix:control.unit.sock" --pid FILE set pid filename default: "unit.pid" --log FILE set log filename default: "unit.log" --modules DIRECTORY set modules directory name default: "build" --user USER set non-privileged processes to run as specified user default: "nobody" --group GROUP set non-privileged processes to run as specified group default: user's primary group
登録確認
まず listener
や application
の確認を行います。まだ未登録だということがわかります。
$ curl --unix-socket /Users/yone098/nginx-unit-work/unit/control.unit.sock http://127.0.0.1 { "listeners": {}, "applications": {} }
Goアプリケーション作成
Go
で簡単なアプリケーションを作成します。 http.ListenAndServe
を unit.ListenAndServe
に変更するだけです。
公式ドキュメントの import
が { }
になっているのでそのままコピペすると動かないので ( )
に書き換えてください。
package main import ( "io" "net/http" "unit" ) func HelloServer(w http.ResponseWriter, req *http.Request) { io.WriteString(w, "hello, unit!\n") } func main() { http.HandleFunc("/", HelloServer) // 以下を unit に変更する //http.ListenAndServe(":8000", nil) unit.ListenAndServe(":8000", nil) }
go build
してバイナリを作成します。
設定ファイルにて作成したバイナリを executable
として指定します。
設定ファイル
{ "listeners": { "*:8070": { "application": "golang" } }, "applications": { "golang": { "type": "go", "workers": 1, "executable": "/Users/yone098/nginx-unit-work/gounit", } } }
登録
$ curl -X PUT -d @/Users/yone098/nginx-unit-work/gounit.json --unix-socket /Users/yone098/nginx-unit-work/unit/control.unit.sock http://127.0.0.1/ { "success": "Reconfiguration done." }
確認
$ curl --unix-socket /Users/yone098/nginx-unit-work/unit/control.unit.sock http://127.0.0.1/ { "listeners": { "*:8080": { "application": "golang" } }, "applications": { "golang": { "type": "go", "workers": 1, "executable": "/home/ubuntu/gounit" } } }
登録したあとに変更する場合は listener
を一旦削除してから登録します。
以下のように削除したあとに確認すると listener
が削除されていることが確認出来ます。
削除
$ curl -X DELETE --unix-socket /Users/yone098/nginx-unit-work/unit/control.unit.sock 'http://127.0.0.1/listeners/*:8080' { "success": "Reconfiguration done." }
$ curl --unix-socket /Users/yone098/nginx-unit-work/unit/control.unit.sock http://127.0.0.1/ { "listeners": {}, "applications": { "golang": { "type": go", "workers": 1, "executable": "/tmp/gounit" } } }
Mac OS でのエラー
Mac OSで確認
$ curl http://127.0.0.1:8080/
Read header timeout
エラーログ
2017/09/09 23:52:21 [info] 28656#1194422 "golang" application started 2017/09/09 23:52:21 [crit] 28329#1175827 process 28656 exited on signal 9 2017/09/09 23:52:26 [alert] 28335#1176038 *17 error 408: Read header timeout
ubuntu で実行
$ curl http://127.0.0.1:8080/
hello, unit!
Mac OS
上の Go
で実行しようとした際に “Read header timeout” になる件は、 nxt_router.c
の 3185
行あたり
static void nxt_router_conn_timeout(nxt_task_t *task, void *obj, void *data) { nxt_conn_t *c; nxt_timer_t *timer; timer = obj; nxt_debug(task, "router conn timeout"); c = nxt_read_timer_conn(timer); if (c->read_state == &nxt_router_conn_read_header_state) { nxt_router_gen_error(task, c, 408, "Read header timeout"); } else { nxt_router_gen_error(task, c, 408, "Read body timeout"); } }
ubuntu
上だと全く同じ手順(ビルド後の ./sbin/unitd 経由で起動した場合)で正常に Go
のアプリケーションが稼働しているところをみると Mac OS
固有の問題なんだろうなと思う。しばらくしたら Mac OS
でも正常に動作するようになるかなと期待します。
まとめ
まだ出たばかりなので、これからに期待といったところでしょうか。
ubuntu
でアプリ書き換え後にホットリロードされるかと思ったのですが unitd
の再起動後、再度設定し直す必要があり、このへんもこれからといったところだと思いました。
今後は、 https://github.com/nginx/unit#key-features
Key Features
を見るとこれから機能追加といったところでしょうか。
- Fully dynamic reconfiguration using RESTful JSON API - Multiple application languages and versions can run simultaneously - Dynamic application processes management (coming soon) - TLS support (coming soon) - TCP, HTTP, HTTPS, HTTP/2 routing and proxying (coming soon)
Node.js, Java, Ruby もサポートするようなので Java
サポートされたらまた触ってみようと思います。