App Engine Go

# 自己紹介

[<img width="593" alt="スクリーンショット 2016-09-28 23.54.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/15818/b16c8a28-261e-d707-fc01-c07bf2dba05f.png">](https://twitter.com/k2wanko)

---


# App Engine とは

- Googleが提供するPaaS
- GoogleCloudPlatformの一つ
- 普通のWebサービスを作る上で必要なものが揃っている
- 対応言語: Python, Java, PHP, Go
- Snapchat や メルカリ アッテ が使っている
- Standard Environment と Flexible Environmentの２つある
- 今日は Standard Environment の話

---

# App Engine Architecture
![00_WebApp_ArchDiagram.png](https://qiita-image-store.s3.amazonaws.com/0/15818/62d10f12-cdf5-7477-c222-4a9478ed7436.png)


https://cloud.google.com/solutions/architecture/webapp

---

# App Engine を 使う理由

- インフラのめんどうを見る必要がない
- Googleと同じインフラを使える。(Google.comが落ちなければ落ちない)
- 突然のトラフィックもオートスケールで対応してくれる(※デフォルト設定なら)
- **豊富な無料枠がある** <- 重要

---

# App Engine の 辛いところ

- 外部との通信はAPIベース
- ローカルに書き込めない
- スケールを意識した書き方を強制させられる(そのおかげでできた時には負荷対策が完了)
- 好きなポートにListenできない
- などなど

--- 

# App Engine で Goを選ぶ理由

- スピンアップが40ms!!  Python,PHPも結構速い
- ピュアGoで書かれているライブラリなら**ほぼ**使える (Cとかsyscallとかunsafe使ってるとダメ)
- 他の言語はバージョンが低い python2.7, Java7, PHP5.5.34 (2016/9/28)
- Goなら1.6!!

---

# App Engine の 主なサービス

- Cloud Datastore - スキーマーのないオブジェクトデーターベース
- Cloud Storage - 1プロジェクト 5GBまで無料のストレージ 画像の保存などに
- Task Queue - TaskをQueueに入れて成功するまでリトライしてくれるサービス
- Search API - 全文検索エンジン
- [Edge Cache](http://qiita.com/sinmetal/items/37c105a098174fb6bf77) - 無料で使える静的コンテンツのキャッシュサーバ
- ほか、認証系のサービスやMemcachedやCronなどもある

---

# Hello World

---

# インストール

- Macならhomebrewで一発で入れられる

```
$ brew install app-engine-go-64
```

---

# app.yaml

```yaml
runtime: go
api_version: go1

handlers:
- url: /.*
  script: _go_app
```

---

# app.go

```go
package main

import (
	"fmt"
	"net/http"
)

func init() {
	http.HandleFunc("/", handle)
}

func handle(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello world")
}
```

---

# Dev Server

app.yamlがあるディレクトリで以下のコマンドを使う

```
$ goapp serve
```

http://localhost:8080/ に立ち上がる

---

# Deploy

以下のコマンドでデプロイできる

```
$ goapp deploy -application <projectID> -version 1
```

Cloud consoleにアクセスしてprojectIDを作る

---

# App Engine Tips

---

# App Engine Go では contextが大事

各種サービスを呼び出すのにcontextを要求する

```go
function handle(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	appID := appengine.AppID(ctx)
	log.Infof(ctx, "handle: appID %s", appID)
	fmt.Fprintf(w, "AppID %s", appID)
}
```

---

# 外部とHTTP通信するのもcontextが必要

```go
function handle(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	hc := urlfetch.Client(ctx)
	resp, err := hc.Get("https://example.com")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	io.Copy(w, resp.Body)
}
```

---

# 使いたいライブラリが App Engine で使えないパッケージを使ってた場合

forkしてBuild Constraintsでappengineを指定して処理を分けてPR!!

```go
// +build appengine

package hogehoge
```

App Engineで使いたいという熱い思いをこめてIssueを作っておくといいです。

---

# 個人的に App Engineでオススメのフレームワーク

[labstack/echo](https://github.com/labstack/echo)

contextをいい感じに包んでるので扱いやすいしパフォーマンスもいい

```go

e := echo.New()
e.Use(AppContext()) // . github.com/k2wanko/echo-appengine
e.GET("/", func(c echo.Context) error {
  return c.String(200, "AppID %s", appengine.AppID(c))
})
Init(e)

```

---

# まとめ

- 余程のことがなければクラウド死はないと思うので気軽に使おう
- App EngineはGoとWebの技術を試すのにいい遊び場
- App Engineの癖さえわかれば最高のプラットフォーム
- App Engineで足りないところはGCEなど他のサービスでなんとかなる！
- わからないことは 懇親会や[GCPUG](https://gcpug.jp/join) で聞いてください