AppEngine for Go でのVendoring

GAE/GoでVedoringの設定をしてみました。

2016/11/23

GAE/Go 皆さん使っていますか?やっぱりGAE使うならGoですね!
Goの1.6から正式にvendoringが使えるようになりましたが、どうも僕が使っていた今までの構成だと上手く行かなかったんですよね。
今回、やっと実用性のありそうな構成にたどり着いたので書いてみました。

GAE/Goのパッケージ構成

以下がVendoringが機能した際のパッケージ構成になります。

root (GOPATH)
└── src
    ├── mypackage
    │   ├── handler.go
    │   ├── model.go
    │   …
    │
    ├── static
    │   ├── css
    │   ├── js
    │   …
    │
    ├── vendor
    │   ├── google.golang.com
    │   …
    │
    ├── app.yaml
    ├── glide.yaml
    └── index.yaml

mypackage

ポイントは、mypackageの場所でしょうか。
僕は、今までsrcの下に直接 *.go を置いていたのですが、パッケージを作らないとvendorディレクトリを認識してくれませんでした。

GOPATHの設定

GAE/Goは、 syscall などGAEでは使えない機能があります。プロジェクト内に外部のライブラリを入れてしまうと、これらも含めてコンパイルされてしまい動きませんでした。その為、GOPATHは、プロジェクトの外に設定することが多くありました。

今回、Vendoringが使えるようになることで、外部にGOPATHを設定する必要がなく、プロジェクトルートのみの設定で対応が可能となりました。

パッケージ管理ツール(Glide)

vendorディレクトリを認識できるようになったのですが、vendorディレクトリに go get をするとgitなどのリポジトリになってしまい、pkgディレクトリとか、binディレクトリも出来てしまったりと色々困ります。そこで、パッケージ管理ツールの出番になります。

今回は、Glide を利用しました。使い方は、今回は割愛させて頂きます。

今回使ったコマンドは、

glide create

glide update

の2つのみでした。

app.yamlの設定追加(これ重要!)

GAEの設定ファイルである、app.yamlに以下を追加する必要があります。

nobuild_files:
- vendor

skip_files:
- vendor/.*$

nobuild_files

vendorディレクトリを作って、Vendoringが可能になっても、残念ながらvendorディレクトリ以下もコンパイル対象になってしまいます。これに対応するために、 nobuild_files の設定を追加してビルド対象から外します。

skip_files

nobuild_files を入れればビルドは出来て問題なく動くようです。
しかし、appengineのプロダクション環境のコンソールでサイズを見ると、異常に大きくなっています。どうやら、deployする際、vendor以下も上がってしまうようです。
skip_files の設定を入れることで、vendor以下のファイルをアップロードしなくなります。

最後に

実際に集中して対応する時間が取れていませんでしたが、初心者向けに色々とGAEを触るきっかけ作りをしたいなと思いながら、簡単な構成がないかを考えていたところでたどり着きました。
僕が主催している タネマキGAE の中で色々と試しながらでした。

自分で作るアプリは、しばらくはこの構成でやっていきたいと思います。

GAEに関して、何か質問や相談などありましたら、こちらの問合せフォームからご連絡下さい。
FreeGufo 問い合わせフォーム

By nuki_pon

Google Compute Engineのインスタンスの操作

GAEから、GCEのインスタンスを操作するためにCompute Engine APIを使ってみました。

2016/6/10

GCEのインスタンスは、分単位での課金であり、起動の時間も短くとても扱いやすいインスタンスです。
それが故に、手軽にStart,Stopをしたくなります。

当然、GoogleさんもWeb、CLI、スマホアプリなど色々な方法を提供してくれていますので、基本的にはそれで事は足ります。
でもね。やっぱり自分で操作したいこともあるじゃないですか。
というわけで、エンジニアとしては初級レベルの僕が試せた部分だけ紹介しますね。

Githubで公開してみました

ちなみに、GAEのスペシャリストsinmetalさんがMinecraftのために作ったライブラリがとても参考になります。
僕が使ったもの以上の事をたくさんされているので、本格的に使う方はこちらを参考にされるといいと思います。

GCEを操作するためには

Google Compute Engineを操作するために、 Compute Engine API が用意されています。
これを、Golangで扱うためもライブラリも公開されています。

実際にライブラリの中身を見て頂けると分かるのですが、色々な事が出来すぎて見ているだけで気持ち悪くなります。(少なくとも僕は。。)

というわけで、今回触った部分だけをかい摘んで書いてみたいと思います。

なにはともあれ、ライブラリをimport

ライブラリのインポート、APIライブラリを使う上での認証をするために、oauth2などのライブラリもインポートしています。
その他、必要なパッケージをインポートして下さい。

import (
    compute "google.golang.org/api/compute/v1"
    "golang.org/x/net/context"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
)

computeをエイリアスを書いておくと、VSCodeでソースを認識してくれるので便利でした。
context,oauth2,googleの3つは、次の項目でAppEngineのClientを作成する際に使用しています。

ComputeServiceを作る

操作を始める上では、GCEを操作するためのServiceを作ります。
instanceだけでなく、zoneやnetworkなど様々な操作をする為の基本となるServiceです。
ポイントは、clientを作る際に「AppEngineTokenSource」を使うことですね。これを使うと特別な認証が不要になるのでとても簡単になります。

client := &http.Client{
    Transport: &oauth2.Transport{
        Source: google.AppEngineTokenSource(ctx, compute.ComputeScope),
        Base:   &urlfetch.Transport{Context: ctx},
    },
}
s, err := compute.New(client)

zoneのリストを取得する

instanceは、zoneを指定して取得することになりますので、まずはzoneを取得します。

zs := compute.NewZonesService(s)
zoneList, err := zs.List(project).Do()

取得したzoneのリストをfor文で回しながらinstanceのリストを取得します。

instanceのリストを取得する

instanceのリストを取得します。

is := compute.NewInstancesService(s)
insList, err := is.List(project, zone.Name).Do()

External IPを取得する。

ここ一番苦労したところです!

External IPは、instanceの奥の方に入っています。
instanceのリスト(insList)をfor文で回しながら、instance(ins)を取り出し、その中の情報を掘り起こします。
AccessConfigのNatIPが、External IPになります。

natIp := ins.NetworkInterfaces[0].AccessConfigs[0].NatIP

instanceに入っていると思ってはいたのですが、NetworkInterfaces>AccessConfigs>NatIPにたどり着くのに時間がかかりました。
それらは、リストになっているのですが、良くわからないので、とりあえず一つ目を取得しています。。

インスタンスを起動、停止する

インスタンスの起動、停止は、instanceが取得できていれば簡単です。

起動

ope, err = is.Start(project, zone, instance).Do()

停止

ope, err = is.Stop(project, zone, instance).Do()

ちなみに、projectIDは、appengineパッケージをimportして、以下で取得が可能です。

projectID := appengine.AppID(ctx)

最後に

各種メソッドだけを抜粋してみました。
今回は、GAEからGCEのinstanceを起動、停止する機能を作ってみました。

By nuki_pon

AppEngineで静的コンテンツ配信用テンプレート

AppEngineで静的コンテンツ配信用テンプレートを作りました。

2016/4/16

Google App Engine(GAE)は、Python、Java、Go、PHPでWebアプリケーションが作れるPaaSのサービスです。
実は、静的コンテンツを配信する為のサーバーとしてもとても強力なサーバーになります。

GAEで静的コンテンツを配信する上での予備知識

以下の特徴を知っていると理解しやすいかと思います。

  • PaaS
  • リクエストがきたら上がって、その分だけの課金
  • オートスケール
  • Static Server(インスタンス使わない)
  • エッジキャッシュ

以下で、簡単に各機能を紹介したいと思います。

PaaS

Platform as a Service です。
世の中でクラウドという言葉がバズワードになってだいぶ経ちますが、PaaSはやっと実用段階になってきている感はありますね。
GAEは、Googleがクラウドサービスとして一般に提供し始めた最初のサービスとも言えるサービスです。
正確には、GmailなどSaaSにあたるサービスはそれ以前からありましたが、自分のサービスを提供できるプラットフォームとしては、かなり早い段階で出ています。

一般によく使われているApacheなどのWebサーバーなどを既によういしてあり、ユーザ側はHTMLなどを用意してデプロイ(サーバーへのアップロード)をするだけで、世界に発信できる様になります。

リクエストがきたら上がって、その分だけの課金

GAEは、通常はinstanceが落ちている状態になります。
リクエストを受けてからinstanceを立ち上げて、リクエストを処理します。instanceを立ち上げるのを「spin up」落とすのを「spin down」と言っています。
GAEは、このspin upが異常に早いために、無駄なリソースを利用せずに課金額が抑えることが可能となっています。
これを実現するために、ある程度の制限が入っていますが、静的コンテンツを配信する上では、影響の出る制限はありません。

オートスケール

オートスケールは、このspin upが早いことで通常のシステムでは考えられない様なスケールをすることが可能となっています。
GAEでは、アクセスが多くなって一つのインスタンスでは捌ききれなくなると、自動でインスタンスを上げて処理をしてくれます。
後述しますが、静的コンテンツの配信では、オートスケールの機能を使う必要もありません。

Static Server(インスタンス使わない)

GAEは、Python,Java,Golang,PHPでアプリケーション開発が可能となっていますが、これらのアプリケーションを実行するためのアプリケーションサーバーが用意されています。これらを動かすと課金対象となります。
(無料枠もあるし、アクセスがあまり多くなければほぼ無料で運用が可能です)

これに対して、html,css,js,image,fontなどの静的コンテンツは、Static Serverからの配信が可能です。
こちらは、インスタンを立ち上げることもないため、課金対象にもなりません。
静的コンテンツだけの配信は、このサーバーのみを利用することが可能となります。
※アクセス数が多くなると、ネットワーク料金が多少かかることは有ります。

Googleの強力なインフラを利用しているため、アクセスの急激な増加も気にする必要はありません。

エッジキャッシュ

Googleのネットワークは、各国にそれぞれのGoogleのネットワークへの入り口が用意されています。GmailなどのGoogleのサービスを利用する際に、その入口のところでキャッシュされているものを返す機能があります。
利用者に近いところでキャッシュされているため、レスポンスがとても早くなります。

クライアントキャッシュを利用する際に、レスポンスのheaderにキャッシュの設定をすると思いますが、それを設定しているとエッジキャシュに乗ることがあります。ベストエフォートとなっているため、利用者側での制御はできず、Google側が独自のルールにより判断してキャッシュに乗せているそうです。

GAEを使った静的コンテンツの配信のメリットまとめ

  • GAEが備えているStatic Searverを使うことで、課金対象にもならない。
  • Googleの強力なインフラを利用できるため、急激なアクセス増加(いわゆるWBS砲など)も気にする必要がない。
  • 場合によっては、強力なキャッシュが利用可能。

各行政ので、災害時のHPなど通常はほとんどアクセスがなく、発生時に急激なアクセスが見込まれる様なページにも最適だと思います。

テンプレートについて

普段GAEを使っている側からすると、静的コンテンツにGAEを使わない理由がないくらいなのですが、AppEngine SDKの導入、GAEの設定ファイルのapp.yamlなど記載方法を覚えることもあり、敷居が高くなるのではないかと思います。
そこで、簡単にお試し頂けるようなテンプレートを作ってみました。

こちらでGithubのリポジトリを公開しています。

こちらのREADME、および、ここからもリンクしている以下のリンクでapp.yamlなど記載方法等を解説しています。

最後に

この内容は、GCPUG Shonan feat.GAE vol.2 向けに作成しました。
イベントでは、この内容を説明し実際に触って頂きました。

今回は、個人的な趣味もあり、一部(NotFoundの場合の処理)Golangを入れています。
Pythonの方が、GoogleAppEngineLauncherが使えるようになるため、ターミナル等を利用する部分が減ってさらに敷居が低くなるように思いました。
今後、Python用もつくろうかなー。

GAEに関して、何か質問や相談などありましたら、こちらの問合せフォームからご連絡下さい。
FreeGufo 問い合わせフォーム

By nuki_pon

AppEngineを始めたけど悩んでいる方向け

質問を受けたので、まとめてみます。

2016/3/16

FreeGufoのHPには、問合せフォームを用意しています。GAEで自作した問い合わせフォームです。

色々なことを細々とやっているので、せっかくの問合せフォームも使われることは殆どないのですが、この度技術サポートのご依頼をいただきました。
ご依頼と言っても、Google App Engineを触り始めたけど、良くわからない!という質問です。もちろん、Google App Engineを触りたい、教えて欲しいと言われて、無下には出来ませんよね。

たまたま、Macを開いていたタイミングだったのと、問合せフォームからGAEの質問を受けるなんて考えてもいなかったので早速返信してみました。
とりあえず、ある程度問題は解決したようです。

折角なので、やり取りした中で初心者がぶつかりそうな内容をまとめてみました。

GCPとGAEについて

そもそも、Google Cloud Pratform(GCP)とGoogle App Engine(GAE)の違いがわからないとのことでした。

GCPは、プラットフォーム全体の総称

GCPは、Googleが提供しているクラウドサービスの総称になります。
AWSを知っている人は多いと思いますが、AWSのGoogle版といったところでしょうか。
詳細は、公式サイトを参照して下さい。

cloud.google.com/

GAEは、GCPの中の1サービス

GAEは、このGCPの中の1サービスになります。

GAEは、Googleがクラウドサービスを提供し始めた最初のサービスになっており、GCPが出来る前から存在していました。そのためか、多少情報が混乱することがあるような気がします。

GCPの代表的なサービスを挙げると

無理に3文字にするのも厳しいですよね。しかも基本的には Google で始まるので、実質2文字。。一応代表的なものを挙げるとこんな感じです。

GAEGoogle App EnginePaaS
GCEGoogle Compute EngineIaaS
GCSGoogle Cloud StorageStorage

Googleらしいサービスとして、BigQueryが話題になることが多くなりましたがこちらは、BigQueryと呼んでいます。流石に、最近出てきているサービスは3文字にはしなくなってきた気がします。

GCP、GAEに関する用語について

出てくる用語でも混乱していたようです。

「Project ID」 と 「Aplication ID」について

プロジェクト名、プロジェクトID、アプリケーション名、アプリケーションIDなどの用語が出てきます。

これらの違いがわからないようでした。

GAEとGCPの成り立ちから、言い方が混在しているのが大きな問題でしょう。基本的には、

プロジェクト名=アプリケーション名
プロジェクトID=アプリケーションID

と考えていいと思います。

GCPが出来る前のGAEだけが提供されていた頃は、 アプリケーション名、アプリケーションIDと呼んでいました。
GCPになって、他サービスでも同一のIDを使用していることから、プロジェクトIDという言い方になっています。

プロジェクト名とプロジェクトIDの関係は、少し気をつける必要があります。

プロジェクト名:自分のプロジェクト内での識別名
プロジェクトID:他のユーザも含めたGCP全体で一意となるID

となります。

このため、プロジェクト名とIDは、同じものにすることもできますが、他のユーザがプロジェクトIDを使っている場合には使用できません。

GAEのapp.yaml等で指定する、「application」には、このGCPのプロジェクトIDを指定します。

以下、 app.yaml のサンプルですが、最初に記載する application には、プロジェクトIDを入力する必要があるということになります。

application: myapp
version: 1
runtime: python27
api_version: 1
threadsafe: true

AppEngine SDK と Cloud SDKについて

GCPは、開発マシンからコマンドラインで操作できるようにするための「Google Cloud SDK」というものが用意されています。

これ一つで、GCPのほとんどのサービスを(奥の方まで)操作することが出来ます。

ただ、なぜか App Engine に関しては、別になっています。(一時期は、含まれていたのですが2015年夏に分離されました。)

「Google App Engine SDK」は、こちらです。Python、Java、PHP、Golangそれぞれ様に分かれています。

Mac OSXのPython、PHPだけは「Google App Engine Launcher」というGUIのアプリケーションになっています。

ちなみに、AppEngineの中で、_Managed_VM_ というサービスがありますが、そちらに関しては「Google Cloud SDK」を使うことになります。

この辺りは、かなりややこしい感じになっていますね。

開発サーバーについて

App Engineは、PaaSのサービスで、一般にレンタルサーバーやIaaSのサービスとは違ったインフラが提供されています。

このため、ローカル開発にはプロダクト環境を再現した専用のサービスが必要になります。

「Google App Engine SDK」には、これを開発マシンで再現してくれるサーバーが含まれています。

Pythonのlauncherを使う場合は、こちらのボタンを押すだけです。

コマンドラインだと以下のコマンドで実行します。

Python: dev_appserver.py
Golang: goapp serve

各パラメータ等は、コマンドのヘルプなどでご確認下さい。とても良く出来ていて、App Engineを使う場合は必ずお世話になると思います。

Javaは、使っていた時期はあるのですが最近は全く触っていないので、良く分かりませんw

Deployについて

Deployも「Google App Engine SDK」に含まれているコマンドを使います。

基本的には、app.yamlに記載されているapplicationにdeployすることになります。

Pythonのlauncherを使う場合は、こちらのボタンを押すだけです。

コマンドラインだと以下のコマンドで実行します。

Python: appcfg.py update
Golang: goapp serve

こちらも、パラメータ等は、コマンドのヘルプなどでご確認下さい。

最後に

今回、質問を受けたことを中心に書いてみました。

Cloud Repository、Cloud Shellについても質問が及んだのですが、そちらは整理が出来たらということで。

何かありましたら、こちらのお問合せフォームからお気軽にどうぞ。

By nuki_pon

GCPUG Shonan feat.GAE Vol.1 その3

GCPUG ShonanでGAEシリーズの1回目が開催されました。その3 Datastoreを書きました。

2016/3/5

個人的な話になりますが、GCPUG Shonanの管理者をやらせて頂いています。
今回は、Google App Engine シリーズの1回目ということで、茅ヶ崎で開催しました。

3つのセッションの内、3つ目を書いてみたいと思います。

3本目のセッションは、Datastoreについてでした。

Google App Engineを本格的に使うには、Datastoreは、欠かせません。

そして、最初に躓くところでもありますよね。特に、RDBが得意な方ほどハマりどころが多いと言う困ったものです。ただ、GAEのオートスケールの凄さを支えているものでもあります。

登壇者

@sinmetalさん です。

CP300という、GoogleがGCPを広めるために作った資格があるのですが、そちらの日本で唯一の講師をされています。

既に、GCP全体の人になってしまっていますが、そもそもはGAEのスペシャリストです。色々なところで、GAE愛を感じています。

もともとは、Javaをガッツリ使っていたそうですが、最近はGolangの割合が増えてきているようです。

そんな、GAEを知り尽くしている@sinmetal さんには、GAEの最初の鬼門ともいうべきDatastoreについてお話をして頂きました。

スライド

スライドは、こちらです。

かなり盛りだくさんです。

Datastoreだけでも1冊の本が出来るくらいの内容になっています。また、CP300では、Datastore全体で3時間程度はかかるそうです。

その内容を1時間という短い時間に詰め込んだスペシャル版ですね。

内容について

かなり濃い内容で、要約することは難しいので、僕が印象に残ったところをかい摘んで、僕の知識での補足もしながらご紹介します。

Datastoreの作り

Datastoreは、Googleが内部でガッツリ使用しているNoSQLデータベースの Big Table が動いています。

Megastore というTransaction機能が乗り、一番上の層で Query を実行する仕組みが動いているそうです。

GAEが出た当初は、_XG_Transaction_ は、使えなかったのですが、_Megastore_ が入ったことで制限はあるものの使えるようになったそうです。

最近 Cloud BigTable というサービスも始まっていますが、アプリケーションで実用化するには、この辺りを自分で実装する必要があるんですかね?

Keyについて

Datastoreを使うには、Keyの作りを理解する必要があります。

Datastoreを効率良く使うには、 Entity Group を上手く使うことが必要になりますが、それらはKeyの作り方で決まります。

この辺りが、Datastoreを理解しづらくする大きな要因でしょう。

セッションでは、keyの構造、内部的にどうsortされるかなどを紹介して頂きました。

Eventual Consistency と Strong Consistency について

日本語でいうと、「ゆるい一貫性」と「強い一貫性」でしょうか。

Datastoreでは、更新したデータが即時で反映されないことがあります。

その中でも、Strong Consistency となっているものは、一貫性をもってオペレーションが出来ることになります。
それぞれ、以下のような整理になります。

・Strong Consistency
   Key Operation
   Ancester Query

・Eventual Consistency
   Query

それぞれのオペレーションについて紹介して頂きました。

Key Operation

Keyによる、Get, Put, Deleteです。

Golang では以下の様になります。(出典:スライドより)

func handle(w http.ResponseWriter, r *http.Request) {
    ctx := appengine.NewContext(r)
    k := datastore.NewKey(ctx, "Entity", "stringID", 0, nil)
    e := new(Entity)
    if err := datastore.Get(ctx, k, e); err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
}

Query

filterなどを利用した、いわゆるQueryです。

Queryは、Eventual Consistencyです。 データを更新した後、Getでは取得できるが、Queryでは取得出来ないというケースが起こりえます。

Queryは、ちょっと苦手ですね。この後に紹介されている、Indexを使いながらの検索となります。

上手く使わないと、課金が増えたり、遅くなったりと色々発生しますね。

Ancester Query

Ancester Queryは、先祖(親)キーを指定したQueryです。

DatastoreのKeyを作る際に、親キーを指定します。その親キーも親を指定することが出来ます。同じ先祖(親)を持つEntityが Entity Group となります。

通常のQueryとの大きな違いは、 Strong Consistency になるということです。

ここはとても重要でDatastoreを使うときには、 Ancester Key は必ず意識するべきものとなります。

以下はちょっと補足です。(ここは、僕の理解なので間違っていたらご指摘下さい)

[そもそも、なぜConsistencyを意識する必要があるのか?]
Datastoreは、High Replication Datastore(HRD)が採用されています。高可用性を実現するために、複数のデータセンターにリプリケーションすることで、メンテナンスによるダウンタイムなどをなくしています。
このリプリケーションをしている間の不整合な状態を意識する必要が出ています。

HDRにより基本的には、Eventual Consistency となるQueryの中で、Ancester Query に関してはStrong Consistencyを実現していますよ。

ということかなと思います。

Index

これも、Datastoreで特に意識するべきことです。

Datastoreは、BigTableを機能拡張して作られているということは、先に記載しましたが、BigTableは、Keyのみの取得しか出来ません。

このため、QueryなどをDatastoreで行うために、これが出来るようにBigTableに並びを変えたTableを作成しています。それがIndexです。

Indexの数を増やせば、その分のデータがそのまま入るので実際に入れた2倍、3倍.... と増えてしまうことになります。

Indexには、以下の2種類があります。
それぞれについて説明をして頂きました。

  • Single Property Index
  • Custom Index

Single Property Index

Entityを作成すると、その定義によって作成されます。

Entityは、アプリケーションでは、Modelとし定義することが多いと思いますが、その際に_noindex_を指定しないとdefaultでIndexが作られます。

このIndexは、単項目でのQuery、Sortで使われます。

Query、Sortで使うことのない項目は、必ず_noindex_ を設定しましょう。

Custom Index

Single Property Index で対応出来ないQuery等を行う場合に使用されます。

GAEの設定ファイルの一つである、index.yaml or index.xmlを作ります。

ローカル環境で該当のQueryを実行すると、自動でindex.yamlを作成してくれます。そのままdeployをすると反映されます。

Index爆発

DatastoreのKindには、List Propertyを指定することが可能です。

このList Propertyに対してもQueryが出来るのですが、そのためには、indexが必要になります。

特に、複数のList Propertyに対してのQueryをやろうとすると、、*爆発*します。

それぞれの掛け算分のIndexができて、それぞれのindexにデータが入っていることになるので、もうどうなるか分かりません。。

気をつけましょう。

その他

ここのブログで紹介できなかった部分も紹介して頂きました。

  • Missing Property
  • Vacuum Index
  • Queryの制約
  • Transaction

など

あまりに内容が濃かったのでブログでは紹介しきれませんでした。ゴメンナサイ。

最後に

@sinmetalさん、お忙しい中ありがとうございました。

濃い内容になるとは思ったのですが、思っていた以上でした。

次回登壇をお願いする時は、もっと長い時間を取るようにしますので、今後ともよろしくお願いします!

本当の最後に。

今回は、茅ヶ崎南口から3分のところにある、茅ヶ崎loginさんでの開催でした。

とてもリーズナブルで、臨機応変に対応頂き、懇親会の料理には、大豆屋さんのお豆腐も特別に使って頂きました。

湘南地域を中心に開催を考えているので毎回とは行きませんが、今後も利用させて頂きたいと思います。

以上で、今回のイベントの紹介は終了です。

最後まで読んで頂いてありがとうございました!!

By nuki_pon

See the index for more articles.

--- AD ---