先日公開した Web API サービス Pixelaは、Google App Engine 上で Go Web Application として動いている。Go のバージョンには特に気を使わずに開発をしてたんだけど、GAE で Go の 1.11 がサポート(まだ β だけど)されたこと、そして Go 1.11 であれば GAE Standard Environment で System Package として imagemagick
が使えそう(svg → png 変換がしたい)ということもあって、Go 1.11 へのモチベーションが俄然上がったので、今回移行してみた。このエントリは、その際にやったことのまとめメモ。
Before
- Go 1.9.4
- パッケージ管理はなにもしてない状態(ひどい)
After
- Go 1.11.1
- パッケージ管理に Modules を使用
やったこと
goenv
の導入、Go 1.11.1 のインストール
これまではずっと開発機に直接 Go をセットアップしてたんだけど、もし今回の移行が難しくなりそうだったらいつでも Go のバージョンを切り替えられるようにしておきたいなと思ったので、まずはこれから。
$ brew install goenv
以下は ~/.bash_profile
などに追記。
export PATH="$HOME/.goenv/bin:$PATH" eval "$(goenv init -)"
そして、Go 1.11.1 のインストール。
$ goenv install 1.11.1 $ goenv global 1.11.1 $ goenv versions system * 1.11.1 (set by /Users/a-know/.goenv/version)
gcloud
のアップデート
$ gcloud components update
app.yaml
への変更
api_version
は deprecated とのこと。
init()
から main()
への書き換え
もともとは以下のようなコードを書いて置いていた。
1.11 からは init()
ではなくなるとのことなので、main()
に変更。
Modules の導入
まず最初に、環境変数へのセットが必要。
export GO111MODULE=on
そして初期化。
$ go mod init
なんかこれだけだと、中身がほぼ空の go.mod
ファイルができただけだったんだけど、ビルドとテストを実行したらそれっぽく設定できた。
$ go build $ go test -v -cover . $ cat go.mod module github.com/a-know/pixela require ( github.com/favclip/testerator v0.0.0-20180606025010-04c1c0fc2a5a github.com/go-chi/chi v3.3.3+incompatible github.com/google/uuid v1.0.0 github.com/pkg/errors v0.8.0 go.mercari.io/datastore v1.3.0 golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4 // indirect google.golang.org/api v0.0.0-20181026000445-511bab8e55de // indirect google.golang.org/appengine v1.2.0 )
appengine.Main()
の呼び出しの追加
ここまでの対応で動くかなと思ったんだけど、Datastore に読みにいくところで The process handling this request unexpectedly died. This is likely to cause a new process to be used for the next request to your application. (Error code 203)
というエラーになってしまっていた。
いろいろ調べたところ、結論としては google.golang.org/appengine
パッケージを使っている場合には main パッケージで appengine.Main()
を呼び出す必要があるようだった。
公式ドキュメントの Quick Start は最低限の構成すぎて、Datastore とかへのアクセスが無くこの呼び出しも省略されてしまっていた。。
これにより、アプリケーションがちゃんと動くようになったことを確認できた。
Go 1.11 への単純移行は簡単
結局、app.yaml やコードへのほんのちょっとの変更と、Modules の導入くらいで簡単に移行できてしまった。今のところ順調に動いている。
ただ、Migrating your App Engine app from Go 1.9 to Go 1.11 に We strongly recommend using the Google Cloud client library or third party libraries instead of the App Engine-specific APIs.
とあるけれど、今回これに対しては特になにもしておらず、引き続き google.golang.org/appengine
パッケージを使っている。
特に Datastore へのアクセス周りは Access Cloud Datastore through the datastore package.
とあるように、 datastore
パッケージを使うようにしなければいけないんだろうけど、ちょっとそれはまた別の機会にしっかり腰を据えて取り組んでみようと思っている(go.mercari.io/datastore
を使っているから、若干ラクだったりするかな......とか思ったりもしている)。
なので今回は本当に単純に、Go 1.11 ランタイムで動かすようにしました、という、それだけ。
追記(2018-10-30)
GAE/Go アプリケーションを Go 1.11 に移行するためにやったこと - えいのうにっきb.hatena.ne.jp
- [Go]
- [GAE]
僕は11/1以降に一回トライしてみる予定(試すだけ試して多分レスポンスが悪化するのでapplyはしない予定
2018/10/29 18:28
そう。移行をして数日経って、ダッシュボードを眺めていると、どうも微妙に効率が落ちている気はしていた。
たしかに、Go 1.11 にしてからちょっと効率悪くなった気もするんだよなー... pic.twitter.com/bmK1t6CRch
— a-know | Daisuke Inoue (@a_know) 2018年10月29日
スピンアップするインスタンス数も、普段より1,2台多いかんじ。僕は上述のとおり、System Package として imagemagick
が使えそうというメリットがあるためもう少し様子をみたいと思うけど、特にそういったメリットがない人は 1.11 への移行は少し様子を見てもいいかもしれない。
追記(2018-11-03)
今日、何気なくデプロイしようと思ったら、今まで出てなかったはずの ERROR: (gcloud.app.deploy) INVALID_ARGUMENT: script field for handler '/heartbeat' must be set to 'auto' for runtime go111.
というエラーが出てデプロイできなくなっていた。
適当にググっても特にこれといって情報は出てこなかったので、高度な勘を働かせ、app.yaml の以下の記述を、
- url: /heartbeat script: _go_app secure: always
以下のように変更することでデプロイできるようになった。
- url: /heartbeat script: auto secure: always
これがβリリースか......!ってなったけど、まぁ解決したのでよかった。
おまけ
無事 Go 1.11 でも動きそうだったので、production 環境の方も移行してみた。
— a-know | Daisuke Inoue (@a_know) 2018年10月27日
いきなり全差し替えはコワイので、全体の10%のトラフィックを 1.11 のバージョンに流す。こんなことも簡単にできちゃう、そう、GAEならね😎 pic.twitter.com/s2pPw8hOaY
便利。