AppEngineのGo1.11のランタイムを簡単に試してみた

GAE/Go1.11のランタイムを実際にデプロイまでしてみましたよっていう内容です。

準備

ディレクトリ構成

以下のようなディレクトリ構成でプロジェクトを作成しました。

$GOPATH
└── src
    ├── app
    │   ├── app.yaml
    │   └── main.go
    └── handler
        ├── index.go
        └── init.go

server準備

GAE/Go1.11からは標準の net/http パッケージが使えますので、http.ListenAndServe で簡単なweb server を書きます。

routerの実装

// app/main.go

import (
    "fmt"
    "log"
    "net/http"
    "os"

    "handler"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", handler.Index)

    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
        log.Printf("Defaulting to port %s", port)
    }

    if err := http.ListenAndServe(fmt.Sprintf(":%s", port), mux); err != nil {
        panic(err)
    }
}

※ main.goでportを環境変数から取り出してますが、この PORT はAppEngineのデフォルトで指定されてるものなのでこのまま使えます。

handlerの実装

// handler/index.go

// Index ...
func Index(w http.ResponseWriter,r *http.Request){

    if r.URL.Path != "/" {
        http.NotFound(w,r)
        return
    }

    w.WriteHeader(http.StatusOK)
    if _, err := w.Write([]byte("hello appengine go1.11 world!!!")); err != nil {
        http.Error(w, "Internal Server Error", http.StatusInternalServerError)
        return
    }
}

local で起動

goapp serve app.yaml が使えなくなっていたので、gcloud component の中に入ってくる dev_appserver.py を使います。
※ 事前に dev_appserver.py を gcloud コマンドでinstall -> pathを通しておくといいです。

$ dev_appserver.py src/app/app.yaml

INFO     2018-10-28 11:25:04,061 devappserver2.py:278] Skipping SDK update check.
INFO     2018-10-28 11:25:04,213 api_server.py:275] Starting API server at: http://localhost:64860
INFO     2018-10-28 11:25:04,281 dispatcher.py:270] Starting module "default" running at: http://localhost:8080
INFO     2018-10-28 11:25:04,283 admin_server.py:152] Starting admin server at: http://localhost:8000

local packageの初期化

main package以外の各パッケージも main で初期化するものかと思ってましたが、init で初期化できました。
各packegeで初期化時に行いたい処理を各場合は init に書けば良さそうです。

// handler/init.go

func init(){
  // sample的に log とconsoleに出力させる。
    log.Printf("init")
}

Deploy

appcfg およびそのラッパーコマンドである goapp が使えなくなり gcloud app deploy のみしか使えなくなっていますのでこちらのコマンドでデプロイを行います。

事前にdeploy対象のプロジェクトにログインをしておきます。

$ gcloud auth login

Deploy準備

デプロイ前に以下のファイルを設定します。

  • setting app.yaml
  • setting .gcloudignore

setting app.yaml

app.yaml Configuration File  |  App Engine standard environment for Go 1.11 docs  |  Google Cloud を参考にするといいです。

基本はruntimeとservice名だけ入れておくとdeploy時に自動でどのサービスにデプロイするのか解釈してくれるので便利です。

runtime: go111
service: YOUR-SERVICE-NAME

setting .gcloudignore

gcloud app deploy を使う場合、従来の skip_files は使えず、deploy時にアップロードしたくないファイル群は .gcloudignore ファイルを使って管理します。

Deploy

$ gcloud app deploy --project [YOUR_PROJETCT_ID] --version [VESRION_NAME]
Services to deploy:

descriptor:      [~/emahiro/path/gae_go111_app/src/app/app.yaml]
source:          [~/emahiro/pagh/gae_go111_app/src/app]
target project:  [dena-opfsys-gcp]
target service:  [gae-go111-app]
target version:  [VESRION_NAME]
target url:      [https://gae-go111-app-[YOUR_PROJETCT_ID].appspot.com]

Do you want to continue (Y/n)?  Y

Beginning deployment of service [gae-go111-app]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 1 file to Google Cloud Storage                 ═╣
╚════════════════════════════════════════════════════════════╝

# 略

deployはmoduleで変更があった場合などアップロードする対象が増える、差分アップロードっぽいです。

まとめ

とりあえず起動してdeployするところまでざっくり試してみました。
loggingやdatastoreあたりのライブラリの動作を検証してみようと思います。特に cloud.golang.org/appengine のpackageが使えなくなるのでその代替となる golang.google.com/go あたりを使うところは確認してみたいです。
また、実際にどうライブラリをinstallしてpackageを取り込んでくれるのか、go.modあたりも使ってみようと思います。