せっかくなので動作までの作業ログと所感をまとめて書いておく。最新のインターフェースや環境構築については公式README.mdのほうが詳しいので参考程度に。記事内リンクについてはv0.1時点のものを引用しているためmasterとは差分があるので注意。
環境
Vagrantでubuntu-xenialを用意してgolangの受け答えができるところまで作った
$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"
構築
unitの本体を入れる
configurationの受け答えしたり、(将来的に)アプリケーションのリロードや監視などのAPIが生えるであろうパッケージ。yum
だと面倒な手順いらないらしいけどapt
だとkeyの登録が必要だったりする。インストール手順はREADME.md#ubuntu-packagesを見てほしい。
goのプロジェクト作成
テスト環境なのでディレクトリはGOPATH
以下に作ってしまう
$ mkdir -p $GOPATH/src/github.com/your-name/nginx-unit $ cd $GOPATH/src/github.com/your-name/nginx-unit $ touch nginx-unit.go
nginx-unit.go
このunit
パッケージはgolangだけ必要らしい。PHP, pythonはピュアな応答をするモジュールを作成するだけで済むが、Golangはおそらくバイナリ上でポート設定等をgracefulにやりたかったのでパッケージを別にする必要があったのだと思ってる*1。それはそうと、unit
って名前どうにかならないのかな。リネーム前のnginext
よりはいいんだけど。
package main import ( "fmt" "net/http" "unit" ) func handler(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "text/plain") fmt.Fprintf(w, "Proto : %s\n", r.Proto) fmt.Fprintf(w, "Method : %s\n", r.Method) fmt.Fprintf(w, "URL : %s\n", r.URL.Path) fmt.Fprintf(w, "Host : %s\n", r.Host) } func main() { http.HandleFunc("/", handler) // port はダミーなので適当で良い unit.ListenAndServe("8080", nil) }
nginx/unitをコンパイル
各種言語用のパッケージをコードからビルドする必要があるのでcloneしてきて必要なものをビルドしていく。依存パッケージのインストールからパッケージのインストールまでをやると動く。特にv0.1に関しては入れるだけで済んだ。
起動
goのプロジェクトをビルドしてパスを控える
$ cd $GOPATH/src/github.com/your-name/nginx-unit $ go build
unit本体の起動
$ sudo service unitd start
一応socket探す(手元では /run/control.unit.sock
にあった)
$ find / -name 'control.unit.sock'
config.json
configuration用のjson。executable
へは先程のビルドしたバイナリファイルへのパスを書く。また、ポート・ワーカー数などは適当な数に設定する
{ "listeners": { "*:8040": { "application": "golang" } }, "applications": { "golang": { "type": "go", "workers": 1, "executable": "full/path/to/nginx-unit/binary/file", } } }
jsonの内容はAPI、もしくはserviceに生えてるインターフェースから適用する
$ sudo curl -X PUT -d @config.json --unix-socket /run/control.unit.sock http://127.0.0.1:8040/ # または $ sudo service unitd restoreconfig /full/path/to/json
ここまでするとconfigに書いた内容でgolangのプロセスが立ち上がっているのでcurlで確認
$ curl curl http://localhost:8080/foo/bar Proto : HTTP/1.1 Method : GET URL : /foo/bar Host : localhost:8040
さらにconfig.json書き換えることで複数のパスを指定し、複数のプロセスを管理することもできる。
おお、簡単に動くじゃんと思ったが、機能としては現状ここまでらしく、hot reload がされなかったり(インターフェースがまだない?)unitをrestartするとconfigurationは全てpurgeしたり*2するなど全く実用段階ではないことがわかった。
所感
そもそもNGINX unitで何が嬉しいのかっていうと、今のところ言語間のインターフェースを吸収することでUnicornとかuwsgiを必要とせず、さらにアプリケーション内にデプロイ用のコードを個別に実装する必要がなくなるっていうのが強みにかなと思う。あとはHTTPで橋渡しができるのでそれがとにかく楽であった。 公式のKey Featuresを見る限りは動的なプロセス管理の対応や、サービスメッシュになっていくぞという宣言があるのでそこにも期待していきたい。所詮NGINX Application Platformの一機能としてのNGINX unitだが、unitのKey Featuresだけでも高機能なので、完動すればだいぶ心地の良いものになるんじゃないかと思っている。