2012-03-09 6 views
4

をキャッシュしているようです。私は要求を処理するためにマルチスレッドHttpClientベースのクラスを構築しました。私はExecutorServiceを使ってスレッドプールを作ってスレッドを実行しています。問題は、動的属性が各リクエストで変更されないことがあり、3つまたは4つの後続スレッドで同じ値を取得することになります。私はHttpClientについて多くのことを読んできました。この問題の原因がわかりません。それはキャッシングについての何かか、それとも何かのようなものでしょうか?のJavaのHttpClientは、私はシンプルなウェブスクレイパーを構築していると私は同じページに数百回をフェッチする必要があり、動的であり、それぞれの要求に応じて変更する必要がありますページ内の属性がありますコンテンツ

更新:ここで、各スレッドで実行されるコードです:

HttpContext localContext = new BasicHttpContext(); 

HttpParams params = new BasicHttpParams(); 
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
HttpProtocolParams.setContentCharset(params, 
     HTTP.DEFAULT_CONTENT_CHARSET); 
HttpProtocolParams.setUseExpectContinue(params, true); 

ClientConnectionManager connman = new ThreadSafeClientConnManager(); 

DefaultHttpClient httpclient = new DefaultHttpClient(connman, params); 

HttpHost proxy = new HttpHost(inc_proxy, Integer.valueOf(inc_port)); 
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, 
     proxy); 

HttpGet httpGet = new HttpGet(url); 
httpGet.setHeader("User-Agent", 
     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"); 

String iden = null; 
int timeoutConnection = 10000; 
HttpConnectionParams.setConnectionTimeout(httpGet.getParams(), 
     timeoutConnection); 

try { 

    HttpResponse response = httpclient.execute(httpGet, localContext); 

    HttpEntity entity = response.getEntity(); 

    if (entity != null) { 

     InputStream instream = entity.getContent(); 
     String result = convertStreamToString(instream); 
     // System.out.printf("Resultado\n %s",result +"\n"); 
     instream.close(); 

     iden = StringUtils 
       .substringBetween(result, 
         "<input name=\"iden\" value=\"", 
         "\" type=\"hidden\"/>"); 
     System.out.printf("IDEN:%s\n", iden); 
     EntityUtils.consume(entity); 
    } 

} 

catch (ClientProtocolException e) { 
    // TODO Auto-generated catch block 
    System.out.println("Excepção CP"); 

} catch (IOException e) { 
    // TODO Auto-generated catch block 
    System.out.println("Excepção IO"); 
} 
+0

サーバー側にキャッシュできます。 – PeterMmm

+0

スレッドセーフでないコードを書くことができます。データをダウンロードするたびに古い結果が新しい結果で上書きされます。コードなしで伝えるのは難しいです。 –

+0

コード – Trota

答えて

3

は一般的に、HTTPリクエストがワイヤ上で行われているかどうかをテストするために、あなたは「スニッフィング」ツールを使用することができます例えば、ネットワークトラフィックを分析:

私は非常にHttpClientは(これは、メモリ内またはディスク上のページを格納する必要が暗示する - その機能のない1)いかなる種類のキャッシングを実行している疑い。

これは熟考する答え、そのポイントではありませんが:それは、サーバ(またはその間のいくつかのプロキシが)あなたにキャッシュされたコンテンツを返すことは可能ですか?同じコンテンツに対して(同時にまたはほぼ同時に)多くのリクエストを実行している場合、サーバーは情報が「期限切れ」ではないと判断したため、キャッシュされたコンテンツを返す可能性があります。実際、HTTPプロトコルはそのような機能のためのキャッシングディレクティブを提供します。ここでは別のHTTPキャッシュメカニズムの高レベルの概要を提供し、サイトである:

http://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/

私はこれがあなたの出発点を与える願っています。すでにこれらの道を考えているなら、それは素晴らしいことです。

1

あなたは(サーバーで、どこかの道に沿って)任意のURLベースのキャッシュを無効にしようとするすべてのリクエストにURLにいくつかのユニークなダミーのパラメータを追加してみてください。キャッシュが問題でない場合、またはサーバーが未知のパラメーターを持つ要求を拒否するのに十分なほどスマートな場合、またはサーバーがキャッシュしているが関心のあるパラメーターのみに基づいている場合、または選択したパラメーター名がサイトが実際に使用するパラメータ。

これはあなたが http://www.example.org/index.html を使用しているURLである場合は、要求ごとに異なる値に http://www.example.org/index.html?dummy=1

セットダミーを使用してみてください。

+0

で質問を更新しましたFixedThreadPoolを使ってスレッドを実行しています: 'ExecutorService pool = Executors.newFixedThreadPool(10);for(int i = 0; i Trota

4

HTTPClientのデフォルトでキャッシュを使用していない(あなたはDefaultHttpClientクラスを使用する場合のみ)。あなたがCachingHttpClientを使用する場合は、キャッシュを有効にするHttpClientインタフェースデコレータである、そうする:

HttpClient client = new CachingHttpClient(new DefaultHttpClient(), cacheConfiguration); 

次に、それは、リモートサーバーへの要求が行われたかどうかを判断するためにIf-Modified-SinceIf-None-Matchヘッダを分析し、またはその結果が返された場合キャッシュから。

あなたの問題は、アプリケーションとリモートサーバーの間にプロキシサーバーが置かれていることが原因と考えられます。

curlアプリケーションで簡単にテストできます。

#!/bin/bash 

for i in {1..50} 
do 
    echo "*** Performing request number $i" 
    curl -D - http://yourserveraddress.com -o $i -s 
done 

そして、すべてダウンロードしたファイルの間diffを実行します。プロキシを省略リクエストをいくつか実行します。それらのすべてにあなたが言及した違いがあるはずです。次に、curlに-x/--proxy <host[:port]>オプションを追加し、このスクリプトを実行してファイルを再度比較します。いくつかの応答が他の応答と同じである場合は、これがプロキシサーバーの問題であることを確認できます。

関連する問題