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するのは以下のクラスです。
1 | import java.util.concurrent.Future; |
3 | import com.google.appengine.api.urlfetch.FetchOptions; |
4 | import com.google.appengine.api.urlfetch.HTTPMethod; |
5 | import com.google.appengine.api.urlfetch.HTTPRequest; |
6 | import com.google.appengine.api.urlfetch.HTTPResponse; |
7 | import com.google.appengine.api.urlfetch.URLFetchService; |
8 | import com.google.appengine.api.urlfetch.URLFetchServiceFactory; |
01 | ArrayList<URL> urlList = new ArrayList<URL>(); |
05 | ArrayList<Future<HTTPResponse>> responseList = new ArrayList<Future<HTTPResponse>>(); |
07 | for ( int i = 0 ; i < urlList.size(); i++){ |
08 | URLFetchService ufs = URLFetchServiceFactory.getURLFetchService(); |
09 | responseList.add(ufs.fetchAsync(urlList.get(i))); |
12 | for ( int i = 0 ; i < responseList.size(); i++){ |
14 | HTTPResponse response = responseList.get(i).get(); |
15 | byte [] content = response.getContent(); |
これが必要最小限の構成で非同期URLFetchを使うプログラムです。GETメソッドでurlのコンテンツを取得してきます。
01 | ArrayList<URL> urlList = new ArrayList<URL>(); |
04 | ArrayList<Future<HTTPResponse>> responseList = new ArrayList<Future<HTTPResponse>>(); |
06 | for ( int i = 0 ; i < urlList.size(); i++){ |
07 | URLFetchService ufs = URLFetchServiceFactory.getURLFetchService(); |
08 | HTTPRequest request = new HTTPRequest(urlList.get(i), HTTPMethod.GET); |
09 | request.addHeader( new HTTPHeader( "original-header" , "test" )); |
10 | responseList.add(ufs.fetchAsync(request)); |
13 | for ( int i = 0 ; i < responseList.size(); i++){ |
15 | HTTPResponse response = responseList.get(i).get(); |
16 | byte [] content = response.getContent(); |
ヘッダやパラメータを追加するとこのようになります。GETメソッドなのでURLにパラメータを埋め込みましたが、POSTメソッドの時はどうするんですかね…。
2010年10月の時点では、POSTのパラメータを追加するようなAPIは存在しません。
02 | ArrayList<Future<HTTPResponse>> responseList = new ArrayList<Future<HTTPResponse>>(); |
04 | for ( int i = 0 ; i < urlList.size(); i++){ |
05 | URLFetchService ufs = URLFetchServiceFactory.getURLFetchService(); |
06 | HTTPRequest request = new HTTPRequest(urlList.get(i), HTTPMethod.GET, Builder.disallowTruncate().setDeadline( 10.0 )); |
07 | request.addHeader( new HTTPHeader( "original-header" , "test" )); |
08 | responseList.add(ufs.fetchAsync(request)); |
11 | for ( int i = 0 ; i < responseList.size(); i++){ |
13 | HTTPResponse response = responseList.get(i).get(); |
14 | byte [] content = response.getContent(); |
disallowTruncate()を追加しました。これにより、レスポンスが大きすぎるときはResponseTooLargeExceptionをだすようになります。Exceptionを
ださずに大きすぎるレスポンスを切り捨てる場合は、allowTruncate()を使います。
setDeadline(10.0)により、URLFetchのタイムアウト時間を10秒に設定しました。最大が10秒です。デフォルトのタイムアウト時間は5秒です。5秒だとすぐ失敗します。
「Java版のURLFetchにはタイムアウト時間を変更できないバグがある」という解説をたまに見かけますが、2010年10月の時点ではちゃんと10秒に設定できます。
このページの中で何か分からないことがありましたら、
@ts_3156に何でも聞いてください。
「このコードのここの意味が分からない」とか、何でも大丈夫ですよ(^-^)