2014年5月25日日曜日

Golang Cafe #30を開催しました。

Golang Cafe #30を開催しました。

今回はGoのプレゼンテーションツールのpresentの使い方を紹介して頂いた後、Dockerのソースコードを読み進めるという内容になりました。

Goのプレゼンテーションツールであるpresentの使い方は+Takanobu Haginoさんが事前に調べてくれていたので、その結果から使い方を説明していただきました。
インストール方法は、まず、go getを使ってソースコードをダウンロードします。ダウンロード後、go installでコマンドができあがるので準備完了です。

$ go get code.google.com/p/go.tools/cmd/present
$ cd src/code.google.com/p/go.tools/cmd/present
$ go install

その後、プレゼンテーション用のファイルを作成(中身はテキストファイル、フォーマットはmarkdown風)して

$ $GOPATH/bin/present

とするだけで、ローカルにWebサーバが起動しプレゼンテーションを参照する事ができます。このプレゼンテーションツールはプレゼンを表示した状態で、Goのプログラムを動かす事ができるので、いちいち画面を切り替えなくても良いという点では非常に便利です。

ただし、PowerPointとか、Google Presentationのような柔軟な配置が難しいので、凝ったプレゼン資料が作りにくいのも確かです。

後半は、Dockerのソースコードを読み進めました。
今回は、docker versionと、docker runコマンドの2つを読み進めました。
結局、クライアント側を読んだ結果、プロセス通信とHTTPのプロトコルの組み合わせの通信をしているということがわかったので、サーバ側も、各コマンドがリクエストURLから分析した結果から実行する処理が決まるというものでした。

あまり、新しい成果が生まれなかった(Engine構造体とJob構造体がキモというのが変わらない)のと、Docker自体がかなりのペースでMergeとCommitが加わっているので
現状のソースコードを読むことに意味を成さなくなる可能性がでてきました。
(最新のものと比べてかなりの乖離がある)

ということで、最新ソースを追いかけながら読み進める事をすると、Dockerの勉強会になりそうだという判断もあって、次回はGoの資料を読み進める事になりました。

個人的に、ですが、Dockerのソースコードは読みにくい…。と思います。
でも、いい経験になったと個人的に思っているので、人のソースコードを読むのは
間違いじゃないと思います。

最近、Golang Cafe直前になってBlogを書いているので、少し改善したい今日この頃。


2014年5月17日土曜日

Golang Cafe #29を開催しました。

Golang Cafe #29を開催しました。

今回は、#27に引き続き、dockerのソースコードを読み進めました。

前回は、deamon側に向かって、リクエストを飛ばすクライアント側のソースコードを読みましたので、docker/docker.goの98行目から開始しました。
(-d、-deamonオプションを付けた場合に動作する部分)

dockerにはHandlerという内部コマンド(?)があって、最初にHandlerを実行するための準備をします。(builtins/builtins.go)内部コマンドはコマンドの名前(例:initserverなど)をキーにして実行する関数を保持するmapとして定義されていて、各処理の時に、名前を指定して呼び出します。
最初は、"initserver"、"init_networkdriver"、"serveapi"の3つが登録されています。

initserverの中で、クライアントからのリクエストに対するHandlerが登録されます。

ただ、読み方としてコツがあって、以前にもでてきた、「goroutinesの切り替わり」を考えて処理の順番を考えないといけません。

したがって、登録したHandlerの順番としては、最初に"serveapi"が実行されます。これは、docker.goの133行目付近はgoroutineになっていますので、バックグラウンドで動くことになります。よって、先にdocker.goの179行目にある、job.Run()が実行されることになります。docker.goを見る限りでは、runtime.GOMAXPROCS()を呼び出していませんのでMAXPROCSは1で動作していますから、「明示的なスレッドのブロック」が無い限りは"serveapi"が動作すると思われます。(ということは、runtime.GOMAXPROCS()を呼び出すとまともに動作しないのかも…?)

job.Run()の中では、登録されているHandlerを呼び出すので、初見では、何かの関数か?と思うかもしれませんが、関数型のmapの関数を呼び出すような仕組みなので、呼び出しの部分は勘違いしないようにしなければいけないと思います。

以前のクライアントからUnixソケットを使って接続するようになっていましたが、docker.goの155行目でacceptconnectionsが実行されています。
(中で、net.DialUnix()されています。(Unixソケットってサーバ、クライアントどちらもDialなのか…?))

正直、dockerのソースコードは読みづらい…。俺だけか?

次回は、各コマンドの内部を読み解いていく予定です。

2014年5月11日日曜日

Golang Cafe #28を開催しました。

Golang Cafe #28を開催しました。

今回は前回に引き続き、dockerのソースコードを読もうと思っていたのですが、東京から返ってきた、+Shingo Ishimuraさんの「デプロイツールをGoで」というお題がでて、その検証をしていました。

結局、os/execパッケージのCommandを使って、標準入力と標準出力を取得する。というのがポイントになります。これは、以前のGolang Cafeでもやりました。
ということで、自身満々に

と、言ったのですが、単純なコードだとうまくいくソースコードは書けたのですが、実際にはどうなんだろうか。(業務に係わるものだったので、直接見たわけではないので…)

作成したソースコードはgithubにありますのでごらんください。

今回は、os/execパッケージが主な機能だったので、golangcafeのexecsampleディレクトリに含めてあります。exec.Commandを使うときの参考までに。

それから、その後、今回の内容を活かして、aetesthelperというツールを作ってみました。これは、GAE/Gのgoapp testをサポートするコマンドです。

公式サイトの通りに、goapp testを行えば良いのですが、どうしても、パッケージを分けて、別のパッケージを参照する時に、GOPATH変数を参照して、GOPATH変数で設定したパスの上にファイルがないとテストが動作しない(私だけ?)ので、仕方なく、Tempdir()で作った、ディレクトリにSetenv()して、ファイルを全てコピーして、goapp testを流すという単純な動作にしています。
これで、プロジェクト内の全てのパッケージに対してgoapp testが実行できるので、非常に快適になりました。

次回(と言っても、あと3時間後ですが)は、先々週に引き続いてdockerのdaemon側のソースコードを読みます。