2025/12/12

残念な AppRun

ガバメントクラウドに暫定認定の「さくらのクラウド」で、 2025/12/09にAppRunがリリースされました。

さくらインターネット、アプリケーション実行基盤「AppRun」の正式サービス提供を開始 〜専有型と共用型の2プランを同時リリース、用途に応じた柔軟な実行環境を実現〜


おめでとー と喜びたいところですが...


「占有型と共用型」... なにそれ。上記のリリースニュースを読めばわかりますが、共用型はこれまでプレビューリリースだったもの、占有型は新たに追加されたものとあります。


そして占有型は「CPU使用率ベースでのスケーリング」であると...

コレいらない。


一般的には市場に提供されるサービスはwebアプリであることが多いと思いますが、webサーバのスケーリングはリクエスト数ベースでないと適切にスケーリングできません。CPU使用率ベースでは手遅れになってからスケールが始まります。

まあ、占有型を無視して共用型を使えばいいことですが。


さらに言えば、フロントエンドであるwebサーバはオートスケールが必要ですが、バックエンドではオートスケールは邪魔になるケースのほうが多くなります。バックエンドに必要なのは実行開始時にスケールを指定できるマニュアルスケールです。

バックエンド向けのプロダクトはこれから出てくるのでしょうか。


料金体系も異なりますので、おそらくこの料金体系を反映させるための仕様でしょうか。

期待していたのに残念です。


2025/12/07

「なんとか as a Service」って、何種類あんねん

この記事のタイトルが どこかで聞いたことのあるような... いや聞いたことないことにしてください。


XaaS

面白い記事を見つけてたので紹介します。

AaaS、BaaS、CaaS、DaaS、、、 どこまであるの?調べてみた!

最後のオチが...


実際には上記の記事で紹介されている以外にもXの部分は、AIaaSとかSECaaSのように2文字・3文字に増えているものや、iDaaSのように2文字かつ小文字混じりのものもあります。

もう本当に増えすぎていて、まとめてXaaSと呼ばれるようになっていますね。


CaaS

CaaSの読みとして「カース」と紹介している記事を見受けますが、これだけXaaSがあると、この読み方には違和感を感じています。

  • KaaSも「カース」で区別がつかない。
  • MaaSは「マース」?  SaaSは「サーズ」? これらの読みは一般的にはMERS・SARSの方が有名なので、印象が悪い。
  • IaaSのように発音が難しいうえに頻出するものがある。
  • DaaSは某企業様から訴えられそう。と思ったらDARSだった。

KaaS

もう一つの違和感。
KaaSは「kubernetes as a Service」の略と紹介されることが多いですね。Knativeを忘れていませんか。実際に有用なのはkubernetesではなくてKnativeの方であることが多いので、KaaSには「Knative as a Service」も追加すべきだと思います。

2025/10/13

LotteryServアップデート

    LotteryServを更新しました。今回の更新は1つだけです。


応募画面を独自デザインに対応

 応募画面を募集ごとに、独自のデザイン/UIに対応可能にしました。


 これまで応募ページはデフォルトのデザインのみで、主催者様の好みに合わせた内容・デザインを使えませんでした。

 今回のアップデートで、主催者様で応募ページのコンテンツ(HTML/CSS/JavaScript)を作成し、それをアップロードしていただくことで、独自デザインの応募ページを表示することが可能になりました。応募ページ内に画像や動画を表示することも可能です。いくつか約束事はありますが、それさえ守っていただければ、応募ページは自由なデザインをご利用いただけます。

 応募ページに独自コンテンツをアップロードするには、募集詳細画面から「コンテンツ編集」ボタン押下で遷移する「コンテンツ編集」画面で操作します。


 応募ページのコンテンツには以下の制限があります。

  • 最低1つのHTMLをアップロードする必要があります。
  • HTMLは複数アップロード可能ですが、応募者に最初に表示されるメインページを設定する必要があります。
  • ディレクトリなどの階層構造は利用できません。
  • 応募や抽選結果の確認のためにJavaScriptを用意してあります。それを読み込み、適切に使用する必要があります。


 独自コンテンツのアップロードがない場合、従来どおりのデフォルトのデザインのページとなります。アップロードしたコンテンツの削除も可能です。アップロードしたすべてのコンテンツを削除した場合は、デフォルトのデザインで応募ページを表示します。

 より詳しくは各画面のヘルプをご覧ください。


2025/08/25

Docker+Kubernetesでいいの?

動機

 前スレの『さくらのクラウドとサーバレスアーキテクチャ』で書いた以下について説明不足と感じたので、ここで詳しく書いておこうと思います。

「クラウドに移行したもののランニングコストが予測よりずっと高く、期待したように下がらない」という話を時々聞きます。

自治体システム標準化、ガバクラ移行で運用コスト2~4倍に悲鳴「議会に通らない」(有料記事ですが1ページ目のみ無料で閲覧可能)

 ガバメントクラウド移行で自治体の年間コストが5.7倍に…計画の重要性

 ガバメントクラウド移行で自治体の運用コストは本当に下がるのか?

上記の引用はガバメントクラウドに関するものですが、過去に私が関わった民間企業のwebアプリケーションでも同様の現象が起きていました。この企業で使っていたのもKubernetes(GKE)ですが、「思うようにスケーリングできない」ので無駄にリソースを割り当ててアプリケーションを実行しているという状況でした。


問題点

クラウド上に実装されたアプリケーションで「Dockerコンテナに突っ込んでKubernetesでオーケストレーション」という作りをよく見ますが、webアプリケーションでこれが有効なケースは、実際には一部に限られます。

実際にはこの構成でwebアプリケーションを実装すると、以下の問題が発生します。

  • オートスケールを設定しているのに、リクエストの急増でサーバビジーが発生する。
  • (上記のように)運用コストが高いケースがある。


原因

クラウドがオンプレミス/レンタルサーバに比べて有利になる要因は、スケーリングの恩恵によるところが大きくなっています。

従来(オンプレミス/レンタルサーバ)では、あらかじめ契約により用意したリソースの中で、それを有効活用できるようにユーザがやりくりしていました。確保されるリソースは契約で変更するのが前提なので、迅速な変更はできず、これがリソースの無駄の原因となっていました。

対するクラウドでは、複数のプロジェクト(これには他人のプロジェクトも含みます)にまたがってデータセンター全体の中で、リアルタイムでリソースの割り当てを変更することで、リソースの無駄を削減します。必要なものを、必要な時に、必要なだけ確保します。ここが従来と最も異なる点です。無駄がなくなることによって運用コストが下げられます。


ここまでならKubernetesによるオートスケールでも実現できそうに感じるのですが、実際には一般的なwebアプリケーションでは、そう思いどおりにならないケースが多いようです。


一般的なwebアプリケーションではエンドユーザの操作に従ってクライアントからリクエストが送信され、サーバがそれに答えます。この間はエンドユーザが待っているので短い方が好ましく、一般的には1秒以下、瞬間的に遅くなっても3秒程度が限度とされます。

Kubernetesによるオートスケールはデフォルトでは30秒ごとにCPU負荷を監視して、Pod/ノードをスケーリングします。そのため負荷の変化が起きてからでないとスケーリングは始まりません。負荷を急増させるリクエストがあっても、そのリクエストはすでに処理を開始した後なので、スケーリングの恩恵を受けられません。

またwebアプリケーションのリクエストの一般的な処理時間に比べて、Kubernetesによる負荷監視の間隔はあまりに長いので、適切な監視およびスケーリングを行いきれません。監視間隔を短くすれば改善できるでしょうが、CPU負荷の測定そのものがコンテナに負荷をかけるので、短いのも悪影響があります。

さらにPodの水平スケールは秒単位で終わりますが、ノードのスケールは分単位で時間がかかります。これだけ長いとエンドユーザは待ってくれません。


つまりKubernetesでのオートスケールが有効なのは、リソース要求の変化が比較的ゆっくり(分単位かそれ以上)の場合です。急激に変化する場合は追従しきれず、サーバビジーを発生する原因となります。


解決策

解決策の構成の1つが以下です。

webサーバのオートスケールのコントロールをKubernetesではなく、Knativeで行うことで改善が期待できます。KnativeはKubernetesに替えてサーバレスアーキテクチャに基づいてスケーリングを行います。
webサーバの場合はリクエストはイベントとして処理され、リクエスト数がスケーリング指標となるので、CPU負荷に頼らずスケーリングが可能です。リクエストがプラットフォームに届いた時点でスケールアウトの必要性が判断され実行されるので、スケールアウトの要因となったリクエストもスケーリングの恩恵を受けられます。そのためサーバビジーは発生しにくくなります。
またCPU負荷監視の間隔がスケーリングに与える影響が少なくなり、負荷の変化に対して迅速なスケーリングが可能となります。これによってリソースの無駄がなくなり、運用コストを削減できます。

Knativeを利用したApp EngineやCloud Runサービスを長年使ってますが、ノードのスケールアウトに相当するケースに遭遇したことがありません。ノードについてはプラットフォーム側である程度プールしているものと推測されます。ノードのスケールインは観測できないので、いつ起きているのか不明です。

またKnativeには、複雑なKubernetesの設定を簡略化してくれるという側面もあります。

設計

ユーザが自分でKnativeを組み込むことはまずなく、一般的にはすでにKnativeが組み込まれたPaaSを利用します。Google Cloudでは以下が該当します。
以下はKnativeだけどPaaS以外。

Knativeによるサーバレスアーキテクチャでの実装については、アプリケーション(=コンテナへの分割の仕方、コンテナの中身)の設計・実装も従来とは変える必要があります。これはモノシリック構成に替えてマイクロサービス化する程度では対応できません。スケーリングがいつ起きてどこに影響するのかを考慮する必要があります。
具体的にどうすればいいのかは、長くなるのでまた別の記事で。(書くかもしれませんが書かないかもしれません)

例外

論理的に、アクティブユーザ(=同時接続していて操作しているユーザ)が十分多い大規模アプリケーションの場合、各ユーザの操作が平均化されて極端なリクエストの変化が起きにくくなる可能性があります。このような場合はKubernetesによる緩慢なスケーリングでも十分となります。
しかしこれに該当するには相当な規模のアクティブユーザ数が必要なようです。具体的にどの程度の規模が必要かを知るには、私自身もこの業界もまだ経験が足りないようです。toBの規模ではないと想像しています。toCでは「何時から開始」のようなサービスを提供するケースで、緩慢なスケーリングでは一時的に対応できなくなる可能性が高くなります。
またどのようなサービスでも最初は小規模から始まるものなので、ある程度の規模がないと効果がないKubernetesよりKnativeのほうが、損失を抑えながらサービスを立ち上げることができるという利点もあります。

またイベントドリブンではなく、要件やアプリケーションの仕様(操作方法)の工夫によってスケーリングの要求を緩慢なものにできるアプリケーションでは、Kubernetesで十分な性能を発揮できることがあると思われます。

まとめ

以下はwebアプリケーション、正確に言えばその中でも、エンドユーザからのリクエストを処理するフロントエンドを構成するwebサーバに限った話です。

コンテナの中身については、クラウド以前の古い設計・実装のままでも機能的には動くかもしれませんが、それではKubernetesにせよKnativeにせよ、性能面でクラウドが能力を発揮することはまずないでしょう。
オーケストレーションについては、ここで最適なのはKubernetesではなく、Knativeです。クラウドと同時に登場したサーバレスアーキテクチャこそが、イベントドリブンの場合の本来の使い方だと言えます。

最後に

「従来の設計・実装のままDockerコンテナに突っ込んでKubernetesでオーケストレーション」という例が未だになくならないのは、クラウドの使い方を理解している人が少ないだけでなく、仕事を受注してお金を稼げればいいだけの意識の低い受託開発業者が多く、発注側もこのような技術面での認識が出来ていないということだと思います。
もう少し踏み込んでモノシリックな構成から脱却しマイクロサービスアーキテクチャを取り入れているケースや、DDD(ドメイン駆動設計)を取り入れているケースもあります。これらはコンテナの使い方を意識したものと思われますが、スケーリングを考慮しないならクラウドでの効果は限定的です。またコンテナの分割の仕方によっては逆効果となる可能性もあります。

営利目的のサービスの場合は、多少運用コストが高くても売り上げを増やせば利益を確保できます。しかし行政のような直接売り上げを生み出さないアプリケーションの場合、運用コストの増大は危機的な悪影響となります。まして行政の場合は潜在ユーザは多いもののアクティブユーザは僅かと考えられますので、事実上有望な選択肢はサーバレスアーキテクチャの一択となります。

2025/07/18

さくらのクラウドとサーバレスアーキテクチャ

さくらのクラウドの注目記事

 私が現在利用しているクラウドはGoogle Cloudのみですが、その他には国産クラウドである「さくらのクラウド」にも興味を持っています。現在ガバメントクラウド認定を目指して整備が進められているさくらのクラウドですが、そのアプリケーション実行基盤である「AppRun」はサーバレスであることが発表されています。

さくらインターネット、アプリケーション実行基盤「AppRun β版」にて製品版のトライアルを開始

さくらのクラウド、コンテナをサーバレスで実行する「AppRun」製品版トライアルを開始。トライアル中は全機能が無料に


サーバレスアーキテクチャとは

2008年のApp Engineリリースから使えるようになったものなので、まだご存じない技術者も見かけます。理解が簡単ではないので、普及はこれからといった印象です。またFaaS(Function as a Service)と混同しやすいので注意が必要です。


サーバレスアーキテクチャは、このブログの記事「サーバレスアーキテクチャ」でも説明しています。コンピューティングにおいては、アプリケーションの実行インスタンスは常に起動しているわけではなく、必要な時に必要な分だけのリソースを割り当ててアプリケーションの実行を行うアーキテクチャです。リソースの管理はプラットフォームがやってくれるので、ユーザは意識する必要がありません。

サーバレス アーキテクチャとは

サーバーレス・コンピューティングとは

クラウド以前の従来のサーバは想定された利用状況に応じてあらかじめリソースを割り当てておきます。リソースの管理は、夜間など利用の少ない時間帯にバッチ処理を走らせるなど、計画的で柔軟性はありません。

クラウドでも非サーバレス場合は、最低1つ以上の実行インスタンスが常に割り当てられます。夜間バッチの実装など従来と変わらない設計が主流です。

それに対してサーバレスアーキテクチャでは、リアルタイムで必要なだけリソースを割り当て/開放します。これによりランニングコストの低減や、サーバビジーによる一時的なサービス提供不能の発生低減が期待できます。これはユーザにとって大きなメリットとなります。


しかしクラウドベンダー目線で考えると、上記とは違う特徴を実現することが目的ではないかと考えられます。

リアルタイムにリソース割り当てを変更できることから、データセンター全体でリソースを有効利用できるようになります。またリソースの割り当ては基本的に永続的ではなくなるので、ハードウェアのメンテナンスをしやすくなる(ユーザにとってもメンテナンスの影響を受けにくくなる)利点も考えられます。


「みんなのクラウド」と表現されることがありますが、データセンターのリソースをユーザみんなで共有し、その割り当てをより柔軟にして(非サーバレス以上の)最大限の効果を狙うのがサーバレスアーキテクチャであると言えると思います。


サーバレスアーキテクチャの現状

現在の日本のwebアプリケーションは、まだサーバレスアーキテクチャを採用したものは少ないように見えます。キーワードとしてKubernetesが出てくるアプリケーションは、サーバレスアーキテクチャではありません。それどころかクラウドに最適化されていなくて従来の延長線上でしかないものもあるようです。

現在クラウドの利用方法の主流は、Docker+Kubernetesの構成と思われます。この構成が流行った要因は以下のようなものと考えられます。

  • どのクラウドベンダーでも同じように実装でき、ベンダーロックインが発生しない。これは特に受託開発やSESにとって好都合。
  • クラウド以前の従来の技術・知識・プロダクト(ライブラリ、フレームワーク)を使いまわせる。新たに覚えるべきことはDockerとKubernetesのみ。
  • Kubernetesによって一応スケーリングも可能なので、スケーリングの恩恵も得られる。
主に開発者の都合が中心です。ひどい場合はDockerコンテナにクラウド以前のレガシーな構成をそのまま詰め込んだだけのケースもありそうです。Kubernetesでスケーリングさせているつもりが、その効果さえ確認していないケースもあるようです。クラウドに最適化しないのであれば、クラウドによる恩恵も最低限しか受けられません。


サーバレスアーキテクチャではコンテナオーケストレーションにはKubernetesではなく、Knative(あるいは相当のもの)を用います。


ランニングコストについて

「クラウドに移行したもののランニングコストが予測よりずっと高く、期待したように下がらない」という話を時々聞きます。

自治体システム標準化、ガバクラ移行で運用コスト2~4倍に悲鳴「議会に通らない」(有料記事ですが1ページ目のみ無料で閲覧可能)

 ガバメントクラウド移行で自治体の年間コストが5.7倍に…計画の重要性

 ガバメントクラウド移行で自治体の運用コストは本当に下がるのか?


上記の引用はガバメントクラウドに関するものですが、過去に私が関わった民間企業のwebアプリケーションでも同様の現象が起きていました。この企業で使っていたのもKubernetes(GKE)ですが、「思うようにスケーリングできない」ので無駄にリソースを割り当ててアプリケーションを実行しているという状況でした。

他の原因の1つは、クラウド以前の従来のアーキテクチャを引きずったまま移行していることにあるのではないかと考えられます。クラウドに最適化しないのであれば、クラウドに乗り換える効果も限定的でしかないのは想像に難しくありません。


その他にも、従来の手作業・紙ベースの手順をそのままにしておくことを優先したため、コンピュータ処理に適さない手順を無理やり実装したことによる弊害もあると考えられます。これは今に始まったことではなく、クラウドやアーキテクチャによるものでもない別次元の話なので、本記事ではこれ以上取り上げません。


サーバレスアーキテクチャでの実装

実際にサーバレスアーキテクチャで実装するには、対応するPaaSのプロダクトを利用することになります。しかしそれだけでは実装後に以下のような性能上の問題が発生することがあります。

  • レスポンスが悪い、または悪くなることがある。
  • バッチ処理などバックエンドの処理に時間がかかる。
  • ランニングコストが下がらない。
    (使い方を間違うと効果は得られない)
  • コストの予測が困難。
    (スケーリングする限り非サーバレスでも同じだが、より変化が大きい)


サーバレスアーキテクチャを有効に使いこなすためには、それに対応した設計が必要となります。ここでのノウハウにはサーバレスアーキテクチャを実装した経験からしか得られないものもあります。具体的にここで書ききれる量ではないので別の機会に。

しかしサーバレスアーキテクチャを使いこなせば、スケーリングを最大限に活用できて以下の効果を得られる可能性があります。

  • ランニングコストの削減。
  • サーバビジーによる一時的なサービス不可の減少。


技術的課題

従来のサーバは「起動しておいて必要とされるのを待つ」思想で実装されています。しかしサーバレスアーキテクチャでは「必要とされたから起動する」という思想に変わります。そのためwebサーバのような「ユーザが待っている」ケースでは、起動の遅い実装はユーザを待たせる悪いユーザエクスペリエンスにつながります。バックエンドのような起動の遅延が影響しないケースでは無視できます。

これにより従来のプロダクト(サーバレスアーキテクチャを考量していないライブラリやフレームワーク)が使い物にならなくなっているケースがあります。フレームワークの場合はそれを理解せず使用してしまうと、ほぼすべて再実装でしか改善できないほどの影響も考えられます。たとえ人気で過去に実績もあるプロダクトといえど、サーバレスアーキテクチャを考量してなくて悪影響となるものは、早めに清く捨て去る必要があります。

この思想の違いは開発者にとっては、パラダイムシフトとも言えるほどの影響です。これはサーバレスアーキテクチャの理解や使いこなしを難しくしています。


またクラウドベンダーにより対応の方法がバラバラです。簡単にサーバレスアーキテクチャへの対応をまとめると、以下のようになります。

  • Google Cloud
    • App Engine(Standard Environment):独自コンテナ+Knative、webサーバ。
    • Cloud Run:Docker+Knative。
      • Service:webサーバ。
      • Function:FaaSとしての利用形態で実態はServiceと同じ。
    • GKE + Knative serving:もうCloud Runでよくない?
  • AWS:Serverless Application Modelに基づいてLambdaで実装。
  • Azure:Azure Functionsを利用。
  • さくらのクラウド
    • AppRun:Docker+Knative

そのほかにIBM、Oracleも対応しているようです。

AWS, AzureはFaaS(Function as a Service)の流用にとどまっており、あまりサーバレスアーキテクチャの採用に関して積極的に見えません。

Google CloudはFaaSだけでなくPaaSも用意されており、対応が最も進んでいます。またwebサーバでなくバッチ処理でも同じように使えるプロダクト(Batch, Cloud Run Job)が用意されいます。これらは本来サーバでないのでサーバレスアーキテクチャと呼びませんが、「必要な時に必要な分だけ」リソースを使うことができる点においては同じです。


さくらのクラウドに対する期待

さくらのクラウドでは今後はサーバレスアーキテクチャが普及していくものと予測しているそうです。これは私も同意見で、世の中の技術者たちがサーバレスアーキテクチャの理解を進め、普及していくように活動しています。


2025/06/20

LotteryServアップデート

   LotteryServを更新しました。今回の更新は細かい仕様変更や不具合修正です。


多要素認証の設定はEメールアドレスのみ必須に

 2025/05/06の更新で多要素認証に対応しましたが、同時に主催者の支払い方法を設定するにはユーザアカウントに多要素認証の設定を必須としました。しかしGoogleアカウントを利用している場合、Googleアカウントにパスキーや多要素認証が設定されているか否かを判断できないため、Googleアカウントの多要素認証とLotteryServの多要素認証で2回の第2認証が行われる可能性が発生しました。これは意味がないので、以下の仕様に変更しました。

  • Googleアカウントの場合は、LotteryServでの多要素認証設定は任意とします。ただしGoogleアカウントにパスキーを利用するか、多要素認証の設定を推奨します。
  • Eメールアドレスの場合は、LotteryServでの多要素認証設定は必須のままです。

応募・抽選結果のCSVをZipアーカイブに

 応募・抽選結果はCSVファイルでダウンロード可能ですが、応募数が多い(100,000以上)場合は複数のCSVファイルに分割しています。これは少々古いバージョンのExcelでも扱えるようにするための仕様です。

 従来はCSVファイルを1つずつダウンロードする必要がありましたので、応募数が多い場合は面倒でした。今回の更新では、すべてのCSVファイルを1つのZipアーカイブにまとめる仕様に変更しました。ダウンロード後に解凍は必要ですが、ダウンロードの手間は軽減されています。


ツールチップが表示されない不具合を修正


 操作可能なアイコンをマウスポインタでポイントすると、アイコンのそばにそのアイコンの説明を表示するのがツールチップです。上の図は主催者ログイン画面の告知リスト左下のリロードアイコンのものです。

 これを実装していたのですが、どこかの更新で表示されなくなっていました。おそらく2025/05/06の更新からだと思われます。気づくのに遅れましたが、今回修正しました。

 ただし全画面でツールチップに対応しているわけではありません。一部の画面では以前からツールチップには非対応です。なんとなくアイコンの見た目で機能は判断できると思いますので、今後もツールチップ非対応画面ではそのままの予定です。


Angularの*ng~ディレクティブについて

従来

 Angularでは状況に応じてHTMLの内容を変更する際に以下のディレクティブを使用します。

  • *ngIf
  • *ngSwitch, *ngSwitchCase, *ngSwitchDefault
  • *ngFor

 これらのディレクティブは以下のタグと組み合わせて使用することもあります。

  • ng-container
  • ng-content
  • ng-template

 使い方を説明した記事はネット上に既にたくさんあるので詳細は説明しませんが、以下のような感じになります。

<div *nfIf="isProcessing; then processingMess; else doneMess"></div>

<ng-template #processingMess>
    <span>処理中...</span>
</ng-template>

<ng-template #doneMess>
    <span>完了!</span>
</ng-template>
<div [ngSwitch]="processState">
    <span *ngSwitchCase="PREPARING">準備中.</span>
    <span *ngSwitchCase="PROCESSING">処理中...</span>
    <span *ngSwitchCase="DONE">完了!</span>
    <span *ngSwitchDefault> (?o?) </span>
</div>
<table>
    <tr *ngFor="let item of itemList">
        <td>{{item}}</td>
    </tr>
</table>

 ngSwitchやngForの例はまだ何とかわかりますが、ngIfのようにng-templateなどとの組み合わせになると直感的でなくて、わかりにくいと大変不評です。


Angular17以降

 Angular17で、以下の新しい構文が追加されました。
  • @if, @else, @else if
  • @switch, @case, @default
  • @for, @empty

 これらは直感的に書けるように改善されています。

<span>
    @if (isProcessing) {
        処理中...
    } @else {
        完了!
    }
</span>
<span>
    @switch (processState) {
        @case ("PREPARING") {準備中.}
        @case ("PROCESSING") {処理中...}
        @case ("DONE") {完了!}
        @default { (?o?) }
    }
</span>
<table>
    @for (item of itemList; track item) {
        <tr>
            <td>{{item}}</td>
        </tr>
    }
    @empty {
        <tr>
            <td>空っぽです</td>
        </tr>
    }
</table>

 @emptyに対応する*ng~ディレクティブはなさそうです。探してみたのですが見つかりません。


 一度使ってしまうと、もう*ng~ディレクティブには戻れません。


2025/06/08

LotteryServアップデート

  LotteryServを更新しました。前回2025/05/06の更新に続いて、今回の更新もセキュリティの強化が中心です。


ワンタイムパスワード認証に対応

 多要素認証の第2要素として、ワンタイムパスワード認証を追加しました。

 多要素認証はログインできなくなった場合への備えとして複数の第2認証を登録することを勧めていますが、前回のアップデートで対応したSMS認証のみでは、複数のスマートフォン/携帯電話が必要になり、現実的とは言い難い状況でした。今回ワンタイムパスワード認証を追加したことで、スマートフォン/携帯電話は1台でも2つの第2認証に対応できるようになります。

 ワンタイムパスワードアプリは、以下の2つで動作することを確認しています。

  • Google Authenticator
  • Microsoft Authenticator


 ただし機種変更時の移行には、あらかじめワンタイムパスワード認証の設定をアカウントに保存するなど準備をしておくか、新旧2台を並べて操作するかが必要なようです。ご注意ください。


第2認証の完全な削除を可能に

 前回のアップデートでは、第2認証を複数登録した場合は1つずつ削除が可能でしたが、最後の1つの第2認証は削除不可能という制限がありました。今回のアップデートでその制限はなくなりました。

 すべての第2認証を削除すると、ログイン・再認証は第2認証なしとなります。もちろんこの場合は多要素認証の設定がないので、アカウントは脆弱な状態となります。

 多要素認証の設定がないユーザでは募集の開始ができない制限は、前回2025/05/06の更新からのものです。この制限はクレジットカード決済の悪用による被害を防ぐためのものです。


UIのモダナイズ

 前記ワンタイムパスワード認証の追加に伴い、主催者ログイン画面など一部の画面をモダンなデザイン・実装に変更しました。

 また他の画面でもごく一部に画面遷移やデザインを変更した個所がありますが、使い方には変化はありません。


メールでログインでもアイコンを利用可能に

 Eメールアドレス/パスワードでログインするアカウントの場合、従来はアイコンが固定でした。

 インタネット上に公開されているアイコンがある場合、そのアイコンのURIを指定していただくことで、LotteryServ上でもそのアイコンを表示するようになりました。

 ただ、現在このアイコンを表示するのは、ユーザメニューの最初の項目のみです。


その他軽微な不具合の修正

 詳細の説明は割愛いたしますが、軽微な不具合を複数修正しています。

2025/06/06

Firebaseコンソールの不具合

 Firebase Authenticationで多要素認証を実装しようとしていて発見した、Firebaseコンソールの不具合です。


準備

まずはテスト用の電話番号を登録します。SMSを受信できるスマホや携帯電話が2台以上あれば、テスト用の電話番号は不要かもしれません。

テスト用電話番号の登録手順は以下のとおり。この手順を説明した記事は少なそうだったので、念のため記載します。

  1. FirebaseコンソールでAuthenticationを選択。
  2. 画面上部のタブで「ログイン方法」を選択。

  3. 「SMS多要素認証」の「変更」を押下。

  4. ダイアログの「有効にする」をチェックして
  5. 「テスト用の電話番号」を押下するとダイアログが伸びてテスト用の電話番号の設定が現れます。
  6. 適当な電話番号(日本なので"+81aabbbbcccc")と確認コード(10進数6桁)を入力して、
  7. 「保存」を押下。


発生手順

手順の際現にはSMS認証による多要素認証をFirebase Authenticationで実装したアプリが必要です。ない場合はFirebaseのquickstart-jsでも再現できます。

以下にquickstart-jsによる再現手順を示します。

  1. SMS multi-factor authenticationを選択。

  2. 登録してある任意のアカウントのEメールアドレスとパスワードを入力して「SIGN IN」を押してログイン。
  3. 「ENROLL」を押下して第2認証のSMS認証の登録を開始。
  4. SMS認証に追加する電話番号を入力。準備で設定したテスト用の番号で十分です。

  5. reCAPTCHAをチェックしたら「SEND CODE」を押下。ここで"Firebase: Error (auth/requires-recent-login)."が発生したらいったんSIGN OUTし、手順2からログインしなおし。
  6. 届いたSMSに記載されている認証コードと、任意の表示名を入力して「VERIFY CODE」を押下。ここでは表示名は"test SMS 1"としています。
  7. SMS認証の追加が完了し、結果が表示されます。
  8. FirebaseコンソールのAuthenticationで「ユーザー」タブを選択し、SMS認証を追加したユーザの3点リーダを押下してオプションメニューを表示。
  9. オプションメニューから「多要素認証を構成」を選択。
  10. ダイアログの「保存」押下。特に編集しなくても現象は発生します。

  11. アプリquickstart-jsに戻ります。手順10でユーザアカウントを編集しているので、ログアウトしているはずです。ログアウトしていなかったら「SIGN OUT」を押下してログアウトします。
  12. もう一度ログインします。今度は手順3~7で追加した第2認証が必要になっていますので、これも認証します。

現象

アプリquickstart-jsでログインしてみると、第2認証のSMS認証の表示名が「N/A」に変わっています。


複数の電話番号を使えば1人のユーザに対して複数のSMS認証を追加できますが、すべてのSMS認証の表示名が「N/A」に変わってしまいます。

第2認証にワンタイムパスワードを使用している場合、ワンタイムパスワードだけ影響をうけません。SMS認証のみで発生します。


最後に

Firebaseのライブラリでいうと、MultiFactorInfo.displayNameがnullになっているようです。表示名を設定する手段はMultiFactorUser.enroll()しか見つからなかってので、消えてしまった表示名を復活させるには、SMS認証をいったん消して再登録するしかないようです。


一応Firebaseのサポートには報告し、「再現できたから開発チームに報告しておく」と回答をいただきました。そのうち修正されるでしょうが影響を受けるのは開発者のみなので、優先順位は低く対応が遅い可能性があります。Firebase Authenticationで多要素認証を実装・デバッグしていると混乱しかねない現象ですので、ご注意ください。

ちなみにFirebaseのサポートとのやり取りには3週間以上かかっています。


2025/06/03

Container RegistryからArtifact Registryへの変更の影響

動機

 少し古い話ですが、Container Registryは2025/3くらいから徐々に停止しています。プロダクトによって具体的な停止のタイミングはいくらか異なるようです。これに伴いContainer Registry→Artifact Registryへの移行が必須となるのですが、この移行により思わぬ影響があったので、ここに記しておきます。


手順

移行は「Container Registry から Artifact Registry に自動的に移行する」による自動移行ではなく、「標準リポジトリへの移行」に従って手作業で移行しています。具体的に変わるのは、Cloud Buildによるコンテナのレジストリへの保存や、レジストリから取り出してCloud Runにデプロイする部分のみだと認識していました。

実際のコマンドだと以下のようになります。

Container Registry

gcloud builds submit --tag gcr.io/プロジェクト名/イメージ名

gcloud run deploy apply --image gcr.io/プロジェクト名/イメージ名 --region=リージョン名

 

Artifact Registry

gcloud builds submit . --pack image=リージョン名-docker.pkg.dev/プロジェクト名/リポジトリ名/イメージ名

gcloud run deploy apply --image リージョン名-docker.pkg.dev/プロジェクト名/リポジトリ名/イメージ名 --region=リージョン名


その他のソースなどは変更不要の認識です。


現象

ところがCloud Runでデプロイしたイメージを実行してみると、動作が違います。ソースとログから解析して、環境変数がなくなっていると判断しました。
Container Registryを使っていたころの該当環境変数は、以下のような感じでDockerfileで指定していました。

ENV 環境変数名 値の文字列


Artifact RegistryだとDockerfileの環境変数は反映されない様子です。


対処

DockerfileをあきらめてgcloudコマンドでCloud Runにデプロイする際に環境変数を指定することにしました。これはContainer Registryでも実績がある方法です。
実際の指定は以下のような感じ。
gcloud run deploy apply --image リージョン名-docker.pkg.dev/プロジェクト名/リポジトリ名/イメージ名 --set-env-vars="環境変数名=値の文字列" --region=リージョン名


これで解決しました。 

ちなみに、複数の環境変数を定義したい場合、"--set-env-vars"の値をコンマで区切って並べます。こんな感じ。

--set-env-vars="環境変数名1=値の文字列1","環境変数名2=値の文字列2"

 

2025/05/06

LotteryServアップデート

 LotteryServを更新しました。今回の更新はセキュリティの強化のみです。そのために利用方法が若干変わった点があり、また新たな制限を追加しています。


3Dセキュア対応

 LotteryServのご利用料金はクレジットカード払いです。クレジットカードの不正利用のリスクを下げるため、EMV 3Dセキュアに対応しました。これは経済産業省の「クレジットカード‧セキュリティガイドライン」に準じるものです。

 以下に説明します今回の更新のその他の変更は、これに伴うものとなっています。


募集の開始・再開ができるユーザを制限

 募集の開始および、休止中の募集の再開ができるユーザを、主催者の支払い方法を登録しているユーザのみに制限しました。

 募集の開始・再開時にご利用料金の上限を決め、クレジットカードに対して支払いの予約を行うため、この制限が必要になりました。

 練習モードではこの制限はありません。


多要素認証に対応

 ログインの際に多要素認証を利用できるようにしました。今回の更新では第2要素に利用できるのは、SMS認証のみです。

 主催者の支払い方法を登録するユーザは、多要素認証の追加を必須としています。


2025/04/21

SMS認証登録のログ「Failed to initialize reCAPTCHA Enterprise config. Triggering the reCAPTCHA v2 verification.」

(2025/04/23)
タイトルに「エラー」と表記していましたが、「ログ」に修正しました。

 現象

Identity Platform/Firebase Authenticationを使用して多要素認証にSMS認証の登録を実装する場合、PhoneAuthProvider.verifyPhoneNumber()で表題のログがブラウザのコンソールに出て失敗することがあります。

Failed to initialize reCAPTCHA Enterprise config. Triggering the reCAPTCHA v2 verification.

実装はGoogleのスニペットどおりですが、web8とweb9で実行結果に違いが出たりします。

対象結果
web8 (namespaced)期待どおり成功
web9 (modular)失敗


調査

Googleのドキュメントにはこのような現象についての記述は見当たりません。

ネットで検索してみると、redditの記事「Firebase Phone Auth reCAPTCHA Error」が見つかりました。他の記事はこの記事の別言語版と、リンク切れのみでしたので、実質たった1つです。

この記事ではReact Nativeで発生しているようですが、私が発生を確認したのはweb9 + Angularの組み合わせです。またこの記事は多要素認証ではなく電話認証のようです。しかし発生している現象はほぼ同じの様子です。この記事でも解決はしていません。


解決

手がかりが全くないので、思い当たるところを勘で変更して動作を確認するという地味な作業を繰り返し、解決方法にたどり着けました。

失敗していた実装は以下のような感じです。MultiFactorUserインスタンスをあらかじめ取得しておき、それを使いまわしていました。


class MfaComponent {
    multiFactorUser: MultiFactorUser;
    ...
    constructor(...) {
        ...
        this.multiFactorUser = multiFactor(ログインユーザのUser);
        ...
    }

    sendSms() {
        this.multiFactorUser.getSesstion()		←ここが原因
        .then((multifactorsession) => {
            const options = {
                phoneNumber: 電話番号,
                session: multifactorsesstion,
            };
            const provider = new PhoneAuthProvider(auth);
            provider.verifyPhoneNumber(options, recaptcha).then((verificationid) => {
                ...
            });


MultiFactorUserインスタンスを必要な時に取得するように変更することで、成功するようになりました。


class MfaComponent {
    ...
    constructor(...) {
        ...
    }

    sendSms() {
        multiFactor(ログインユーザのUser).getSesstion()		←修正
        .then((multifactorsession) => {
            const options = {
                phoneNumber: 電話番号,
                session: multifactorsesstion,
            };
            const provider = new PhoneAuthProvider(auth);
            provider.verifyPhoneNumber(options, recaptcha).then((verificationid) => {
                ...
            });


最後に

無事SMSは送信できるようになったものの、表題のログは出続けています。このログがPhoneAuthProvider.verifyPhoneNumber()が期待動作しなかったことと関係あるのかは不明です。動作には影響してなさそうですが、ちょっと不安です。


2024/10/18

LotteryServアップデート

 LotteryServを更新しました。


抽選の仕組みを更新

 抽選の仕組みを変更しました。

 抽選はユーザの方々からは見えないところで動作しているので、それを変更しても変化はまったく感じていただけません。UIの見た目や使い方にも影響や変化はありません。


価格の変更

 上記の抽選の仕組みの変更により、運用コストを下げることが可能になりましたので、それを価格に反映しました。Google Cloudの利用料金は米ドルで計算されるので、現在も続いている円安により運用コストが高めになっているのは頭が痛いことですが。


ユーザ認証の変更

 ログインや再認証のなどユーザ認証の実装を若干変更しました。Googleアカウントでの認証では、ポップアップウィンドウが出るように変更しています。

 まれにポップアップウィンドウが自動的に閉じられず、認証後も残ったままになることがあるようです。残っていても無害ですが、認証が成功していたらクローズボタンで閉じてください。


2024/10/01

Batch実行時のエラー「java.lang.NullPointerException: Cannot invoke "String.lastIndexOf(int)" because "endpoint" is null」の対処

事象

GAE/JでBatchジョブを起動しようとBatchServiceClient.create()をコールすると、以下のエラーが発生しました。

java.lang.NullPointerException: Cannot invoke "String.lastIndexOf(int)" because "endpoint" is null

ソースコードはGoogleのスニペットどおりで、ヌルポなど発生するわけがないはずです。しかし何度実行しても、ビルドしなおしても状況に変化はありません。


調査

BatchServiceClient.create()ではどのようにしてBatchServiceClientが生成されているのかわかりませんが、BatchServiceClient.create(BatchServiceSettings settings)メソッドを使用して自分でBatchServiceSettingsを生成して渡せば、生成されるBatchServiceClientの内容をある程度推測できそうです。
とりあえず以下のようなスニペットでBatchServiceSettings.newBuilder()でデフォルト設定のBatchServiceSettingsを生成し、別のBatchジョブの起動に成功しているプロジェクトとBatchServiceSettingsの内容を比較してみました。

	BatchServiceSettings settings = BatchServiceSettings.newBuilder().create();

生成されたBatchServiceSettingsの内容で、有意な差異は以下のとおりでした。

成功しているプロジェクト :
	endpoint=batch.googleapis.com:443,
失敗するプロジェクト :
	 endpoint=null,

エラーメッセージどおりですが、endpointがnullです。


endpointは文字列ですし、BatchServiceSettings.Builder.setEntpoint(String endpoint)で設定できます。そこで強制的にendpointに成功しているプロジェクトと同じ値をセットしてBatchServiceSettingsを生成し、それを渡してBatchServiceClientを生成してみると、発生するエラーが以下に変わりました。

com.google.api.gax.rpc.PermissionDeniedException: io.grpc.StatusRuntimeException: PERMISSION_DENIED: Batch API has not been used in project プロジェクト名 before or it is disabled.

Batchが有効になっていない...


解決方法

その1

BatchのAPIを有効にします。GCPコンソールからなら以下の手順になります。

  1. GCPコンソールの「APIとサービス」-「ライブラリ」を表示。
  2. 「APIとサービス」にBatchと入力してBatchを探す。
  3. 検索結果のリストから「Batch API」をクリック。
  4. Batch APIのページの「有効にする」をクリック。



Batchは手動で有効化する必要があったのを忘れていただけでした。そして最初に目にするエラーメッセージはそれを連想しにくいものなので、気づけないというワナもあったということでした。


その2

Batchを有効化し、BatchServiceClient.create()のコールをGoogleのスニペットどおりに戻してみたのですが、相変わらずこの記事の最初と同じヌルポが発生したままです。
とりあえず上記調査と同様にendpointを強制的に設定することで、Batchジョブの実行はできるようになりました。

しかしなぜプロジェクトによって挙動が違うのかは不明のままです。

2024/08/26

Firestore/Datastoreで複数の範囲フィルタを使ってクエリが可能に

Firestoreが登場する前の昔のDatastoreから、Firestore/Datastoreのクエリには「不等式はクエリ内で1つだけ」という制限があったのですが、2024/7/29にやっと解除されました。

上記リンクはFirestoreですが、Datastoreも同様のページがあります。Datastoreの日本語ページにはプレビューマークがついていますが、リリースノートにはGAと説明されています。

この制限のためにこれまで「DBに範囲を記録しておいて、指定の値がその範囲内にあるデータを検索」ができませんでした。具体的には以下のようなケースです。
  • 開始・終了日時を保存しておき、指定の日時に対応するデータを検索。
  • 上限・下限の金額を保存しておき、指定の金額に対応するデータを検索。
  • etc.

ただし無制限になったわけではなく、少ないながらも制限事項もあるようです。検索時間などパフォーマンス面も未検証なので、遅くないのかなど気になります。

これまではこの制限を回避するためだけにSearch APIを利用したりElasticsearchをインストールしたりといった対応が必要だったのですが、だいぶFirestore/Datastoreのみで検索ができるようになりそうです。

2024/07/17

vsReversiアップデート

 vsReversiをアップデートしました。


仕様変更

  • 以下のアカウントによるログイン/新規登録を廃止。
    • FaceBook
    • twitter

不具合修正

  • ブラウザでクロスオリジン・リダイレクト・ログインがサポート停止された影響でログインできないケースがあったので、ログインをポップアップウィンドウに変更。

FaceBookアカウントによるログインは維持するのが難しくなったので、廃止しました。
FaceBookは定期的にアカウントなどを利用する機能に対する審査を行っており、機能の提供を受けるためにはその審査を通過する必要があります。審査の内容や、通過しなかった場合の対応の仕方は毎年変わります。昨年まではサポートやり取りしながらなんとかなりましたが、とうとう維持する手間が見合わないところまで来ました。
最近はあまり使われていないようですし、メールアドレスでも利用可能なのでサポート外とすることにしました。
twitterは今のところそのようなことはないのですが、Xに変わってから収益化のために一部サービスの有料化を進める可能性があるようです。今後有料になる可能性もあると考えられますが、vsReversiの本来の目的はデモンストレーションなので、手間暇や運用費用をかけられません。そのため同時にサポートを廃止することにしました。幸いtwitterアカウントによるユーザは登録されていません。

2024/07/01

Google Domains停止の影響

経緯

Google Domainsが新規ドメインの登録を停止し提供終了したのが2023年、それまでGoogle Domainsが管理していたドメインはそのまま放置していればSquarespaceに移管されます。

特にSquarespaceに不満があるわけでもないのですが移管後は価格が高くなるという話もあり、カスタムドメインの更新期限を迎える機会に日本のレジストラに移管することにしました。

それに伴っていろいろとトラブルが発生したので、今回はそれについてです。


まずはドメイン登録事業者の選択

ドメイン登録事業者によって結構価格が異なるので一応比較しました。事業者の比較記事はたくさんあるのでここでは比較の結果は載せませんが、気づいたのは以下。
  • 海外の事業者は今回は比較することなく選外。
  • 売り込みDMがうざいと悪評高い お名前.com も選外。
  • GMOはなんで3つもあるの???
  • さくらインターネットは高い。
  • 知名度あまりない会社も多い。

トラブル1

最初に選んだのは ValueDomainです。webサイトからユーザ登録してドメイン移管の依頼をしてしばらく待つだけです。
しかし1週間たっても全く何の連絡もなく、移管の作業が進んでいる気配もありません。しかしクレジットカード決済だけは支払い済みという、嫌な状況に... サポートに問い合わせしてみると「移管の手続きがされた形跡がない」「すでに決済済み」という状況であるとの回答がありました。
状況が詐欺と同じです。何のためのクレジットカード決済でしょうね、信用できません。

すぐに移管も請求もキャンセルの旨連絡を入れると、「キャンセルの際はポイントで還元」とか意味不明な回答。「返金で対応して」と要求して、なんとかなかったことに。

トラブル2

最初のトラブルに比べればずっと小さい小さいトラブルですが。

しかし返金がなかなか確認できません。これはクレジットカード会社のwebサイトに反映されるまでに1週間もかかることが原因です。そんなに反映遅いって、いつの時代の仕組みを使いまわしているんでしょう。

トラブル3

返金待ちの間にStarDomainにドメイン移管を依頼しました。今度は依頼や決済のトラブルもなく、すなんり依頼完了。
しかし数時間で「移管不可」の回答がありました。理由が明記されていなかったのでサポートに連絡して理由を確認したところ、WHOISで代理公開しているので「登録されたEメールアドレスが確認できない」とのこと。他の事業者ではこのような理由で拒否されたことはないので、これはStarDomain独自の仕様だと思われます。
WHOISの代理公開を停止して待つこと3日、やっと依頼が通過し、Google Domainsから移管の確認メールが来ました。

トラブル4

ここまででドメイン移管までは完了したものの、カスタムドメインが解決できずDNSエラーになるという事象が発生。StarDomainの管理画面にネームサーバやDNSSEC設定の警告が表示されていたのですが、その警告についてマニュアルには記載がありません。サポートに問い合わせてみると、DNSレコードの設定を有効にするために以下の操作が必要とのことでした。
  1. DNSSECを解除して (これはサポートに依頼が必要)、
  2. ネームサーバをスタードメイン専用に変更し、
  3. DNSレコードを設定。
以上は、マニュアルには全く記載がありません。警告から推測はできるものの、こんなのわかるわけがない仕様です。
以上を設定して、やっとカスタムドメインが復活しました。

トラブル5

Looker StudioでSearch Consoleからデータ取得して各ドメインの表示数・クリック数の分析を行っていたのですが、ドメイン移行でデータ取得できなくなりました。Googleのサービス内で連携するからこそ実現できていた機能です。

最後に

カスタムドメイン移管を行ってみて、感じたことをまとめてみます。
  • トップレベルドメインによってはGoogle Domainsは意外と安価で高機能だったということです。なぜ事業売却したんだ。結局移管して2割ほどですが、料金は上がりました。
  • ValueDomainの運営会社であるGMOインターネットは意外と怪しい企業かもしれません。何らかの関係を持つのは今回が初めてでしたが、詐欺と変わらない状況で実際にお金の請求にまで至ったのは、長いネット利用歴があるにもかかわらず今回が初めてです。
    またお名前.comと同じようにValueDomainもユーザ登録後は毎日のように売り込みのDMが届きます。かまってちゃんなウザい組織です。
  • StarDomainの運営会社であるネットオウルは、少しはまともそうです。サポートの対応は遅くはありませんが、若干稚拙な印象があります。webサイトの完成度はあまりいいとは言えません。作りっぱなしという印象で、マニュアル含めて説明が足らなくてわかりにくいことが多く、経験と勘とサポート頼みになります。改善を提案してみたのですが、「対応しません」と全くやる気のない回答が返ってきました
  • カスタムドメインは一度取得してしまうとそのまま更新を続けるだけなのが普通なので、あまりドメイン管理事業者のwebサイトを操作することもありません。ドメインの手続きだけではいかにも儲かりそうにない事業です。各事業者のUIや運用の改善、事業としての健全化に関して後回しにされている印象を受けました。

2024/05/16

BASICは今年で60才

「BASIC」誕生60周年--コンピューター利用を容易にしたシンプルな言語の歴史』によると、BASICの誕生から2024年5月で60年だそうです。

BASICは私が最初に学んだ言語でもあり、過去(1980年前後)には一世を風靡した言語でした。それ以前にもCOBOL, FORTRANなどの言語もありましたが、目的とする分野以外では使いにくく、理解も容易でないと感じるような代物でした。それゆえBASICはそれらの言語の目的外の分野で、特に情報処理に入門する人達に受け入れられたように思います。


この当時の一般的なPCのスペックは以下のとおり。

  • CPU : バス幅=8ビット、クロック=4MHz
  • メモリ : 64kB
  • 記録媒体 : データレコーダ(カセットテープ) or フロッピーディスク(容量は320kB程度)
  • モニタ : 640×400 (or 480)ピクセル、8色

現在のPCと比べるとゴミ並みにしか見えません... 単純に、バス幅×クロック×メモリ で比較すると...
  • 当時 : 8bit×4MHz×64kB=2,048
  • 現在 : 32bit×4GHz×16GB=32bit×4096MHz×16,777,216kB=2,199,023,255,552
いったい何を計算しているんだろうという疑問は置いておいて、現在は当時の 1,073,741,824(約10億7300万)倍です。

ここでさらに疑問。現在は当時と比べて10億倍のことができるようになったのでしょうか。そんな感じはしません。それどころかせいぜい10倍程度にしか感じません。それだけ無駄なことにいろいろなリソースを費やしているように感じます。

2024/02/29

Cloud Runのインスタンス起動時間

 動機

Cloud Runのドキュメント「実行環境について」については以下の記述があります。
第 2 世代の実行環境は、一般に持続的な負荷の下では迅速に動作しますが、ほとんどのサービスでは、第 1 世代よりもコールド スタート時間が長くなります。
このように書かれると、第1世代/第2世代ともどの程度インスタンスの起動時間がかかるのか、どの程度違うのか気になります。また第2世代のジョブはバックグラウンドで動作するものなので起動時間はあまり気にされるものではありませんが、これも知りたくなってきます。
実行速度は目的によって測定方法も変えることになるので面倒ですが、インスタンスの起動時間については過去の記事「GAEのインスタンス起動時間」「GAEのインスタンス起動時間 #2」と同様に測定できますので測ってみました。


測定方法・条件

今回はCloud Runなので言語やランタイムのバージョンについては、使う人がDockerコンテナを作る際にいいようにすればいいだけの話です。なので純粋にCloud Runのインスタンス起動時間として、Hello World相当のGoでリクエスト→処理開始までを測ることにします。
  • リージョン : 大阪
  • ネットワーク : NTT Flets光 隼、実効300Mbps程度
  • サービス : 
    • ブラウザからAjaxでリクエストし、JavaScriptでレスポンスが返るまでの時間を測定。
    • スピンアップあり/なしの2パターンで、それぞれ10回測定し、平均値を算出。
    • 前記2パターンの差から、インスタンス起動時間を計算。
  • ジョブ : 
    • GAEからジョブを起動し、GAE/Cloud Runそれぞれに仕込んだログから、インスタンス起動時間を測定。
    • スピンアップは毎回行われるのでサービスのような「スピンアップなし」に該当するパターンは無いはず。念のため検証目的で、前回起動から15分以上時間空けてをスピンアップあり相当、前回起動から時間空けずにをスピンアップなし相当として、2パターンでそれぞれ10回測定し、平均値を算出。

測定結果

単位はすべてmsです。測定結果をtableにするのが面倒だったので、今回もExcelのキャプチャ画像です。

スピンアップあり。

スピンアップなし。

そしてインスタンス起動時間。

第1世代第2世代
serviceservicejob
158.7452.59344.4


まとめ


Cloud Runの世代間

公式ドキュメントの記載どおり、インスタンス起動時間は第1世代のほうが速いという結果です。
ジョブの起動時間はおおむね10秒程度でした。ちなみにジョブ終了→GAEで終了を検知も、おおむね10秒程度でした。

GAEとの比較

GAEのインスタンス起動時間 #2」と比較してみるとCloud Runは全体的に遅く、第2世代のサービスだとGAEの素のJavaよりいいくらいになっています。
本稿の趣旨からちょっと外れますが、スピンアップなしのケースではGoだろうがJavaだろうがほぼ確実に100msを切れるGAEに対して、Cloud Runだと3倍程度のレイテンシが発生しています。Webフロントエンド専用のプロダクトとしてgVisorという独自コンテナ技術まで作っただけあって面目躍如といったところで、汎用のDockerコンテナを利用するCloud Runは一歩及びません。

GoのコードはそのままでGAE/Goに実装したRESTful APIを、Cloud Runサービス/Goに変えたところ、ちょっともっさりするようになった気がした経験があります。これは気のせいではなかったと改めて認識しました。
Firebase Hostingには動的コンテンツをCloud Runで配信する機能「Cloud Run を使用した動的コンテンツの配信とマイクロサービスのホスティング」があるのですが、今回の結果を見ると、App Engineにも対応してほしいと思います。

2024/02/09

GAEのインスタンス起動時間 #2

動機

Java17 + レガシーバンドルサービスを実装したところ、GAEインスタンスのスピンアップが若干遅いと感じました。いつの間にかJava21もプレビューになっていましたので、あわせてインスタンス起動時間を再測定してみました。

また前回(GAEのインスタンス起動時間)はログで確認していたのですが、その方法の精度にも疑問を感じたので、測定方法も対象も変更しています。


今回はJava8がすでにサポート終了しているので、対象外としました。


測定条件・方法

  • リージョン : 大阪
  • ネットワーク : NTT Flets光 隼、実効300Mbps程度
  • インスタンスクラスはF1。
  • ServletのアプリはGoogleのサンプルに入っていたHelloWorld。
  • SpringBootのアプリはGoogleのサンプルに入っていたHelloWorldそのままなので、バージョンは2.7.18。
  • レガシーバンドルサービスは、Googleのサンプルは余計なコードが入っていたのでpom.xmlのみ参考にし、Hello World相当を自作。
  • GoもHello World相当を自作、今回はフレームワークなしのパターンのみ。
  • ブラウザからAjaxでリクエストし、JavaScriptでレスポンスが返るまでの時間を測定。
  • スピンアップあり/なしの2パターンで、それぞれ10回測定し、平均値を算出。
  • 前記2パターンの差から、スピンアップ+VM起動+フレームワーク起動の時間を計算。

測定結果

単位はすべてmsです。測定結果をtableにすると横長になってレイアウトが崩れたので、画像です。
まずはスピンアップあり。

続いてスピンアップなし。

そして、スピンアップ+VM起動+フレームワーク起動の時間。
Servletspringレガシー
Java11625.24728.62098.6
Java17599.84769.21655.0
Java21630.24622.92451.5
Go1.20176.9--


所感

起動時間は 17<11≒21。わずかとはいえ、最新の21で悪化しているという意外な結果に。まだプレビューなのも影響しているのでしょうか。

SpringBoot

前回と比べてバージョンが2.6.6→2.7.18と変化していますが、結果はほぼ同じ。他はJava21で遅いのに、なぜかspringだけはJava21が最速と、一致しません。なぜ...

レガシーバンドルサービス

遅い気がしたのは気のせいではありませんでした。Java8のスピンアップが遅かったのはもしかして、Googleのカスタマイズのせいだったのではという疑惑が生じます。そしてJava21での遅延が目立って大きくなっています。残念過ぎる...