在httpclient.execute中的HttpClientConnectionOperator.connect时忽略套接字读取超时

时间:2016-04-22 10:40:51

标签: java multithreading sockets ssl httpclient

下面是jstack的输出,观察线程,nid = 0x771d(30493)。这是几个小时前开始的。

"taskScheduler-6" prio=10 tid=0x00007f4479e07800 nid=0x771d runnable [0x00007f446e63a000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:152)
    at java.net.SocketInputStream.read(SocketInputStream.java:122)
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
    at sun.security.ssl.InputRecord.readV3Record(InputRecord.java:554)
    at sun.security.ssl.InputRecord.read(InputRecord.java:509)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
    - locked <0x00000007601abdf0> (a java.lang.Object)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
    - locked <0x00000007601abea0> (a java.lang.Object)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory
.java:275)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:
254)
    at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:1
23)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionMa
nager.java:318)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)

    ........ // other call stack of custom codes

并且线程的CPU时间总是相同的,而不是更改:(由top -Hp pid生成)

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND
30493 root      20   0 3832m 1.0g  11m S   0.0  2.2   0:01.20 java

这是Java代码:

    RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(so_timeout_milliseconds)
                        .setConnectTimeout(so_timeout_milliseconds).setSocketTimeout(so_timeout_milliseconds).build();  // so_timeout_milliseconds = 6000
    do {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpGet httpget = new HttpGet(url);
            httpget.setConfig(config);
            if (headers != null) {
                for (Header header : headers) {
                    httpget.addHeader(header);
                }
            }

            CloseableHttpResponse response = httpclient.execute(httpget); // see jstack output above
            try {
                StatusLine statusLine = response.getStatusLine();
                if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        InputStream instream = entity.getContent();
                        try {
                            return IOUtils.isToString(instream);
                        } catch (IOException ex) {
                            throw ex;
                        } finally {
                            instream.close();
                        }
                    }
                }
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    } while (--try_times > 0);

HttpClient版本:

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.5</version>
    </dependency>
  1. 我不确定这是HTTPClient中的错误吗?如果是,部件代码会出现什么问题?
  2. 为什么线程为RUNNABLE状态,CPU时间不增加?
  3. 在我看来,这是因为IO无法完成,所以它不会发生CPU中断,但是为什么状态不是SUSPEND。(我在Java中的意思是WAITING)。

2 个答案:

答案 0 :(得分:1)

我找到了一个解决方案,将httpclient更新为4.3.6,问题解决了。 这是apache JIRA。 更改后的代码为here

答案 1 :(得分:0)

  

我不确定这是HTTPClient中的错误吗?

没有。任何这样的'bug'都将驻留在JVM中,而不是JSSE中,当然也不会存在于HTTPClient中。

  

如果是,部件代码会出现什么问题?

无。见上文。

  

为什么线程处于RUNNABLE状态,并且CPU时间不会增加?

作为RUNNABLE的Java线程意味着它不会被Java中的任何东西所阻碍,例如监视器或其他线程。这并不意味着没有阻止操作系统的观点,例如,在阻塞读取中,这里的情况显然如此。

  

在我看来,这是因为IO无法完成,所以不能发生CPU中断,但为什么状态不是SUSPEND。

Thread.State.SUSPEND[{ "key1": "key here", "key2": "key2 here", "key3": "pId here11", "details": { "detailsKey1": "https://linkHere.com/conf/conf1/conf2/img/testImage.png", "detailsKey2": "desc here", "detailsKey3": "some url here", "detailsKeys4": "some key here", "terms": [{ "termsKey1": "über dreißig", "termsKey2": "mäßig term here" }] } }, { "key1": "key here", "key2": "key2 here", "key3": "pId here11", "details": { "detailsKey1": "https://linkHere.com/conf/conf1/conf2/img/testImage.png", "detailsKey2": "desc here", "detailsKey3": "some url here", "detailsKeys4": "some key here", "terms": [{ "termsKey1": "über dreißig", "termsKey2": "mäßig term here" }] } }]