AppEngineスタンダード環境のチューニング

# AppEngineスタンダード環境のチューニング

## はじめに

こんにちは、京セラコミュニケーションシステム　五十嵐（@kccs_hironobu-ikarashi）です。

現在、Google Cloud上で構築されたIoTデバイスからのデータの受信、集計、分析、見える化等を行う基盤の開発・運用・保守をしております。

構築当時は接続デバイス数も少なかったため、Google Cloud利用料はたいしたことはありませんでしたが、日々接続デバイス数やデータ量の増加に伴い、Google Cloud利用料も目立ってきたため、費用削減を目的に各プロダクトのチューニングを実施しています。
今回はAppEngineのチューニングについて内容をまとめましたので、参考にしていただければ幸いです。

:::note info
本記事は 2024 年 03 月ごろに実施した内容を記事にしておりますので、ご了承ください。
記事の内容は筆者の理解をベースに実施したものとなり、必ずしも効果を保証するものではありません。
:::

## 本記事の対象者
- AppEngineスタンダード環境を利用している方
- 課金額を減らしたい方

### 環境情報

- AppEngineスタンダード環境（asia-northeast1リージョン）
- 数万台のデバイスが接続されており、10分毎に計測したデータをサーバに送信
- 送信タイミングはばらつきがあり、とくに0分台（00分、10分、20分、…）と3分台（03分、13分、23分、…）にアクセスが集中する
- automatic_scalingを設定しており、インスタンス数（作成）は、70台~350台で推移している（下記画像参照）
※Google Cloudコンソールの「AppEngine」>「インスタンス」より確認可能

【構成図】
|![図1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794674/8f86b028-bbcd-89ff-fe8e-2f5218aa4f44.png)|
|:--|

【インスタンス数】
|![図2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794674/f075fcfc-488e-f6c2-67fb-4a8f1ccc1294.png)|
|:--|

#### チューニング内容

|設定|デフォルト値||
|:----|:----|:----|
|target_throughput_utilization|0.6|※1
|max_concurrent_requests|10|※1
|max_idle_instances|automatic|※2

※1の2項目によって、同時リクエストによって新しいインスタンスが起動するタイミングを指定できます。

※設定の詳細は[公式のAppEngine app.yamlリファレンス](https://cloud.google.com/appengine/docs/standard/reference/app-yaml?hl=ja&tab=go)を参照

リファレンスによると
> max_concurrent_requests と target_throughput_utilization の積に等しい値に達すると、スケジューラは新しいインスタンスを起動します。

とあるので、デフォルト値の場合では2つの値の積が6となり、同時に6リクエストを超えるとインスタンスが新しく起動するため、こちらの設定値(今回は`max_concurrent_request`)を大きくしていきながらチューニングしていきました。

> target_throughput_utilization × max_concurrent_requests = 0.6 × 10 = 6

※2の`max_idle_instances`は保持できるアイドル状態のインスタンスの最大数の設定となるため、こちらを減らすことでインスタンス数を抑えます。

#### チューニング手順

①それぞれmax_concurrent_requests, max_idle_instancesの値を変えたバージョンを作成しました。

|設定|1-4-1b(現行環境)|1-4-1b-12|1-4-1b-18|1-4-1b-24|1-4-1b-24-20|1-4-1b-24-10|
|:----|:----|:----|:----|:----|:----|:----|
|target_throughput_utilization|0.6|0.6|0.6|0.6|0.6|0.6
|max_concurrent_requests|10|20|30|40|40|40
|max_idle_instances|30|30|30|30|20|10

※設定方法は、AppEngineデプロイ時に、app.yamlでそれぞれ設定項目をセットします。
* app.yamlの内容（上の表の1-4-1b-24-10の場合の設定）
```yaml
app_engine_apis: true
runtime: go121
env: standard
instance_class: F1
handlers:
  - url: /.*
    script: auto
  - url: .*
    script: auto
automatic_scaling:
  min_idle_instances: automatic
  max_idle_instances: 10
  min_pending_latency: automatic
  max_pending_latency: automatic
  max_concurrent_requests: 40
  target_throughput_utilization: 0.6
service_account: XXXXXXXXXXXXXXXXXXX
```

②パフォーマンスが落ちないことを確認しながら、バージョンを切り替えて確認していきます。※下記画像のように「Metrics Explorer」にて確認してきます。

確認観点は下記4項目。
1. 作成されるインスタンス数が減少すること　　　　　※画像の「A」のグラフ
2. レスポンスコードが200以外の件数が増加しないこと　※画像の「B」のグラフ
3. 保留中のリクエスト数が増加しないこと　　　　　　※画像の「C」のグラフ
4. レスポンスのレイテンシが増加しないこと　　　　　　※画像の「D」のグラフ

* 「1-4-1b-24-10」の場合

※下は1バージョンのみ表示していますが、画像の4クエリを複製してversion_idを比較したいバージョンに変更すれば、変化が分かりやすいです。
(当時のデータがなかったので2バージョンが表示されている画像は取れませんでした。)
|![図3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794674/bf36fe63-5fb8-a524-f815-177d702dfb7d.png)|
|:--|

①`1-4-1b-12` ⇒ `1-4-1b-18` (`max_concurrent_requests`が20 ⇒ 30)ではパフォーマンスが変わらずに作成されるインスタンス数が減少

②`1-4-1b-18` ⇒ `1-4-1b-24` (`max_concurrent_requests`が30 ⇒ 40)では作成されるインスタンス数に変化はなかったため`max_concurrent_requests`は40で決定

③次に`1-4-1b-24` ⇒ `1-4-1b-24-20`(`max_idle_instances`が30 ⇒ 20)ではパフォーマンスが変わらずに作成されるインスタンス数が減少した

④`1-4-1b-24-20` ⇒ `1-4-1b-24-10`(`max_idle_instances`が20 ⇒ 10)では作成されるインスタンス数に変化はなかったため`max_idle_instances`は10で決定

### チューニング結果

`1-4-1b`（チューニング前）: 約70台~350台

`1-4-1b-24-10`（チューニング後）: 70台~170台

※月額でおよそ￥100,000の削減ができました。

## おわりに

本記事では、AppEngineスタンダード環境のチューニングについて投稿させていただきました。

今後は他のプロダクトで実施した内容などを投稿する予定ですので、楽しみにしていただければと思います。