AppEngine とは
使いどころ
- 実験的な内容をサーバで直ちに動かしたい。取り急ぎ、スマホで画面見たいなど。
- 本番には向かない。
便利なところ
- node とか python とかもろもろインストールすることなく、直ちに試せる。
- 直ちにサーバで動かせる。
- 直ちに一般公開できる。
一方で、不便なところ
- サーバ上のコード、生成物などは自分のみしか触れない(/home/自分/ の下しか置けない)。
- サーバに置いたから誰かバッチ実行して、みたいなことはできない。
- そうしたいなら git で共有して、その人のアカウント環境で実装してもらう。
- 本番 deploy には時間がかかるので、頻繁にデプロイするのには向かない。:8080 で自分だけの実行なら時間はかからない。
- ログやデータをローカルに保持できない。
ワード
- サービス: AppEngine では各種機能をマイクロサービスとしてデプロイすることになる。デプロイの単位。ソースコード+設定で構成。
- バージョン: ソースコードは複数のスナップショットを持てる。これがバージョン。デプロイ時にどのバージョンを使うか指定する。
- インスタンス: サービス x バージョン でデプロイする際に、実際に起動する仮想サーバ。
- スケーリング: 自動、手動、基本がある。基本的には無しでも。
- 無料の場合の制限: 5 サービス/アプリ、 15 バージョン/アプリ
- 有料の場合の制限: 105 サービス/アプリ、210 バージョン/アプリ
- Standard Environment / Flexible Environment: マシンを細かく指定したいか。通常は Standard で。
導入手順
想定(下記を実現してみる)
- AppEngine でバッチ実行をする。(Node.js v8)
- 実行の引数を Web 画面で指定し、実行のログをリアルタイムに受け取る。(Node Express, Firebase Realtime Database)
手順
- GCP でプロジェクトを作り、App Engine の画面に行く。
- Google Cloud Shell 起動(画面右上の
>_
アイコン)。 -
git clone
してソースを持ってくる。その中には下記が含まれている。-
app.js
: メインで動く、express のファイル。 -
app.yaml
: デプロイ時の設定 -
asset/log.js
: Firebase Realtime Database 経由でログを受け取るJS -
firebase-config.json
: Firebase Realtime Database を使うためのコンフィグ -
package.json
: npm install するための設定
-
- clone したディレクトリに移動。
npm install
node app
- 右上にある 8080 でプレビューで画面確認。
とりあえず起動
git pull
npm install
node app
- その後、右上にある 8080 でプレビューで画面確認。
デプロイ
# 最新に更新
git pull
# デプロイ(けっこう時間かかる)
gcloud app deploy
# ログ
gcloud app logs tail
- ダッシュボードでもエラーログみれる。
ファイルの中身
- app.js
'use strict';
const util = require('util');
const path = require('path');
const firebase = require('firebase/app');
require('firebase/database');
const firebaseConfig = require('./firebase-config');
// base
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({limit: '5mb', extended: true}));
// static files
app.use(express.static(path.join(__dirname, 'asset')));
// 起動画面
app.get('/', function (req, res) {
res.send(`<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.3.1/firebase.js"></script>
<script>
var config = ${JSON.stringify(firebaseConfig)};
</script>
<script src="logging.js"></script>
</head>
<body>
<form action="execute" method="post">
<textarea name="data" cols="120" rows="20"></textarea><br/>
<input type="submit" value="送信">
</form>
<pre id="log"></pre>
</body>
</html>`);
});
app.post('/execute', function (req, res) {
// ログ出力準備
const logRef = firebase.database().ref('logRef');
logRef.set(null); // ログ初期化
const logger = {};
logger.log = (...args) => {
args = args.map(a => typeof a === 'object' ? util.inspect(a, false, null) : a);
logRef.push().set(args.join(' '));
console.log(args.join(' '));
};
logger.error = (...args) => {
logger.log('ERROR', ...args);
console.error(...args);
};
// いったん返す(ログ初期化後)
res.redirect('/');
// Dialogflow 準備
(async function () {
try {
// データ受け取り
let str = req.body.data;
// データ処理
// ...
// ログ出力
logRef.push().set('ログ出力!');
} catch (e) {
logRef.push().set('ERR: ' + util.inspect(e, false, null));
}
})();
});
if (module === require.main) {
const server = app.listen(process.env.PORT || 8080, () => {
const port = server.address().port;
console.log(`App listening on port ${port}`);
});
}
module.exports = app;
- app.yaml
runtime: nodejs8
env_variables:
SOME_VAR_NAME: "SOME_VAR_VALUE"
-
asset/log.js
: Firebase Realtime Database 経由でログを受け取るJS
firebase.initializeApp(config);
$(function () {
let $log = $('#log');
firebase.database().ref('logUpdateIntentsRef').on('child_added', function(data) {
$log.text($log.text() + data.val() + "\n");
});
});
-
firebase-config.json
: Firebase Realtime Database を使うためのコンフィグ
{
"apiKey": "xxx",
"authDomain": "xxx.firebaseapp.com",
"databaseURL": "https://xxx.firebaseio.com",
"projectId": "xxx",
"storageBucket": "xxx.appspot.com",
"messagingSenderId": "xxx"
}
-
package.json
: npm install するための設定
{
"name": "xxx",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.16.3",
"firebase": "^5.3.1"
}
}