使用Apache HTTP Client 4.5.x保留线程

时间:2018-05-23 06:11:22

标签: java network-programming apache-httpclient-4.x

在我的weblogic中,很多线程都被这种方式所困扰,但我无法弄清楚原因。这是堆栈跟踪。我设置了连接的所有超时:

  • setConnectionRequestTimeout
  • setConnectTimeout
  • setSocketTimeout

这是堆栈跟踪,我没有看到任何可能导致此卡住线程的代码问题(在帖子末尾)。有什么想法吗?

<22-May-2018 11.48.46 CEST> <Error> <WebLogicServer> <BEA-000337> <[STUCK] ExecuteThread: '36' for queue: 'weblogic.kernel.Default (self-tuning)' has been busy for "616" seconds working on the request "Http Request Information: weblogic.servlet.internal.ServletRequestImpl@7567f23c[POST /aca/rest/servicesupport]
", which is more than the configured time (StuckThreadMaxTime) of "600" seconds in "server-failure-trigger". Stack trace:
    java.net.SocketInputStream.socketRead0(Native Method)
    java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    java.net.SocketInputStream.read(SocketInputStream.java:170)
    java.net.SocketInputStream.read(SocketInputStream.java:141)
    org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
    org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
    org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:282)
    org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:138)
    org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:56)
    org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
    org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
    org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:165)
    org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
    org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
    org.apache.http.impl.execchain.MainClientExec.createTunnelToTarget(MainClientExec.java:473)
    org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:398)
    org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
    org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
    org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
    org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
    org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    com.iberia.es.integration.FacadeSFIntegrationImpl.requestToken(FacadeSFIntegrationImpl.java:71)

这是带有连接方法的类。我正在使用 Apache http客户端4.5.3

public class FacadeSFIntegrationImpl implements FacadeSFIntegration {


    @Autowired
    @Qualifier("confResolver")
    ConfigurationResolver config;

    @Override
    public String requestToken(List<IbEsNameAndValueDTO> params, String url, Boolean proxyEnabled,
            Integer connectionRequestTimeout, Integer connectTimeout, Integer socketTimeout) {

        if (params != null && !params.isEmpty() && url != null) {

            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
                // Preparamos los parámetros
                List<NameValuePair> httpParams = convertParams(params);

                // Configuramos la llamada
                RequestConfig httpConfig = configHttpRequest(proxyEnabled, connectionRequestTimeout, connectTimeout,
                        socketTimeout);

                // Realizamos la llamada post
                HttpPost post = new HttpPost(url);
                post.setConfig(httpConfig);
                post.setEntity(new UrlEncodedFormEntity(httpParams, "UTF-8"));

                // Controlamos la respuesta
                HttpResponse response = httpClient.execute(post);
                int status = response.getStatusLine().getStatusCode();
                if (status >= 200 && status < 300) {
                    HttpEntity entity = response.getEntity();
                    return EntityUtils.toString(entity);
                }

            } catch (UnsupportedEncodingException e) {
                //LOG
            } catch (ClientProtocolException e) {
                //LOG
            } catch (IOException e) {
                //LOG
            }
        }

        return null;
    }


    private RequestConfig configHttpRequest(Boolean proxyEnabled, Integer connectionRequestTimeout,
            Integer connectTimeout, Integer socketTimeout) {

        Builder httpConfigBuilder = RequestConfig.custom();

        if (proxyEnabled) {
            String proxyUrl = config.getValue("proxy.host");
            String proxyPort = config.getValue("proxy.puerto");

            HttpHost proxy = new HttpHost(proxyUrl, Integer.valueOf(proxyPort));
            httpConfigBuilder.setProxy(proxy);
        }

        String connectionRequestTimeoutDefaultS = config.getValue("proxy.timeout.connectionRequest");
        httpConfigBuilder.setConnectionRequestTimeout((connectionRequestTimeout != null) ? connectionRequestTimeout
                : Integer.valueOf(connectionRequestTimeoutDefaultS));

        String connectTimeoutDefaultS = config.getValue("proxy.timeout.connect");
        httpConfigBuilder.setConnectTimeout((connectTimeout != null) ? connectTimeout : Integer
                .valueOf(connectTimeoutDefaultS));

        String socketTimeoutDefaultS = config.getValue("proxy.timeout.socket");
        httpConfigBuilder.setSocketTimeout((socketTimeout != null) ? socketTimeout : Integer
                .valueOf(socketTimeoutDefaultS));

        return httpConfigBuilder.build();
    }

    private List<NameValuePair> convertParams(List<IbEsNameAndValueDTO> params) {

        List<NameValuePair> result = new ArrayList<>();
        for (IbEsNameAndValueDTO nameValue : params) {
            result.add(new BasicNameValuePair(nameValue.getName(), nameValue.getValue()));
        }
        return result;

    }

}

1 个答案:

答案 0 :(得分:1)

在通过代理建立到目标的隧道时,请求执行被卡住了。请注意,请求级别套接字超时设置仅适用于完全建立的连接。为了避免这种情况,您可能希望使用客户端构建器的SocketConfig方法或直接在连接管理器上使用#setDefaultSocketConfig将连接管理器级别的默认超时设置为正值

RequestConfig requestConfig = RequestConfig.custom()
        .setConnectTimeout(5000)
        .setSocketTimeout(5000)
        .build();
SocketConfig socketConfig = SocketConfig.custom()
        .setSoTimeout(5000)
        .build();
CloseableHttpClient client = HttpClients.custom()
        .setDefaultRequestConfig(requestConfig)
        .setDefaultSocketConfig(socketConfig)
        .build();