当所有异步任务完成而没有阻塞时获取

时间:2017-01-26 08:16:10

标签: spring multithreading asynchronous java-8

我的工作每10分钟一次 并发送30K~HTTP邮件请求

我想计算失败次数(超时,404等等)并最终重试

这项工作最长可达10分钟。每个请求超时为3秒

在没有使用.get()

阻止的情况下完成所有异步任务时获取通知的最佳做法是什么

我不想阻止,因为我每次迭代都会有30,000个任务。每个任务发送一个http请求,完成任务的最长时间为10分钟,执行超过40个核心。

我附上了使用spring的ListenableFuture的代码 方法.get是阻塞,在这个例子中,thread5将休眠10秒以获取TimeoutException

是否有任何特殊的数据结构可以检查每个完成的任务并将其删除?

我正在使用java8

    import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOReactorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.AsyncRestTemplate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AsyncRestTemplateTest {

    private static final Logger logger = LoggerFactory.getLogger(AsyncRestTemplateTest.class);

    public static void main(String[] args) throws IOReactorException {
        String url = "http:/some.serivce";
        int connectionTimeout = 3000;
        int soTimeout = 3000;
        int defaultMaxPerRoute = 2;
        int maxTotal = 300;

        IOReactorConfig customIOReactorConfig = IOReactorConfig.custom()
                .setIoThreadCount(Runtime.getRuntime().availableProcessors())
                .setConnectTimeout(connectionTimeout)
                .setSoTimeout(soTimeout)
                .build();

        ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(customIOReactorConfig);

        PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager(ioReactor);

        connManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
        connManager.setMaxTotal(maxTotal);
        CloseableHttpAsyncClient customHttpAsyncClient = HttpAsyncClients.custom()
                .setConnectionManager(connManager)
                .build();

        HttpComponentsAsyncClientHttpRequestFactory asyncRequestFactory = new HttpComponentsAsyncClientHttpRequestFactory(customHttpAsyncClient);
        AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(asyncRequestFactory);

        System.out.println("start");
        List<ListenableFuture<ClientHttpResponseWrapper>> futures = new ArrayList<>();
        for (int i = 0; i < 11; i++)
        {
            final int finalI = i;
            ListenableFuture<ClientHttpResponseWrapper> future = asyncRestTemplate.execute(url, HttpMethod.GET, request -> logger.info("preRequest..."), response -> {
// executing http request
                if (finalI == 5) {
                    try {
                        logger.info("sleeping [{}]", finalI);
                        Thread.sleep(10_000);
                    } catch (InterruptedException ignored) { }
                }

                return new ClientHttpResponseWrapper(response, finalI);
            });
            future.addCallback(new ListenableFutureCallback<ClientHttpResponseWrapper>() {
                @Override
                public void onFailure(Throwable ex) {
                    logger.error("onFailure [{}] [{}] [{}]", finalI, ex.getMessage(), ex.getStackTrace()[0].toString());
                }

                @Override
                public void onSuccess(ClientHttpResponseWrapper result) {
                    if (result != null) {
                        try {
                            StringBuilder body = new StringBuilder();
                            if (!HttpStatus.OK.equals(result.getClientHttpResponse().getStatusCode())) {
                                BufferedReader rd = new BufferedReader(new InputStreamReader(result.getClientHttpResponse().getBody()));
                                String line;
                                while ((line = rd.readLine()) != null) {
                                    body.append(line);
                                }
                            }
                            logger.info("onSuccess [{}] [{}] [{}]", finalI, result.getClientHttpResponse().getRawStatusCode(), body.toString());
                        } catch (IOException e) {
                            logger.error(e.getMessage());
                        }
                    }
                }
            });
            futures.add(future);
        }
        System.out.println("end loop");

        // BLOCK EXAMPLE
        for (ListenableFuture<ClientHttpResponseWrapper> future : futures) {
            try {
                ClientHttpResponseWrapper result = future.get(5, TimeUnit.SECONDS);
                logger.info("Result [{}] [{}]", result.getId(), result.getClientHttpResponse().getRawStatusCode());
            } catch (IOException | InterruptedException | ExecutionException | TimeoutException e) {
                logger.error("Result [{}] [{}]", null, e.getClass());
                future.cancel(true);
            }
        }
        System.out.println("END!!!");
    }


    private static class ClientHttpResponseWrapper {

        ClientHttpResponse clientHttpResponse;
        int id;

        ClientHttpResponseWrapper(ClientHttpResponse clientHttpResponse, int id) {
            this.clientHttpResponse = clientHttpResponse;
            this.id = id;
        }

        ClientHttpResponse getClientHttpResponse() {
            return clientHttpResponse;
        }

        public int getId() {
            return id;
        }
    }
}

0 个答案:

没有答案