blog.tawa.me

東京出身・埼玉育ち・福岡在住のWebエンジニアが得た知見や考えたことを言語化する場所。エンジニアリングと福岡とガジェットの話がきっと多め。

MENU

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

f:id:tawachan39:20190614185319j:plain

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を使った

github.com

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

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

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

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

f:id:tawachan39:20190614163527p:plain
色分けされるのでforegoで起動したほうがテンション上がる

まとめると

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

# メインアプリケーション
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つ)のアプリケーションが更新されるので、まだマシにはなる。ビルド時間もそんなに遅くはないので、この更新処理が保存時とかに走るようにしたらもっと楽になるんだろうか。