*

GAEでよくあるエラーの発生原因と対策1

公開日: : 最終更新日:2016/02/02 投稿者: GAE , ,

GAE上で動くWebアプリケーションに特有の例外について、弊社での運用の事例からいくつか特徴的なものなどをピックアップしてご報告します。

今後追加して行きますので。第一弾です。

Java 7, SDK 1.8.8の環境です。

TooManyResultsException

発生要因

DatastoreからPreparedQuery.asSingleEntity()を利用して1エンティティを取得しようとしたとき、 複数のエンティティが取得された場合に発生するエラー。

原因例

1件だけのはずが複数返却されてきています。原因はいくつかありますが、

  1. データが論理矛盾を起こしている
  2. 設計を理解せず複数取得されるのが当然のクエリに対して、asSingle()をしてしまっている

あたりが主な原因です。

対策案

原因が1番の状況では、データをユニークにすることが一番初めに検討するべき対策となるでしょう。
データをユニークにする一番簡単な方法は、ユニークにするべき値(例えば○○IDやアカウント名など)をKeyオブジェクトにセットしてしまう方法でしょう。
Keyオブジェクトが同じentityは、登録する時に必ず一つになります。

ですが、そうもいかないケースもあり得ます。

特にユーザに関するレコードは、メールアドレスをキーにユニーク性を持たることはよくあるケースです。

単純にメールアドレスをKeyにしてしまえばよさそうなものですが、メールアドレスは変更可能ですので、 Keyには別のIdを振って(自動採番など)、なんらか別のロジックでメールアドレスによる一意制約を担保する必要があります。

原因が2番の状況では、データの設計をちゃんと共有することが、なにより重要です。あまりにも当然ですが。

DeadlineExceededException

発生要因

リクエストを60秒以内に処理できなかった場合に発生するGAE特有のエラー。 同一インスタンス上の他のリクエスト諸共Killされることもあるので、非常に厄介である。

原因例

大量にデータを処理する場合や、他システムとの通信を行う場合に発生します。

たまたまDatastoreやMemcacheからのレスポンスに時間がかかったりすると意外と簡単に発生します。

対策案

方法1:TaskQueueやModulesを積極的に利用する。

大量データを処理する場合は、TaskQueue(10分)、Modulesを利用するようにします。

特に大量に処理することがわかっている場合は、何度でも繰り返し実行可能なような仕組みを考える必要があります。

順次処理をするのであれば、件数をこなすために、繰り替えし繰り替えし実行するしか手段がありません。

そうではなく、同時並行で処理することが可能であれば、そちらのほうがより効果的です。

同時処理でも問題ないか見極めた上で、 1つのタスクをなるべく5分以内に処理ができるようにし、TaskQueueにどんどん登録してしまいましょう。

TaskQueueで同時実行数制限が可能なので、とにかくTaskQueueに放り込んでしまい、あとはお好きな並行数で勝手に処理させるのがCloudっぽくてオススメです。

方法2:Timeoutはリトライをするよう心がける。

他システムとの通信の中には、Googleの他のサービスへのアクセスも含まれるので注意が必要です。

Googleの他のサービスとは、Oauth認証、Drive、メール送信などが分かりやすいと思います。

この場合はDeadLineExceededの前にSocketTimeoutExceptionになることも多いので合わせて注意しましょう。

またMemcacheサービスでたまに応答時間が長くなってしまう事象が起きたりしても結果的にこの例外になりますので、例外を適切にハンドリングしたり、リトライをするようにコーディングしましょう。

特にError Code 104 が発生した場合、そのインスタンスで動いているリクエストが全て中断され、 インスタンスがリセットされるので、FrontEndはとにかく60秒制限を意識して実装する工夫が必要となります。

SocketTimeoutException

発生要因

Oauth認証、DriveなどでURLConnectionを使ってreadする場合に起きやすい。

原因例

ネットワーク越しに処理をする場合は、GAEに限らず必ずTimeoutを意識しましょう。

防げるものではないので発生することを前提としてコーディングするのが鉄則です。

その場合、Connectionの開放もれなどを防ぐために、try-with-resources Statementを積極的に用いるといいです。

対策案

いずれの場合も数秒のTimeout時間を設定し何回かリトライをするように実装します。

あまり多くの時間を設定したり、リトライ回数を無限にするのは控えましょう。 前述の時間制限があることを忘れないようにしてください。

タイムアウトには大きくは2種類あります。

1.connect timeout
connect timeoutは接続にかかった時間で、setConnectTimeoutでタイムアウトする時間を設定できます。

引数はミリ秒で指定し、0を指定すると無限になります。

繰り替えしになりますが、GAEのFront Endの場合は数秒程度が望ましいです。

2.read timeout
read timeoutはデータ取得にかかった時間で、setReadTimeoutでタイムアウトする時間を設定できます。

引数はミリ秒で指定し、0を指定すると無限になります。

一節によると以下のメソッドで発生するらしいので気をつけましょう。

  • getContent
  • getHeaderFields
  • getInputStream
  • getResponseCode
  • getResponseMessage

リトライサンプルコード

以下、Java 7でtry-with-resources Statementを使った例です。

このコードがメソッドにあたり、この上位でfor文によるリトライをします。

[java]
URLConnection connection = new URL(BASE_URL).openConnection();
connection.setConnectTimeout(3000);
connection.setReadTimeout(3000);

try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"))) {
StringBuilder line = new StringBuilder();

String inputLine;
while ((inputLine = in.readLine()) != null) {
line.append(inputLine);
}
}
[/java]

以上、如何でしたでしょうか。今後も追加出来るものができたら追加して行きます。

この記事を書いた人

kimura
kimura
Webデザイナー。本サイトの管理・デザイン担当をしております。
 

関連記事

AppEngineでTwilioを試してみた(応用編)

AppEngineでTwilioを試してみた(基本編) AppEngineでTwilioを試し

記事を読む

Google App Engine Modules in Javaを試す WebToolsPlatform編

みなさんこんにちは。 2013年の7月に、Google App Engine1.8.2がリリー

記事を読む

GAE/JからBigQueryへのStream Insert

今回はGAE/JからBigQueryへのStream Insertを試してみます。 BigQuer

記事を読む

WordPressをGAEで簡単に使う10のステップ

2015/10/05 テーマやプラグインの追加・変更方法について下部に追記しております。 み

記事を読む

Search API詳細解説 Part1「Search API 概要説明」

Google App Engine(以降GAE)に全文検索サービスであるSearch APIが正式リ

記事を読む

1つのエンティティにプロパティをいくつまで作れるか(パート2)

1つのエンティティにプロパティをいくつまで作れるか 1つのエンティティにプロパティをいくつまで

記事を読む

東京リージョンによってGAEの速度は早くなったのか!?

ついにGAEに東京リージョンが新設されました!!サービス開始からGAEを触れていたユーザにと

記事を読む

Search API詳細解説 Part5「Search API 詳細 反映速度編」

Search API詳細解説シリーズ タイトル Part1Search API 概要説明

記事を読む

Search API詳細解説 Part3「Search APIの使い方 検索編」

Search API詳細解説シリーズ タイトル Part1Search API 概要説明

記事を読む

Search APIの「Faceted Search」を使ってみた

Search API詳細解説シリーズは完結しましたが、2015年2月19日のAppEngine SD

記事を読む

PAGE TOP ↑