• 异步请求CloseableHttpAsyncClient的使用


    1、前言

    项目有个需求,需要把一些没用影响业务逻辑的http请求改成异步请求,httpclient在4.0后提供新的api CloseableHttpAsyncClient可以使用,记录下使用过程。

    2、网络调用类型

    (1)传统BIO(Blocking IO)

    同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

    (2)NIO(Not-Blocking IO)

    NIO:同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

    (3)AIO(NIO.2)

    异步非阻塞式IO,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

    3、CloseableHttpAsyncClient

    CloseableHttpAsyncClient是apache在4.0后提供AIO操作的api,基本使用如下

    1)pom.xml引用如下
    <dependency>
    	<groupId>org.apache.httpcomponents</groupId>
    	<artifactId>httpclient</artifactId>
    	<version>4.5.2</version>
    </dependency>
    <dependency>
    	<groupId>org.apache.httpcomponents</groupId>
    	<artifactId>httpcore</artifactId>
    	<version>4.4.5</version>
    </dependency>
    <dependency>
    	<groupId>org.apache.httpcomponents</groupId>
    	<artifactId>httpcore-nio</artifactId>
    	<version>4.4.5</version>
    </dependency>
    <dependency>
    	<groupId>org.apache.httpcomponents</groupId>
    	<artifactId>httpasyncclient</artifactId>
    	<version>4.1.2</version>
    </dependency>
    
    2)构造连接
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.ContentType;
    import org.apache.http.entity.StringEntity;
    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;
    
    /**
     * @Title:
     * @Description:异步连接
     * @Author: yangyongzhen
     * @Date: 2019/9/26 14:38
     */
    public class AsynHttpClient {
        private static CloseableHttpAsyncClient client = null;
    
    
        public static CloseableHttpAsyncClient getHttpClient() {
            if (client == null) {
                synchronized (AsynHttpClient.class) {
                    if (client == null) {
                        RequestConfig requestConfig = RequestConfig.custom()
                                .setConnectTimeout(2000)//连接超时,连接建立时间,三次握手完成时间
                                .setSocketTimeout(2000)//请求超时,数据传输过程中数据包之间间隔的最大时间
                                .setConnectionRequestTimeout(20000)//使用连接池来管理连接,从连接池获取连接的超时时间
                                .build();
    
                        //配置io线程
                        IOReactorConfig ioReactorConfig = IOReactorConfig.custom().
                                setIoThreadCount(Runtime.getRuntime().availableProcessors())
                                .setSoKeepAlive(true)
                                .build();
                        //设置连接池大小
                        ConnectingIOReactor ioReactor = null;
                        try {
                            ioReactor = new DefaultConnectingIOReactor(ioReactorConfig);
                        } catch (IOReactorException e) {
                            e.printStackTrace();
                        }
                        PoolingNHttpClientConnectionManager connManager = new PoolingNHttpClientConnectionManager(ioReactor);
                        connManager.setMaxTotal(5);//最大连接数设置1
                        connManager.setDefaultMaxPerRoute(5);//per route最大连接数设置
    
                        client = HttpAsyncClients.custom()
                                .setConnectionManager(connManager)
                                .setDefaultRequestConfig(requestConfig)
                                .build();
                        client.start();
    
                    }
                }
            }
            return client;
        }
    
        public static HttpPost getPostBody(String urls, String bodys, ContentType contentType) {
            HttpPost post = null;
            StringEntity entity = null;
            post = new HttpPost(urls);
            entity = new StringEntity(bodys, contentType);
            post.setEntity(entity);
            return post;
        }
    }
    
    

    几个重要的参数

    ConnectTimeout : 连接超时,连接建立时间,三次握手完成时间。

    SocketTimeout : 请求超时,数据传输过程中数据包之间间隔的最大时间。

    ConnectionRequestTimeout : 使用连接池来管理连接,从连接池获取连接的超时时间。

    ConnTotal:连接池中最大连接数;

    ConnPerRoute(1000):分配给同一个route(路由)最大的并发连接数,route为运行环境机器到目标机器的一条线路

    3)测试
    CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();
    CloseableHttpAsyncClient httpClient = AsynHttpClient.getHttpClient();
    //        String url = "http://www.baidu.com/";
    //        String url = "https://www.cnblogs.com/";
    String url = "https://study.163.com/";
    String stringBody = JSONObject.toJSONString(AlarmInfoFrm.getInstanceFrom(alarmInfo));
    HttpPost postBody = AsynHttpClient.getPostBody(url, stringBody, ContentType.APPLICATION_JSON);
    //回调
    FutureCallback<HttpResponse> callback = new FutureCallback<HttpResponse>() {
        @Override
        public void completed(HttpResponse result) {
            System.out.println(result.getStatusLine() + "----i:"+i++ );
        }
        @Override
        public void failed(Exception e) {
            e.printStackTrace();
            System.err.println("失败:");
    
        }
        @Override
        public void cancelled() {
            System.err.println("cancelled");
    
        }
    };
    //连接池执行
    httpClient.execute(postBody,callback);
    

    参考的博客和官网地址如下

    https://blog.csdn.net/ouyang111222/article/details/78884634
    http://hc.apache.org/httpcomponents-asyncclient-4.1.x/quickstart.html

  • 相关阅读:
    第一次Java作业
    第十一次作业
    第十次作业
    第九次作业
    第八次作业
    第七次作业
    第六次作业
    Java中数组自定义排序与优先级队列笔记
    力扣每日一题:删除链表的倒数第N个节点
    又一次离谱的错误——运算符优先级
  • 原文地址:https://www.cnblogs.com/yz-yang/p/11596844.html
Copyright © 2020-2023  润新知