Compute Engine から Cloud Datastore を使う

# やりたいこと

Compute Engine から Datastore にアクセスしたい状況になって色々と調べたり議論したりしたので、その記録を残しておきます。

# 選択肢

とりあえず大雑把に以下の 2 つの選択肢があります。

1. App Engine を間に挟んでアクセスする
   - App Engine 側に、リクエストを受けたら Datastore にアクセスして必要な処理をしたりデータを返すような API を実装しておく
   - Compute Engine からはその API を叩く
2. [Cloud Datastore API](https://cloud.google.com/datastore/docs/apis) を直接叩く
   - 今回は [gcloud-py](https://github.com/GoogleCloudPlatform/gcloud-python) というクライアントライブラリを使用します

[Cloud Datastore API](https://cloud.google.com/datastore/docs/apis) があるのにわざわざ App Engine を間に挟むとかこいつアホなのでは？と思われそうですね。ですが、[Cloud Datastore API](https://cloud.google.com/datastore/docs/apis) がイマイチだとか App Engine から Datastore へのアクセスが速いなどの事情があり、結局 App Engine を間に挟む方が良いとか何とかそんな感じでした。

だがそれも昔の話。今はどうなっているか分からない！ということで色々試してみました。

# 試そう！

Key を指定して Entity を一つ取ってくるという単純な処理で比較をしてみました。
正確に測ってはいないので、各数値は 20~30 ms くらいずれる可能性があると思ってください。

手始めに手元の Macbook Pro から試してみると以下のような結果でした。

| | Cloud Datastore API | App Engine 経由 | App Engine 経由 (memcache 有り) |
|:---:|:---:|:---:|:---:|
| **Local** | 1000 ms くらい | 200 ms くらい | 170 ms くらい |

僕はこの時点で Cloud Datastore API はもうダメだと完全に絶望していましたが、隣で会社の先輩が「諦めんなよ！」という顔をしていたので US region [^1] に Compute Engine のインスタンスを建てて頑張ってみました。その結果がこちら。

[^1]: Datastore は US と EU に住んでいるので、インスタンスも近くに建てましょう

| | Cloud Datastore API | App Engine 経由 | App Engine 経由 (memcache 有り) |
|:---:|:---:|:---:|:---:|
| **GCE (US)** | 50~200 ms くらい | 45~50 ms くらい | 15~20 ms くらい |

時間が短くて計測が難しくなってきたのでだいぶいい加減ですが、Cloud Datastore API の速度が何となく許せるくらいになった感じがします。

ただし、Cloud Datastore API の方はどうも速度が安定せず、速いときは App Engine 経由と遜色ない速度なのですが、遅いときは 200 ms くらい掛かることもあるようで、その辺りの理由までは分かりませんでした。また、App Engine 経由の場合 memcache が働くと App Engine から Datastore へアクセスする時間 (30 ms くらい) がほぼ丸々節約できるので速いです。

# それぞれのメリットとデメリット

## App Engine を間に挟む

### メリット

キャッシュが効くようなリクエストが多い場合、memcache が仕事してくれるのはとても大きいです。App Engine からデータを取得するのに 30ms 程度掛かっているのに対して、キャッシュから取ってきた場合は 2ms とかで済んでいました。Read operation の料金が掛からないのもお得です。

### デメリット

バッチ処理で大量のデータを並列に投入みたいな作業をする場合、App Engine のインスタンスをモリモリ生やすので、多少お金が掛かるでしょう。

## Cloud Datastore API を直接叩く

### メリット

実装が楽ですし、もちろん App Engine インスタンスの料金も掛かりません。Compute Engine からアクセスする分には App Engine を経由するのと比べても遜色ない速度が出るかもしれません。

### デメリット

Memcache 無い。
[gcloud-py](https://github.com/GoogleCloudPlatform/gcloud-python) の[ドキュメント](https://googlecloudplatform.github.io/gcloud-python/)が宇宙の始まりかと思うくらい何も無い[^2]。

[^2]: よく見るとほとんどの項目がソースコードへのリンクになっています

# 個人的な結論

単純に速度だけを考える場合は、App Engine を経由する方が今のところ若干速いですが、状況によっては Compute Engine から Cloud Datastore API を直接叩くのも選択肢に入るレベルになっているかなという感じです。

バッチ処理でデータを投入していくような memcache が仕事しない処理であれば Cloud Datastore を直接叩く方が実装が楽だしお金も掛からなくて良さそうです。

# おまけ

[gcloud-python](https://github.com/GoogleCloudPlatform/gcloud-python) のインストールは基本的に

```
pip install gcloud
```

で良いのですが、GitHub の master branch にはもう少し新しいやつが置いてあるようです。

[master branch に置いてあるコード](https://github.com/GoogleCloudPlatform/gcloud-python/blob/master/gcloud/datastore/connection.py)を眺めてみたところ、こんな感じで gRPC があれば使うような記述が新たに加えられていました[^3]。

[^3]: 2016-08-28 現在、この機能は pip で入る v0.18.1 には実装されていませんでした

<img width="1084" alt="スクリーンショット 2016-08-28 17.45.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/70763/e154532c-ac00-e389-d923-bbf96c404d77.png">

<img width="1052" alt="スクリーンショット 2016-08-28 17.53.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/70763/7495cfeb-d216-5e25-537b-7256679aded1.png">

というわけで

```
pip install git+https://github.com/GoogleCloudPlatform/gcloud-python
```

と、GitHub の master branch から直接インストールした gcloud-python でも試してみたところ、最大で 20 ms 程度速くなり、App Engine 経由のと結構良い勝負をするくらいになりました。

相変わらず速度はあんまり安定していないように感じましたが、頑張ってパフォーマンスを良くしていこうとしている気配を感じるので期待しています。