GAE ModulesをSimpleに使う

GAEには [Backend API](https://developers.google.com/appengine/docs/java/config/backends?hl=ja "Backend API") という機能がありましたが、SDK 1.8.2で [Modules API](https://developers.google.com/appengine/docs/java/modules/ "Modules API") がリリースされ、その後、Backend APIは非推奨となりました。

このTopicではModulesとは何か？、Modulesの使い方、そして既存アプリの簡単な移行手順について説明します。

# Modulesとはなにか？

元々GAEにはVersionという機能がありましたが、Modulesはその上にもう1階層を作ったサービスです。
既存のGAEAppのVersionは、Modulesではdefault Modulesの各Versionという扱いになります。

Backend APIではVersionの1つとしてdeployされていたため、FrontEndのようにVersion管理ができませんでしたが、Modules APIではBackend用に用意したものもVersion管理できるようになります。

また、Backend APIは、instanceの生存時間が無制限とDocumentには書いてありましたが、15分ぐらいでよく落ちるという悲しみを背負っていました。
Modules APIではそのあたりも改善されたようで、15分を超えても問題なく動いています。

## スケーリング設定

Modulesより前はPerformanceの設定は以下の3項目でした。

* Frontend Instance Class
* Idle Instances
* Pending Latency

しかし、Modulesより後は、この設定が大幅に強化されています。
まず、スケーリングの仕方そのものを以下の3つから選びます。

* Automatic Scaling
* Manual Scaling
* Basic Scaling

ここでは概要のみ説明しますので、詳細については、[こちら](https://developers.google.com/appengine/docs/java/modules/?hl=ja#Java_Instance_scaling_and_class "こちら") を確認してください。

### Automatic Scaling

従来のFrontEndのinstanceのスケーリングに最も近い設定です。
60秒Deadlinesも有効だが、TQから実行した場合はDeadlinesの制限が10分になります。
従来の設定と同じようにmin-idle-instances, max-idle-instancesを指定できますが、従来のmin-idle-instancesとは違い、実際に待機用のinstanceが立ち上がるようになったので、注意が必要です。
待機用のinstanceはResidentと呼ばれ、Dynamicに立ち上がったinstanceとは区別されます。

![スクリーンショット 2014-07-15 0.14.40.png](https://qiita-image-store.s3.amazonaws.com/0/15640/132119eb-85ef-0eaf-57a7-a0791677385b.png)

Backendとして利用するModulesにも設定できるので、小さなinstanceのたくさん立ち上げて処理したい場合には、最適です。

### Manual Scaling

アクセス数に応じたオートスケールなどは行われず、自分でinstance数を設定します。
常に固定数のinstanceを立ち上げたいようなModuleに対して指定します。
例えば、常時Backendで処理を行わすようなものなどです。

### Basic Scaling

Automatic ScalingとManual Scalingのハイブリッドのような設定です。
Deadlinesやinstance typeはManula Sacalingと同じだが、アクセス数に応じてオートスケールします。
1日1回実行される長時間のバッチ処理や、それなりに時間がかかる上にスケールして欲しい場合などに設定します。

## ルーティング

Versionの場合は、.区切りもしくは-dot-区切りで、URLを指定することで対象のVersionにRequestしていましたが、Modulesでも同じようにアクセスします。
例えば、hoge Module a versionにRequestする場合は以下のように指定します。


http://a.hoge.example.appspot.com/
https://a-dot-hoge-dot-example.appspot.com/

また、hoge Moduleのdefault versionにアクセスするには以下のように指定します。

http://hoge.example.appspot.com/
https://hoge-dot-example.appspot.com/

この場合、default Moduleにhoge versionがある場合、ぶつかってしまうのではないかという懸念を抱いた方もいると思いますが、default Modulesにhoge versionがある場合、hoge Moduleはdeploy時にerrorになります。

また、1つ気を付ける点は、指定したversionが無い場合、default versionに飛ぶようになっていることです。
例えば、hoge Moduleにb versionが無い場合に、以下のように指定した場合、hoge Module default versionにRequestが飛ぶようになっています。

https://b-dot-hoge-dot-example.appspot.com/

## Modulesを使う

Modulesを使うのはとても簡単です。
appengine-web.xmlにModules用の設定を書くだけです。

```appengine-web.xml
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>simple-app</application>
  <module>default</module>
  <version>uno</version>
  <threadsafe>true</threadsafe>
  <instance-class>F2</instance-class>
  <automatic-scaling>
    <min-idle-instances>1</min-idle-instances>
    <!-- ‘automatic’ is the default value. -->
    <max-idle-instances>automatic</max-idle-instances>
    <!-- ‘automatic’ is the default value. -->
    <min-pending-latency>automatic</min-pending-latency>
    <max-pending-latency>30ms</max-pending-latency>
    <max-concurrent-requests>50</max-concurrent-requests>
  </automatic-scaling>
</appengine-web-app>
```

上記はAutomatic Scalingでの設定の例です。
この状態でdeployするだけで、Modulesとして動作するようになります。

Modulesを利用する方法として、[公式Document](https://developers.google.com/appengine/docs/java/gettingstarted/creating?hl=ja "公式Document")では、earを設定してwarを複数用意するという内容を紹介していますが、こんなに大げさなことをする必要があるアプリを作ることは私はありませんので、deploy用のshellを作成し、deploy時に、appengine-web.xmlを差し替えています。

例えば、以下の様なファイルを用意しておき、shellでappengine-web.xmlにリネームしてdeployします。

```appengine-application-backend.xml
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>simple-app</application>
  <module>backend</module>
  <version>uno</version>
  <threadsafe>true</threadsafe>
  <instance-class>B8</instance-class>
  <basic-scaling>
    <max-instances>11</max-instances>
    <idle-timeout>10m</idle-timeout>
  </basic-scaling>
</appengine-web-app>
```

# 既存アプリの移行

appengine-web.xmlの設定を変えるだけで、Modulesとして動作するようになるわけですが、ModulesとしてではないアプリをdeployしているProjectの場合は、最初にGAE Admin Consoleでいくつか設定する内容があります。

1. Application Settings -> Performance Settings Migration for Modulesにある"Migrate Settings" buttonを押す

![スクリーンショット 2014-07-14 20.46.25.png](https://qiita-image-store.s3.amazonaws.com/0/15640/03b5708a-8d97-f21d-7a42-36e7129ea034.png)

2. Are you sure you wish to migrate your performance settings? と聞かれるので、"Yes, migrate" buttonを押す。"Yes, migrate" buttonは画面の下の方にあるので注意してください。

![スクリーンショット 2014-07-14 20.46.59.png](https://qiita-image-store.s3.amazonaws.com/0/15640/a104560e-f442-2ec5-62d5-6c110ffa806c.png)

![スクリーンショット 2014-07-14 20.47.06.png](https://qiita-image-store.s3.amazonaws.com/0/15640/edef716c-ce18-c049-047e-890645333fff.png)


これで設定は完了です。
ただ、この設定を行うと、Modulesでは管理コンソール上から、スケーリングの設定を変えることはできないため、ちびちびmax-idle-instancesを管理コンソールからいじるということはできなくなります。
appcfg.pyに指定したModules versionのスケーリング設定のみをdeployするという機能があれば良いのですが、今のところ、そのような機能は見当たりません。

### sourceの修正

backendsとして利用していたものをModulesに移行する時に、いくつか修正する必要がある場合があります。

1. BackendService -> ModuleService

BackendServiceを使っていた場合、ModuleServiceを使うように修正する必要があります。
だいたい似たような機能があるので、そんなに苦労はせずに移行できるはずです。

2. queue.xml targetの修正

Modulesでもqueue.xmlのtargetを同じように利用することができます。
targetにModule名を指定すれば、指定したModuleのdefault versionにRequestが飛びます。
ただ、元々queue.xmlのtargetとして、backend versionを指定していた場合、Moduleはdefault moduleのversion名とかぶってはいけないという制約があるので、違う名前に修正する必要があると思います。
ここも名前を付け替えるだけなので、あっさり終わると思います。

# おわり

ざっくりとですが、Modules APIの説明でした。Modules APIは便利な機能ですが、日本語の記事が無いためか、あんまり利用されているのを見ないので、書いてみました。

みなさまの手助けになれば、幸いです。