0

お読みいただきありがとうございます。HttpClient:HttpGetメソッドが失敗しました:HTTP/1.0 503サービスが利用できません

このような厄介な問題が私に発生しました。私は誰かが私を助けてくれることを望んでいます。 私はいくつかのURLを開いてコンテンツをスクラップするためにjavaでhttpcomponent(旧バージョンのhttpclientの新しいバージョン)を使用しています。また、multihtreadはパフォーマンスを向上させるために使用されます。

だから、問題は次のとおりです。

1.threadsはHttpClientを

1)Defination

private static final ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(); 
private static HttpHost proxy = new HttpHost("127.0.0.1",8086,"http"); 
private static DefaultHttpClient http = new DefaultHttpClient(cm); 

2)と私のinital機能に

cm.setMaxTotal(100); 
http.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 

3)を共有します私のスレッド機能です

public static String getUrl(String url, String Chareset) 
    { 
     HttpGet get = new HttpGet(url);//uri 
     get.setHeader("Content-Type", "text/html"); 
     get.setHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50215;)"); 
     get.setHeader("Accept-Charset", Chareset+";q=0.7,*;q=0.7");//"utf-8;q=0.7,*;q=0.7"); 
    get.getParams().setParameter("http.socket.timeout",new Integer(CONNECTION_TIMEOUT));//20000 

     String result = ""; 
     try { 
      HttpResponse response = http.execute(get); 
     if (response.getStatusLine().getStatusCode() != 200){//statusCode != HttpStatus.SC_OK) { 
       System.err.println("HttpGet Method failed: " 
         + response.getStatusLine());//httpGet.getStatusLine() 
     } 
     HttpEntity entity = response.getEntity(); 
     if (entity != null) { 
      result = EntityUtils.toString(entity); 
      EntityUtils.consume(entity); 
      entity = null; 
     } 
    } catch(java.net.SocketException ee) 
    { 
      ee.printStackTrace(); 
      Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, ee); 
    } 
     catch (IOException e) { 
      //throw new Exception(e); 
      Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, e);//TODO Debug 
    } finally { 
     get.abort();//releaseConnection();//TODO http.getConnectionManager().shutdown();? 
     get = null; 
    } 
     return result; 
    } 

4)そして、私はのgetURL()関数を呼び出すために10個のスレッドを作成しますが、約1000のループの後、たわごとが起こる:

**HttpGet Method failed: HTTP/1.0 503 Service Unavailable** 

しかし、私は、それはだ、URLを開くためにIEとプロキシを使用それは私の代理人に何も間違っていないことを意味します。

何が問題なのですか? 10件のスレッドの約600ループ、別のたわごと後

public static String getUrl(String url, String Chareset) 
    { 
     HttpGet get = new HttpGet(url);//uri 
     get.setHeader("Content-Type", "text/html"); 
     get.setHeader("User-Agent","Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50215;)"); 
     get.setHeader("Accept-Charset", Chareset+";q=0.7,*;q=0.7");//"utf-8;q=0.7,*;q=0.7"); 
    get.getParams().setParameter("http.socket.timeout",new Integer(CONNECTION_TIMEOUT));//20000 

     DefaultHttpClient http = new DefaultHttpClient(cm);//threads dont't share it 
     http.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); 

     String result = ""; 
     try { 
      HttpResponse response = http.execute(get); 
     if (response.getStatusLine().getStatusCode() != 200){//statusCode != HttpStatus.SC_OK) { 
       System.err.println("HttpGet Method failed: " 
         + response.getStatusLine());//httpGet.getStatusLine() 
     } 
     HttpEntity entity = response.getEntity(); 
     if (entity != null) { 
      result = EntityUtils.toString(entity); 
      EntityUtils.consume(entity); 
      entity = null; 
     } 
    } catch(java.net.SocketException ee) 
    { 
      ee.printStackTrace(); 
      Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, ee); 
    } 
     catch (IOException e) { 
      //throw new Exception(e); 
      Logger.getLogger(DBManager.class.getName()).log(Level.SEVERE, null, e);//TODO Debug 
    } finally { 
     get.abort();//releaseConnection();//TODO http.getConnectionManager().shutdown();? 
     get = null; 
       http = null;//clean almost all the resources 
    } 
     return result; 
    } 

、その後に:スレッドがそのように、HttpClientを共有していないので、私は、のgetURL()関数にHTTPClientのの作成を変え

2.Then起こる:

**Exception in thread "Thread-11" java.lang.OutOfMemoryError: Java heap space* *

例外結果= EntityUtils.toString(エンティティ)で起こります。 line

だから、本当に助けが必要です。

ありがとうございます!

+0

私は拒否されていることが判明しました。拒否されないようにするには、2番目の方法を使用する必要があります。新しいスレッドごとのHTTPClientを使用する必要があります。Java gc()が遅すぎるため、sleep()が良いアイデアかもしれません。プログレスをフラグでリセットして、進捗状況を示します。すべての答えをありがとう! – Jacob

+1

私はついにそれを理解しました。この方法はうまくいきます。そして、どこか他の場所にメモリリークがあります。申し訳ありません。 – Jacob

答えて

1

Guillaumeによって与えられた答えは、私にとって完全に合理的です。あなたが第二の問題としている限り、OutOfMemoryErrorの理由はかなり単純です。 DefaultHttpClientオブジェクトは非常に高価です。それぞれの要求ごとに新しいインスタンスを作成することで、システムリソースを大幅に使い果たしてしまいます。また、一般的にEntityUtils#toStringは、単純なテスト以外は避けるべきです。レスポンスボディ全体をメモリにバッファリングすることなく、HTTPレスポンスメッセージをコンテンツストリームとして消費する必要があります。

+0

HTTP応答メッセージをコンテンツストリームとして消費し、応答本体全体をメモリにバッファリングする必要はありません。どうすればいいですか?entity.getContent?ありがとう。 – Jacob

+0

私はその答えを疑う。 すべてのURLは異なっていますが、そこには製粉所があります。 すべてのスレッドが異なるURLを開きます。 urlが私を否定するなら、なぜurl bも私を否定しますか?私はIEとFirefoxを使用して、同じプロキシを同時に使用してURLの1つを開くと、成功しています。 だから私は論理がかなり正しいと思います。 1つのURLを開いた後にリソースをクリーンアップする必要があるかもしれません。 – Jacob

+0

@Rusty:はい、HttpEntity#getContentから返されたInputStreamを使用して、作業を完了するのに十分なデータだけを読み込む必要があります。 – oleg

2

503はサービスが利用できないことを意味するため、サービスは停止しています。これは、実際に同じサービスに何度もアクセスしていて、エラーが発生したり、そのような負荷が原因でサービスが拒否されたりするためです。

2番目のエラーは非常に明確です。すべてを使用したため、メモリがなくなりました。プログラムがメモリをリークしているか、-Xmx256m、-Xmx512m、-Xmx1Gなどを使ってヒープサイズを増やす必要があります。これらの問題については、SOにはたくさんの答えがあります。

+0

まず、IEが起動している間に同じプロキシを同時に開くことができます私! そして、ちょっと質問すると、私はそれをすべて使っているので、それ以上の記憶ではないことは分かっています。私はちょっと心配していません.getUrl()関数はほとんどすべてのコードです。 sth私はすでに知っている、大丈夫? – Jacob

+0

異なるクライアントが異なる応答を返します。 HTTPClientが動作するはずのIEが動作するからではありません。異なるセッション、異なるエージェントなど...あなたは間違いなくそれが動作するかどうかを言うためにIEに依存してはいけません。また、1000の要求のために、もう一方のサービスがダウンしてしまうかもしれませんが、ほんの少しの問題があるかもしれません。 –

+0

User-Agentフィールドが表示されますか?それは私のPC上のFirefoxです。私はFirefoxとして偽装し、 Firefoxを使用しているURLも大丈夫です! – Jacob

関連する問題