飽き性の頭の中

Goで複数アプリケーション(メインアプリケーションとサイドカー)の開発環境を作ってみた

Goで複数アプリケーション(メインアプリケーションとサイドカー)の開発環境を作ってみた

tawachan
tawachan

1 つのプロジェクトで複数の Go アプリケーションをビルドするときの開発環境を自分なりに整えてみた。

手間は減ったにせよ、ホットリロードとかはできていないので、改善できそうなら教えて欲しい。

メインアプリケーションとサイドカー

イメージとしては、メインのサーバーがいてその補助として裏でジョブを実行するサブアプリケーションがいるような感じ。

Ruby でいえばsidekiqを使っていればこれに当たる。

『分散システムデザインパターン ―コンテナを使ったスケーラブルなサービスの設計』では、こういうのを、メインのアプリケーションに対して、サイドカーと呼ぶらしい。

今回は Go なので、goworkerというものを使っている。同じ Go のプロジェクトであっても、ビルドして吐き出したいバイナリは2つあることになる。さらにgoworkerはジョブの管理に Redis を裏で使うので、合計3つのアプリケーションを起動する必要がある。

それらを開発環境でいい感じに起動・再起動しないと開発したものを動かして確かめられない。その手間を少しでも楽にしようと整えた話。

フォルダ構成

Go の場合、ビルドの起点になるファイルは main パッケージにいる必要があるなのでメインのアプリケーションとサイドカーのビルドの起点となるファイルはどちらもメインパッケージにいなければならない

今回は次のようなイメージ

   ├── worker
│   └── main.go
└── main.go

こうすることで . 起点でビルドすればメインのアプリケーション、./worker 起点でビルドすればサイドカーが吐かれるはず。

両アプリケーションをビルドする

いちいちどちらもコマンドを叩くと大変なのでシェルにまとめた。

   ## メインアプリケーション
if [ -e hoge-main ]; then
    ## 既にバイナリがある場合は削除
    rm hoge-main
fi

echo 'メインアプリケーションをビルド中...'
go build -o hoge-main .

## サイドカー
if [ -e hoge-worker ]; then
  ## 既にバイナリがある場合は削除
  rm hoge-worker
fi

echo 'サイドカーをビルド中'
go build -o hoge-worker ./worker/

コマンドを叩くと次のような状態になるはず。

   ├── worker
│   └── main.go
├── main.go
├── hoge-main
└── hoge-worker

あとはこのバイナリと Redis を実行するだけとなる。

実行は forego を使った

バイナリと Redis の立ち上げにはforegoというものを使った。foreman in Goだとと公式にも書いてあるようにforemanの Go バージョンである。

Procfileを書くだけなのでとても簡単。

   main: ./hoge-main
worker: ./hoge-worker
redis: redis-server

しかもforegoでやっておくと、各々自前で起動するのと違って、各アプリケーションごとに色分けされてログが出るのでとても見やすい。

../../../assets/20190614163527.png

まとめると

これら一連の処理をシェルスクリプトにまとめるとこうなる。

   ## メインアプリケーション
if [ -e hoge-main ]; then
    ## 既にバイナリがある場合は削除
    rm hoge-main
fi

echo 'メインアプリケーションをビルド中...'
go build -o hoge-main .

## サイドカー
if [ -e hoge-worker ]; then
  ## 既にバイナリがある場合は削除
  rm hoge-worker
fi

echo 'サイドカーをビルド中'
go build -o hoge-worker ./worker/

## バイナリとredisの立ち上げ
forego start

Go のプログラムを書き換えて起動し直すときは、一度ctrl + cで落としてから、再度スクリプトを実行すれば更新できる。

少し手間ではあるが、これで 2 つ(Redis 入れて一応 3 つ)のアプリケーションが更新されるので、まだマシにはなる。ビルド時間もそんなに遅くはないので、この更新処理が保存時とかに走るようにしたらもっと楽になるんだろうか。

関連記事