チャプター1でウェブサイトの作り方を簡単に紹介
チャプター2でデプロイの方法を簡単に紹介
本チャプターで作成したサイトのコスト削減術を紹介。この記事で紹介した方法を応用する。
課金の無効化
- Googleの課金説明ページにアクセスし、「[アプリケーションの設定] に移動する」をクリックしてプロジェクト設定を開く。
- 設定画面の「アプリケーションの設定」タブ直下に編集ボタンがあるのでクリックする。
- 一日の利用料を 0 に設定する。
また、課金の予算とアラートを設定することを推奨する。
- 課金管理ページを開く
- 「請求先アカウントに移動する」をクリック
- 「予算とアラート」ページを開き、指定の金額にせまったときアラートメールを送信するようにように設定
インスタンスの上限を設定
app.yaml でインスタンスが最大でひとつだけ起動されるように設定する。
automatic_scaling:
max_instances: 1
max_idle_instances: 1
min_pending_latency: "3000ms"
コンテンツのキャッシング
半永久的に変わることのないファイルはキャッシングさせる。
default_expiration: "1h"
handlers:
- url: /css
static_dir: public/css
expiration: "7d"
- url: /js
static_dir: public/js
expiration: "7d"
- url: /img
static_dir: public/img
expiration: "7d"
- url: /fonts
static_dir: public/fonts
expiration: "7d"
なお、expiration
と default_expiration
エレメントは static
と static_dir
にしか適用できない。
例、以下ハンドラーにexpiration
を加えると gcloud app deploy
実行時エラーになる。
- url: /.*
script: _go_app
つまり、他のファイルは自分で main.go
内でキャッシングを設定しなければならない。
このサイトを参考に、自分の main.go にキャッシング機能を加えてみた。
package main
import (
"os"
"net/http"
"strings"
)
func init() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
etag := `"` + "<some etag string>" + `"`
w.Header().Set("Etag", etag)
w.Header().Set("Cache-Control", "max-age=3600")
if match := r.Header.Get("If-None-Match"); match != "" {
if strings.Contains(match, etag) {
w.WriteHeader(http.StatusNotModified)
return
}
}
if _, err := os.Stat("./public/" + r.URL.Path); os.IsNotExist(err) {
http.ServeFile(w, r, "./public/404.html")
} else {
http.ServeFile(w, r, "./public/" + r.URL.Path)
}
})
}
上記でデプロイし、リクエストを送信すると正常にCache-Controlヘッダーが返っていることを確認。
上記注意しなければならないのは、Etag (<some etag string>) の値。
コンテンツに変更を加え、デプロイするとき ETag が同じだとユーザーはキャッシュされたコンテンツを参照してしまい、新しいコンテンツを閲覧できない自体が発生する。
従い、gcloud app deployでアップロード前に、ETagの値を別のものに更新しておく。
自分は自動に値を更新したmain.goを作成するようにスクリプトを作成した。
また、上記の main.go には以下IF文があることにお気づきだろうか。
if _, err := os.Stat("./public/" + r.URL.Path); os.IsNotExist(err)
このIF文でユーザーが存在しないURLにアクセスしたとき、カスタムの 404 ページを表示するように定義している。
以上!