HttpClient:HttpGet方法失败:HTTP / 1.0 503服务不可用

时间:2012-02-29 14:49:54

标签: java multithreading httpclient out-of-memory apache-httpcomponents

感谢阅读。

这个烦人的问题发生在我身上,我应该有人帮助我。 我在java中使用httpcomponent(以前的httpclient的新版本)来打开一些网址和废品内容。而multihtread用于提高性能。

所以问题在于:

1.threads共享一个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)然后我创建了10个线程来调用getUrl()函数,但是在大约1000个循环之后,就会发生这样的事情:

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

但我使用IE和代理打开网址,它已成功打开。所以这意味着我的代理没有错。

那有什么不对?

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

然后在大约600个循环的10个线程之后,发生了另一个错误:

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

result = EntityUtils.toString(entity);

中发生异常

所以,真的需要一些帮助。

谢谢!

2 个答案:

答案 0 :(得分:2)

503表示服务不可用,因此服务已关闭。现在可能是因为您实际上一遍又一遍地访问相同的服务并最终导致错误或由于此类负载而拒绝您的服务。

第二个错误很明显:没有更多的内存因为你全部使用了它。你的程序是在泄漏内存还是你应该使用-Xmx256m,-Xmx512m,-Xmx1G等来增加堆大小......对于这些问题,SO上有很多答案。

答案 1 :(得分:1)

Guillaume给出的答案对我来说听起来非常合理。就你的第二个问题而言,OutOfMemoryError的原因很简单。 DefaultHttpClient个对象非常昂贵,通过为每个请求创建一个新实例,您可以更快地耗尽系统资源。此外,除了简单测试之外,通常应避免使用EntityUtils#toString。应该将HTTP响应消息作为内容流使用,而不是在内存中缓冲整个响应主体。