2022/06/25

残念なレガシーバンドルサービス

GAE/JのJava17対応


(2024/02/26追記)
本記事の内容はすでに古くなっています。また最初の公開時に記載内容に間違いがあった可能性があります。


 久しぶりにApp Engineのドキュメントを見たら、まだプレビュー版ですが、Java17の対応が載っていて驚きました。Java17って去年秋にリリースされたばかりなので、GCPの対応はまだ先かなと想像していたのですが、予想よりずっと早いようです。Java17はJava11以来のLTSなので、注目に値します。


ランタイムの世代

GAEのランタイムには第1世代と第2世代の2種類があります。これらは実行されるランタイムのバージョンが異なるだけでなく、第1世代のみGoogleが実装した拡張機能があります。
これらの拡張機能のうち、よく使われるのは以下ではないでしょうか。
  • Memcache : オンメモリのキャッシュ
  • Search API : Googleのサーチエンジンと同じ全文検索
  • Mail API : メールの送受信
  • Users API : Googleアカウントによるユーザ認証

ランタイムを選択するうえで、これらの機能が必要かどうかも分かれ目になります。

個人的にはまだ第1世代ランタイムであるJava8を使用していて、第2世代ランタイムに移行への移行はまだです。その理由がこれらの機能を使用したいからです。


代替サービス/ライブラリ

以前は第2世代ランタイムでは、前記の第1世代ランタイムでしか提供されない機能の代わりに、他のサービス/ライブラリを使用するように、Googleは説明していました。これらの代替手段は現在でも有効で、本来はこれらの代替手段で対応するものと思います。主なものは以下のとおり。 

Memcache → Memorystore (無料枠なし)
Search API → Elasticsearch
Mail API → SendGrid/Mailgun/Mailgrid など
Users API → Identity Platform/Firebase Authentication/OpenID Connect など


Memcacheは、有料のMemorystoreが嫌なら、ちょっと極端ですが諦めてもいいでしょう。

Search APIは、代わりとして気軽に使えるものが事実上ありません。

Mail APIは、SendGridのみ無料枠が用意されています。SendGridは使いやすくて性能も十分と思います。

Users APIは優秀な代替手段が用意されており、無料枠もあるので、積極的に置き換えるべきと思います。


これらのGAEの機能と同じような状況にあったのがDatastoreですが、Datastoreはすでにサービス終了しています。代わって登場したFirestoreには「Datastore互換モード」があるので、Datastoreとほぼ同じように使えます。DatastoreはJavaライブラリが使いにくいですが、Firestoreはいくらかライブラリが使いやすくなっています。個人的にはFirestoreネイティブモードに乗り換えました。


レガシーバンドルサービスの提供

Java17対応と同時に、第2世代ランタイムに「レガシーバンドルサービス」が提供されるようになっていることに気付いて2度びっくりしました。

レガシーバンドルサービス」は第2世代ランタイムから、第1世代ランタイムのこれらの拡張機能を使用するためのライブラリのようです。これを使用することで、第2世代ランタイムも第1世代ランタイムと同様に使用することが出来るようになるようです。


しかし残念なことに、一番使いたいSearch APIは提供されないようです。

Elasticsearchがあるとはいえ、ちょっと興味本位で調査したい場合や、商用であってもサービス立ち上げ直後で利益が出せるのがいつになるか不安な状態では、安くない月額固定料金のサービスへの乗り換えは厳しいです。


Googleの本音を予想

GAEの第1世代ランタイムに用意されていた拡張機能は、Googleがランタイム(Javaの場合はJavaVM)を独自拡張して実装したのではないかと想像しています (だからランタイムの存在しないGoにはこれらの拡張機能が提供されない)。

App Engineスタンダード環境のランタイム」を読んでいるとGoogleは、第1世代ランタイムを停止して第2世代ランタイムに移行させたいのではないかと思えてきます (実際すぐに第1世代ランタイムが止まることはないことは、「レガシーランタイムの長期サポート」に説明されています)。古くなったランタイムのメンテナンスが行われなくなるのは当然なのでずっと第1世代ランタイムがサポートされることはないのですが、第2世代ランタイムへの移行を促したいのは、ランタイムの独自拡張のメンテナンスも止めたいからではないでしょうか。

なかなか移行が進まない原因を探ったら第1世代ランタイムの拡張機能が原因だったから、第2世代でも利用できるように「レガシーバンドルサービス」という形で対処したものと思われます。


Search APIの代替が用意されない理由はちょっと想像できません。Googleにとっては自社製の検索エンジンの応用らしいので、技術的には用意できなくはないはずです。政治的な理由しか考えられません。Elasticsearchに誘導したい理由は何なのでしょう。

2022/06/04

vsReversiアップデート

2022/05/17に続いて、 GCPのデモとして用意していたvsReversiをアップデートしました。


アップデート内容は以下のとおりです。

  • マテリアルデザイン対応
  • モバイル対応

マテリアルデザイン対応

Angularのマテリアルデザインに対応しました。上記のキャプチャにはマテリアルデザインの個所はありませんが、全体的に見た目がちょっとAndroidアプリぽく変化しています。


モバイル対応

過去のパーションと比較して大きな違いが出るのは、上記キャプチャのゲーム画面です。モバイル対応は、スマートフォンでしか確認できていません。手元にスマートフォンしかないので、実機での確認が出来ているのはスマートフォンだけです。タブレットや機種によっては表示がおかしくなるかもしれません。

2022/06/01

Cloud Loggingにサブスレッドで出力したログが出ない件

Cloud Logginについて

GCPでログを扱うなら、Cloud Loggingは避けて通れない道です。適当にログを吐くコードでを埋め込んでおいて、ブラウザを立ち上げてGCPコンソールのログビューアで表示。しかも30日前くらいまで遡って表示可能。

Cloud Loggingのライブラリの使い方に慣れれば、出力するログのフォーマットもかなり自由に弄べます。ほとんどのGCPサービス・言語で利用できますし、使い方も同じです。

こんなに便利なツールがあるなら、避ける理由などありません。それくらいに便利です。


症状

しかしCloud Loggingには、ログがまともに出ない問題があります。具体的には、

  • サブスレッドから出力したログが、ログビューアに表示されない。主にGCEで発生。
  • サブスレッドから出力したログが、ログビューア上では実際より後の時刻のログに交じって出力される。主にGAEで発生。

メインスレッドから出力すると問題ありません。しかしFirestoreのトランザクションなど、仕様書に明記されていないもののこっそりワーカスレッドを生成して処理しているケースでも上記の問題が発生します。時にはCloud BuildのビルドログがGAEアプリの実行ログに混じることも。


現状

これについてネットで調べても特に情報がないなあと思っていたのですが、ついに公式サイトに載っているのを見つけました。

「Java8 ランタイム環境」の「スレッド」の注釈に説明されています。

注: Java スレッド作成 API を使用する場合、Cloud Trace はリクエスト ID を正しく表示しません。Google は現在この問題の解決に取り組んでいます。

なんと、まだ対応中でした。何年も前から発生しているので早く直してほしいですね。