App Engine PHP 7.2 Standard Env における Redis / Memcached / Spanner の利用方法
インフラの矢口です
GAEにおいてついにPHP 7に対応したランタイムがリリースされました! gVisorを利用することにより今までよりも圧倒的に制約が減り、標準的な構成を動作させやすくなりました。また大きな懸念点であった言語処理系ランタイムの更新頻度についても改善されることがアナウンスされています。
さて、そのようなGAE PHP 7ですが、DBやキャッシュのミドルウェアまわりについてはどうなっているのでしょうか。通信周りも自由になったため任意のプロトコルで外部に接続できるようになり使用できるものはかなり増えているはずです。
しかし公式ドキュメントで記載されているDBはDatastore, Cloud SQLにとどまっています。またApp Engine付属のマネージドMemcacheは提供されません。
App Engineからよく利用することが想定される3つのミドルウェアについて動作させる手段を検証しました。
Public Networkとセキュリティ
Redis / Memcachedを利用する際もっとも問題になることはセキュリティです。Standard EnvironmentではPrivate Networkが利用できないため、Redis / MemcachedをPublic Networkに公開しつつセキュリティを確保する必要があります。
Heroku / Redis Labs / MemCachier などいくつかのサービスを調査したところ。暗号化は実施せずパスワード認証だけを追加した上で、盗聴のリスクの少ない同一クラウドの同一リージョンに設置する方法が一般的なようです。
SSLは対応するクライアントが少なくApp EngineからのアクセスではSSLトンネルの設置も難しいことや低レイテンシが求められるキャッシュにおいてレイテンシが増加してしまうといった問題からあまり推奨されていないサービスが多いようでした。
Redis
公式ドキュメントではRedis Labsが推奨されています。Cloud MemorystoreがPublic networkから利用できない制約があるためでしょう。
ここでは簡単に検証するためCompute EngineにRedisサーバーを構築し、confでパスワードを設定します
redis.conf
1 |
requirepass XXXXXXXX |
Public networkからアクセスできるようfirewallを設定して疎通を確認します。
predisではなくphpredisを利用する場合にはredis.soはDynamically loadable extensionsになっているためphp.iniに追加します
パスワードを利用する以外は通常と同じように利用できました。
1 2 3 4 5 6 7 8 9 10 |
<?php require __DIR__ . '/vendor/autoload.php'; $redis = new Redis(); $redis->connect('XX.XX.XX.XX', 6379); $redis->auth('XXXXXXXX'); var_dump($redis->set('foo', 'bar')); var_dump($redis->get('foo')); |
Memcached
Memcachedサーバーを構築し、SASLを設定します。SASLは前述のRedis passwordなどと比較してだいぶ複雑です。このあたりが参考になります。
https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-memcached-on-ubuntu-16-04
Redisと同様firewallを解放します。
php.iniにmemcached.soを追加してデプロイすると問題なく接続できました。
1 2 3 4 5 6 7 8 9 10 11 |
<?php require __DIR__ . '/vendor/autoload.php'; $mc = new Memcached(); $mc->setOption(Memcached::OPT_BINARY_PROTOCOL, true); $mc->addServer("XX.XX.XX.XX", 11211); $mc->setSaslAuthData("USER", "PASSWORD"); var_dump($mc->set('foo', 'bar')); var_dump($mc->get('foo')); |
Spanner
結論からいいますとSpannerの利用はうまく行っていません。疎通はできるのですが接続で1秒ちかくかかってしまう状況です。
まず、同一リージョンにSpannerのdatabaseを作成します。
php.iniにprotobuf.soとgrpc.soを追加します。
READMEにあるように各種キャッシュを利用するようにしながら接続するコードを書きます
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php require __DIR__ . '/vendor/autoload.php'; use Google\Cloud\Spanner\SpannerClient; use Google\Cloud\Spanner\Session\CacheSessionPool; use Symfony\Component\Cache\Adapter\FilesystemAdapter; $cache = new FilesystemAdapter(); // Semaphore extensionは非対応のため/tmpにキャッシュ $sessionPool = new CacheSessionPool($cache); $projectId = getenv('GOOGLE_CLOUD_PROJECT'); $spanner = new SpannerClient([ 'projectId' => $projectId, 'authCache' => $cache, ]); $database = $spanner->connect( 'INSTANCE', 'DATABASE', [ 'sessionPool' => $sessionPool ] ); $results = $database->execute('SELECT "Hello Spanner World" as test'); foreach ($results as $row) { print($row['test'] . PHP_EOL); } $database->close(); |
準備としてはこれでいいはずなのですが、実際には現実的ではないレスポンスタイムとなってしまいます
1 2 3 |
$ ab -n 10 -c 1 https://XXXX.appspot.com/spanner.php Requests per second: 0.81 [#/sec] (mean) Time per request: 1234.942 [ms] (mean) |
セマフォ extensionが使えない件と、Spannerへの接続が遅い問題についてはそれぞれissueを起票しています。
https://github.com/GoogleCloudPlatform/google-cloud-php/issues/1255
https://issuetracker.google.com/issues/113305563
まとめ
GAE PHP 7.2は非常にモダンで快適なサービスとなっていました。またミドルウェアについてもPublic Networkが必須となってしまうものの以前よりも自由に利用できるようになっています。
一方でPHPに限らずですが以前から課題であったGAEからのSpanner利用については前進はあるものの依然として難しいようです。
またそのメンテナンスフリーの性質からMemcachedやRedisについてもマネージドサービスが提供されるとなお良いのですが、GCPではなく他社のサービスを利用することが現在の落とし所かもしれません
インフラに関する構築コストを劇的に削減できる、GAEの制約がさらに減りモダンになったことは大変喜ばしいことです。さらにいろいろなユースケースへの対応やサービス連携性の向上がすすむといいですね。