0

読んでくれてありがとう。

そのような厄介な問題が私に起こりました、私は誰かが私を助けてくれるに値します。私はJavaでhttpcomponent(以前のhttpclientの新しいバージョン)を使用していくつかのURLとスクラップコンテンツを開きます。そしてmultihtreadはパフォーマンスを改善するために使用されます。

だからそれは問題です:

1.スレッドはHttpClientを共有します

1)定義

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)そして私の最初の機能で

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**

しかし、私はIEとプロキシを使用してURLを開きましたが、正常に開かれました。つまり、プロキシに問題はありません。

では、何が問題なのですか?

2.次に、httpclientの作成をgetUrl()関数に変更しました。これにより、スレッドはHttpClientを共有しなくなります。

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; 
    }

そして、10スレッドの約600ループの後、別のたわごとが発生します。

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

結果で例外が発生します=EntityUtils.toString(entity); ライン

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

ありがとう!

4

2 に答える 2

2

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

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

于 2012-02-29T14:54:12.887 に答える
1

ギヨームの答えは、私には完全に理にかなっているように思えます。2番目の問題に関する限り、その理由OutOfMemoryErrorは非常に単純です。DefaultHttpClientオブジェクトは非常に高価であり、リクエストごとに新しいインスタンスを作成することで、システム リソースをはるかに速く枯渇させます。また、一般的にEntityUtils#toString、単純なテスト以外では避けるべきです。応答本文全体をメモリにバッファリングせずに、HTTP 応答メッセージをコンテンツ ストリームとして消費する必要があります。

于 2012-02-29T16:13:36.633 に答える