1 year ago

#215775

test-img

zhuangjingwen

"IllegalStateException: Unexpected request state READY" when using HttpAsyncClient under high concurrency

We have a HttpAsyncUtil to process HTTP POST requests.

public class HttpAsyncUtil {

    private static CloseableHttpAsyncClient client = null;

    static {
        try {
            // Connect time out: 2s, read time out: 10s, request time out: 5s
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(2000).setSocketTimeout(10000).setConnectionRequestTimeout(5000).build();

            IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setIoThreadCount(20).setSoKeepAlive(false).build();

            ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(ioReactorConfig);

            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            // don't check
                        }
                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            // don't check
                        }
                    }
            };

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, null);
            SSLIOSessionStrategy sslioSessionStrategy = new SSLIOSessionStrategy(sslContext, SSLIOSessionStrategy.ALLOW_ALL_HOSTNAME_VERIFIER);
            Registry<SchemeIOSessionStrategy> registry = RegistryBuilder.<SchemeIOSessionStrategy>create()
                    .register("http", NoopIOSessionStrategy.INSTANCE)
                    .register("https", sslioSessionStrategy)
                    .build();

            PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor,registry);
            connectionManager.setMaxTotal(2000);
            connectionManager.setDefaultMaxPerRoute(2000);

            client = HttpAsyncClients.custom().setConnectionManager(connectionManager)
                    .setDefaultRequestConfig(requestConfig)
                    .build();
        } catch (Exception ex) {
            // System.exit(0);
        }

    }

    public static void post(String url, Map<String, String> params, Map<String, String> headers, FutureCallback<HttpResponse> callback) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
        }
        if (params != null) {
            List<NameValuePair> parameters = new ArrayList<>(params.size());
            for (Map.Entry<String, String> entry : params.entrySet()) {
                parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
            httpPost.setEntity(formEntity);
        }
        client.start();
        client.execute(httpPost,callback);
    }

It works well under low concurrency. However, something went wrong when processing pressure test.

java.lang.IllegalStateException: Unexpected request state READY
        at org.apache.http.util.Asserts.check(Asserts.java:46)
        at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.outputReady(HttpAsyncRequestExecutor.java:231)
        at org.apache.http.impl.nio.DefaultNHttpClientConnection.produceOutput(DefaultNHttpClientConnection.java:290)
        at org.apache.http.impl.nio.client.InternalIODispatch.onOutputReady(InternalIODispatch.java:86)
        at org.apache.http.impl.nio.client.InternalIODispatch.onOutputReady(InternalIODispatch.java:39)
        at org.apache.http.impl.nio.reactor.AbstractIODispatch.outputReady(AbstractIODispatch.java:145)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.writable(BaseIOReactor.java:188)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:341)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
        at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:588)
        at java.base/java.lang.Thread.run(Thread.java:834)

The source code shows that the Connection state is expected to be BODY_STREAM or ACK_EXPECTED but its actually READY. It seems that something special events reset the Connection state. But we cannot find more evidence on this.

java

apache-httpasyncclient

0 Answers

Your Answer

Accepted video resources