LoginSignup
11

More than 5 years have passed since last update.

GoのtestをGKEで分散実行する

Posted at

前置き

Goのプロジェクトも大きくなってくると、go testに時間がかかってくる様になりますよね〜

私の愛してやまないGAE/Goの場合は特に、テストケースの度にpythonのローカルサーバープロセスが起動する為、バカにならない時間がかかります。

そこで金の弾丸に物を言わせて、Google Container Engine(GKE)でcoreたくさんぶん回してテストを並列実行してみたらどうだろうか、と思い立ち、実験してみました。

GKEのセットアップは↓をほぼそのまま参考にさせてもらいました。とても簡単にできました\(^o^)/
GKE を使って golang アプリケーションコンテナを稼働させる

※ 今回はGKEから外向きにポートは開かないので、Serviceの設定は不要です

概要

用意した資材はこちら。
https://github.com/knightso/honeybee

とりあえず実験目的でかなりテキトーに作った状態なので、今回は詳しいsetup手順は割愛して処理の概要だけ紹介します。
(↑の資材リポジトリに必要なコードは揃ってるので興味のある人はどうぞ)

処理の流れ

クライアント(hb-client)

1. ローカルのgoファイルを解析して、テスト対象のパッケージ&関数のリストを作成

テスト対象のパッケージとファイル名の抽出は手抜きをしてgo list(実際にはgbを使っているのでgb list)を利用しました。

$ go list -f '{{.ImportPath}}:{{.Dir}}:{{range .TestGoFiles}}{{.}},{{end}}{{range .XTestGoFiles}}{{.}},{{end}}' ./...

これで、
importパス:ディレクトリ:hoge_test.go,fuga_test.go,piyo_test.go,...略...
みたいなレコードのリストが出力されます(便利ですね!)。

それを標準入力で受け取り、各ファイルのASTを解析し、テスト関数名を抽出しています。

コード

2. テスト関数毎にリクエストを作成し、GAEのTaskQueue(PULL)に送信

1で解析した情報をもとにリクエストパラメータを作成し、Google Client Libraryを利用してGAEのTaskQueue(PULL)に送信します。

リクエストパラメータ
UUID
github commit番号
パッケージ
ファイル名
テスト関数名

コード

※ 今回メッセージのやりとりにGAEのTaskQueueのみを利用しました。GAEアプリ自体は使用していません。

コンテナ(hb)

1. Taskqueueからリクエストを一件Lease

クライアントが送信したリクエストをTaskQueueから取り出します。
コード

Lease関数で取り出した後はDeleteする必要があります。
コード

2. githubの指定されたcommitをcheckout

ある時点までのレポジトリはdocker build時にイメージ内に、あらかじめcloneしておきます。

コンテナでは、リクエストで指定されたcommit番号でgit checkoutします。
コード

ただ・・差分のみの取得とはいえ大量のコンテナから集中してgit checkoutするのはどうなんだろう?との懸念から現在は一旦処理をコメントアウトしてます。

3. テスト関数を指定してテスト実行

カレントディレクトリにtest.shというスクリプトを用意しておくとキックする仕組みにしました。
サンプルコード

サンプルではgbを利用していますが、go testでもいけます。

4. テスト結果をTaskQueue(PULL)に送信

テスト結果を結果用TaskQueueに送信します。
コード

送信する際に、Tagにクライアントから送られてきたUUIDを指定しています。こうすることでクライアントは自分の送信したUUIDに紐づく結果のみをLeaseすることが出来ます。

5. ログとしてCloud Datastoreにも保存

コード

再度クライアント(hb-client)

1. TaskQueueの結果リストを監視(UUIDでタグを指定してLease)

TagにUUIDを指定して、TaskQueueからLeaseしています。
コード

2. 送信したリクエストの数だけ結果が返ってきたらレポート出力して終了

結果

手元の開発中プロジェクトでテストしました。

まずはローカルで普通にgo test

テストケース数 実行時間
320 約1,000秒

たった320件で1000秒って時間かかりすぎだろ!ってカンジですが、GAE/Goのaetestだとこんなカンジです。

↓↓

GKEクラスターで分散実行!

core数 pod数 実行時間
320 320 約80秒

10倍以上速くなった! \(^o^)/

と一瞬喜んでみましたが、coreが320倍になったのに実行時間はたったの10倍ってちょっとひどいですね(^^;

まあ完全並列実行しても一番長いテストケースの実行時間に集約されてしてしまうので、仕方ない面もありますが・・・費用対効果考えるとかなり微妙ですね。。

・・・という訳で軽く玉砕した感がありますが、せっかくなので記事にさせてくださいm(_ _)m

今回作成したコードは、もうちょっと実用性が上がってツールとしての体裁が整ったら改めて紹介したいな、と思っています。

ではでは、良いお年を〜

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
11