Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

GAE/Jデプロイ環境のDatastoreからデータをローカルにバックアップする

今ベータテストしているtwitter bot(というかウェブサービス?)にひと通り機能がついたので、いよいよ“ベータ”を取り外そうかという段階に来ています。
ただ正式公開となると怖いのが、セキュリティとデータロス。セキュリティはHTTPSの導入とSecretTokenの暗号化とGoogleアカウントのパスワード強化で充分許容レベルになると考えていますが、データロスだけは防ぎようがありません。
「アップデートしたらテスト不足でデータ全部消えました!/(^o^)\」なんてことになる前にバックアップの手法を確立したいと思ったのですが、現時点では公式資料に手法が明記されていない*1ようなのでまとめました。

GAE for Pythonなら公式ドキュメントに方法が記載されている

JavaではなくPython向けなら、公式ドキュメントに記載があります。appcfg.pyを叩いてコマンドラインで処理する方法です。

ただしJavaSDK付属のappcfg.shでは、これと同じことができないようです。`./appcfg.sh help`してもdata_downloadに関するヘルプが出てきません。
ので、PythonSDKを別途ダウンロードして使う必要があります。

PythonSDKを入手する

公式資料に従って入手とセットアップを行います。このへんは日本語資料も充実しています*2

appcfg.pyからアクセスするための窓口remote_apiを用意する

Python版ならapp.yamlに数行書くだけでOKですが、Google社員(だった?)Ikai氏によればJava版でもweb.xmlに十数行書くだけでOKとのことです。

remoteapi com.google.apphosting.utils.remoteapi.RemoteApiServlet remoteapi /remote_api remoteapi /remote_api admin

Datastoreのデータを落とすための窓口なので、securiy-constraintは必須でしょう。私はuser-data-constraintも指定してHTTPSを必須としました。utl-patternは適宜好きなものに変更しても構いません。
書き換えたweb.xmlをGAEにデプロイしたら、ブラウザからhttps://.appspot.com/remote_apiにアクセスしてみましょう(バージョン番号を含むURLではうまく行かないようです)。Googleアカウントのログインが求められた後に、以下のテキストが表示されれば成功です。

This request did not contain a necessary header

bulkloader用の設定ファイルを作成する

ここまで来たら、あとはPython用SDK向けに書かれたWeb上の資産が流用できます。私はこちらのページを参考にさせていただきました。

当初利用を検討していたdownload_dataによるバイナリ取得は使いにくい上にlong[]が正しく取れていないように見えた*3ので、bulkloaderを使ってCSVとして落とす手法を選択しました。

bulkloaderの利用には、まず設定ファイルの作成が必要です。設定ファイルの雛形はappcfg.pyからcreate_bulkloader_configを叩くことで作成できます。

appcfg.py create_bulkloader_config --filename=bulkloader.yaml \
 --url=https://<app_id>.appspot.com/remote_api

設定ファイルにはkind別の設定が記載されていますので、"# TODO"の部分だけ書き換えてやります。今回はconnectorをcsvとし、connector_optionsを削除しました。

download_dataを叩く

設定ファイルができたら、設定ファイルを指定してdownload_dataを叩いてやります。1kindが1ファイルに相当する関係上、kindを指定して1つずつダウンロードしてやる必要があります。

appcfg.py download_data --config_file=bulkloader.yaml  --kind=<kind> \
 --url=https://<app_id>.appspot.com/remote_api \
 --filename=<filename>

これでカレントディレクトリに指定したファイル名でCSVが保存されます。long[]も"[1L, 2L, 3L, ...]"として正しく保存されました。


以上でデータのバックアップがセキュアに行える環境が整いました。Python用SDKの入手だけ若干面倒ですが、バックアップ体制だけはサービス公開前に整えておきたいですね。

*1:Python用ツールの説明に付記する形では記載があるようです

*2:日本語資料は総じて更新が遅いので通常の利用はおすすめしません

*3:sqlite3からCSVに変換するときに失敗した可能性はある