色聴者判定テスト > Google App Engine 非同期URLFetch、FetchAsync()の使い方

Google App Engine 非同期URLFetch、FetchAsync()の使い方

このページでは、非同期URLFetch、FetchAsync()の簡単な使い方を解説します。

このページの中で何か分からないことがありましたら、 @ts_3156に何でも聞いてください。
「このコードのここの意味が分からない」とか、何でも大丈夫ですよ(^-^)

Google App EngineにはURLFetchと呼ばれる機能があります。この機能を使えば、いろいろなURLからデータを取ってくることができます。 非同期じゃない普通のURLFetchについては 『URLFetchの使い方』 このページを参考にしてください。

非同期URLFetchとは

普通のURLFetchだと、各URLのデータを順番に取得することになります。データを取得したいURLが3つあった場合、1つ目のURLからのデータ取得が 完了してから2つ目のURLにアクセス、2つ目のURLからのデータ取得が完了してから3つ目のURLへアクセス、といった具合です。
これでは、30秒制限なんてあっという間に超えてしまいます。

非同期URLFetchを使うことにより上記の問題は解決します。3つのURLに同時にアクセスを開始することにより、1つ目のURLの待ち時間に 2つ目と3つ目のURLからデータを取得できるようになります。これによって待ち時間が大幅に縮むので、大量のURLへのアクセスが簡単にできるようになります。

サンプルコードの解説の前に、Google App Engine公式情報のリンクも載せておきます。
非同期URLFetchの情報は英語のページにしか書いていないので英語のページのリンクを載せておきます。
URL Fetch Java API Overview
URL、HttpURLConnectionを使ったURLへのアクセス
URLFetch Java API一覧

このページの内容で分からないところとかがあったら、@ts_3156 に何でも聞いてください。

非同期URLFetchの具体的なコード

あれこれ説明するよりも具体的なコードを見た方が早いと思うので、サンプルコードを載せてから解説します。

importするのは以下のクラスです。

import java.util.concurrent.Future;

import com.google.appengine.api.urlfetch.FetchOptions;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;

ArrayList<URL> urlList = new ArrayList<URL>();
urlList.add(url1);
urlList.add(url2);
urlList.add(url3);
ArrayList<Future<HTTPResponse>> responseList = new ArrayList<Future<HTTPResponse>>();

for(int i = 0; i < urlList.size(); i++){
	URLFetchService ufs = URLFetchServiceFactory.getURLFetchService();
	responseList.add(ufs.fetchAsync(urlList.get(i)));
}

for(int i = 0; i < responseList.size(); i++){
	// データの取得が完了するまでここでブロックされます
	HTTPResponse response = responseList.get(i).get();
	byte[] content = response.getContent();
}

これが必要最小限の構成で非同期URLFetchを使うプログラムです。GETメソッドでurlのコンテンツを取得してきます。

ArrayList<URL> urlList = new ArrayList<URL>();
urlList.add("http://www.egotter.com/?user=yamada&id=1234");
urlList.add("http://www.egotter.com/?user=suzuki&id=5678");
ArrayList<Future<HTTPResponse>> responseList = new ArrayList<Future<HTTPResponse>>();

for(int i = 0; i < urlList.size(); i++){
	URLFetchService ufs = URLFetchServiceFactory.getURLFetchService();
	HTTPRequest request = new HTTPRequest(urlList.get(i), HTTPMethod.GET);
	request.addHeader(new HTTPHeader("original-header", "test"));
	responseList.add(ufs.fetchAsync(request));
}

for(int i = 0; i < responseList.size(); i++){
	// データの取得が完了するまでここでブロックされます
	HTTPResponse response = responseList.get(i).get();
	byte[] content = response.getContent();
}

ヘッダやパラメータを追加するとこのようになります。GETメソッドなのでURLにパラメータを埋め込みましたが、POSTメソッドの時はどうするんですかね…。 2010年10月の時点では、POSTのパラメータを追加するようなAPIは存在しません。

// urlListの作成は省略
ArrayList<Future<HTTPResponse>> responseList = new ArrayList<Future<HTTPResponse>>();

for(int i = 0; i < urlList.size(); i++){
	URLFetchService ufs = URLFetchServiceFactory.getURLFetchService();
	HTTPRequest request = new HTTPRequest(urlList.get(i), HTTPMethod.GET, Builder.disallowTruncate().setDeadline(10.0));
	request.addHeader(new HTTPHeader("original-header", "test"));
	responseList.add(ufs.fetchAsync(request));
}

for(int i = 0; i < responseList.size(); i++){
	// データの取得が完了するまでここでブロックされます
	HTTPResponse response = responseList.get(i).get();
	byte[] content = response.getContent();
}

disallowTruncate()を追加しました。これにより、レスポンスが大きすぎるときはResponseTooLargeExceptionをだすようになります。Exceptionを ださずに大きすぎるレスポンスを切り捨てる場合は、allowTruncate()を使います。
setDeadline(10.0)により、URLFetchのタイムアウト時間を10秒に設定しました。最大が10秒です。デフォルトのタイムアウト時間は5秒です。5秒だとすぐ失敗します。 「Java版のURLFetchにはタイムアウト時間を変更できないバグがある」という解説をたまに見かけますが、2010年10月の時点ではちゃんと10秒に設定できます。

このページの中で何か分からないことがありましたら、 @ts_3156に何でも聞いてください。
「このコードのここの意味が分からない」とか、何でも大丈夫ですよ(^-^)

色聴判定テスト一覧
テストはどれも10分ほどで終わります
推奨環境
・Internet Explorer7以降
・Firefox3以降
判定テストについて
これまでに 1541人 がテストを受けました
09/12/28~12/02/02
更新情報
・12/10/14
twitterの埋め込み方法を更新しました
・12/01/11
共感覚面白ニュースを更新しました
・11/11/03
共感覚面白ニュースを更新しました
・11/04/03
筑波大学新入生向け情報を書きました
・11/03/04
Twitter4j逆引きリファレンス【使い方 やりたいことから見つける】を書きました
もっと見る
知りたい情報募集中
知りたい情報は見つかりましたか? 見つからなかったならご連絡ください。 詳しく調べて、ネットでは見つからないような良質で科学的な情報を掲載いたします。

研究協力者も募集中です!
お問い合わせはこちら