zoukankan      html  css  js  c++  java
  • httpclient 连接管理器

    连接操作器

    连接操作是客户端的底层套接字或可以通过外部实体,通常称为连接操作的被操作的状态的连接。
    OperatedClientConnection接口扩展了HttpClientConnection接口而且定义了额外的控制连接套接字的方法。
    ClientConnectionOperator接口代表了创建实例和更新那些对象底层套接字的策略。实现类最有可能利用SocketFactory来创建java.net.Socket实例。
    ClientConnectionOperator接口可以让HttpClient的用户提供一乐连接操作的定制策略和提供可选实现OperatedClientConnection接口的能力。
    

    管理连接和连接管理器

    HTTP连接是复杂的,有状态,线程不安全的对象需要正确的管理以便正确的执行功能。http连接在同一时间仅仅只能由一个执行线程来使用。
    
    Httpclient使用一个叫做http连接管理器的特殊实体类来管理http连接,这个实体类要实现HttpClientConnectionManager接口。
    Http连接管理器作用:
    Http连接管理器在新建http连接时,作为工厂类;
    管理持久http连接的生命周期;
    同步持久连接(确保线程安全,即一个http连接同一个时间只能被一个线程访问);
    
    http连接管理器和ManagedHttpClientConnection的实例类一起工作,为一个真实连接去充当一个代理服务,以管理连接状态和控制执行I/O操作。
    ManagedHttpClientConnection实体类可以看做http连接的一个代理服务器,管理IO操作。
    如果一个http连接被释放或者被它的消费者明确的表示要关闭,那么底层的连接就会和它的代理进行分离,并且该连接会被交还给连接管理器。
    即使服务消费者仍然持有代理的引用,但它不能再执行IO操作,或者更改http连接的状态。
    HttpClientContext context = HttpClientContext.create();
    HttpClientConnectionManager connMrg = new BasicHttpClientConnectionManager();
    HttpRoute route = new HttpRoute(new HttpHost("localhost",80));
    //获取新的连接,这里可能耗费很多时间
    ConnectionRequest connRequest = connMrg.requestConnection(route,null);
    //10秒超时
    HttpClientConnection conn = connRequest.get(10,TimeUnit.SECONDS);
    try{
      //如果创建失败
      if(!conn.isOpen()){
       //establish connection based on its route info
        connMrg.connect(conn,route,1000,context);
      }else{
        //and mark it as route complete
        connMrg.routeComplete(conn,route,context);
      }
    }finally{
      connMrg.releaseConnection(conn,null,1,TimeUnit.MINUTES);
    }
    如果要终止连接,可以调用ConnectionRequest的cancel()方法。这个方法会解锁被ConnectionRequest类get()方法阻塞的线程。
    

    简单连接管理器

    BasicHttpClientConnectionManager是一个简单的连接管理器,它一次只能管理一个连接。尽管这个类是线程安全的,它在同一个时间也只能被一个线程使用。
    BasicHttpClientConnectionManager会尽量重用旧的连接来发送后续的请求,并且使用相同的路由。如果后续请求的路由和旧连接中的路由不匹配,BasichttpClientConnectionManager就会关闭当前连接,使用请求中的路由重新建立连接。如果当前的连接正在被占用,会抛出java.lang.IllegalStateException异常。
    ClientConnectionRequest connRequest = connMrg.requestConnection(
    new HttpRoute(new HttpHost("localhost", 80)), null);
    ManagedClientConnection conn = connRequest.getConnection(10, TimeUnit.SECONDS);
    try {
       BasicHttpRequest request = new BasicHttpRequest("GET", "/");
       conn.sendRequestHeader(request);
       HttpResponse response = conn.receiveResponseHeader();
       conn.receiveResponseEntity(response);
       HttpEntity entity = response.getEntity();
       if (entity != null) {
          BasicManagedEntity managedEntity = new BasicManagedEntity(entity, conn, true);
          // 替换实体
          response.setEntity(managedEntity);
       }
       // 使用响应对象做有用的事情。当响应内容被消耗后这个连接将会自动释放。
       connMrg.releaseConnection(conn,null,1,TimeUnit.MINUTES);
    } catch (IOException ex) {
       //在I/O error之上终止连接。
      conn.cancel();
      throw ex;
    }
    

    连接池管理器

    相对BasicHttpClientConnectionManager来说,PoolingHttpClientConnectionManager是一个复杂的类,它管理着客户端连接池,可以同时为很多线程提供Http连接请求。
    当请求一个新的连接时,如果连接池有可用的持久连接,连接管理器就会使用其中的一个,而不是在创建一个新的连接。PoolingHttpClientConnectionManager维护的连接数在每个路由基础和总数上都有限制,默认每个路由基础上的连接不超过2个,总连接数不能超过20.
    在实际应用中,这个限制可能会太小了,尤其是当服务器也使用http协议时。
    
    PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
    cm.setMaxTotal(200);
    cm.setDefaultMaxPerRoute(20);
    HttpHost localhost = new HttpHost("localhost",80);
    cm.setMaxPerRoute(new HttpRoute(localhost),50);
    CloseableHttpClient httpClient = HttpClients.custom()
                                                .setConnectionManager(cm)
                                                .build();
    

    连接管理器关闭

    当一个HttpClient实例不在需要并且即将离开其作用范围的时候,要关闭它的连接管理器以确保所有连接在管理器被关闭后保持活跃,并且这些连接的系统资源会被释放掉。
    CloseableHttpClient httpClient=<....>
    httpClient.close();
    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpGet httpget = new HttpGet("http://www.google.com/");
    HttpResponse response = httpclient.execute(httpget);
    HttpEntity entity = response.getEntity();
    System.out.println(response.getStatusLine());
    if (entity != null) {
       entity.consumeContent();
    }
    httpclient.getConnectionManager().shutdown();
    

    连接管理参数

    http.conn-manager.timeout
    定义了当从ClientConnectionManager中检索ManagedClientConnection实例时使用的毫秒级超时时间。
    如果这个参数没有设置就不会超时(默认无限大超时)
    http.conn-manager.max-per-route
    定义了每个路由连接的最大数量。这个限制由客户端连接管理器来解释,而且应用与独立的管理器实例,为ConnPerRoute类型的值
    http.conn-manager.max-total
    定义了总共连接的最大数目。这个限制由客户端连接管理器来解释,而且应用于独立的管理器实例。Integer类型的值。
    
  • 相关阅读:
    一轮项目冲刺——移山小分队(9)
    一轮项目冲刺——移山小分队(8)
    一轮冲刺项目——移山小分队(7)
    一轮项目冲刺——移山小分队(6)
    一轮项目冲刺——移山小分队(5)
    一轮项目冲刺——移山小分队(4)
    一轮项目冲刺——移山小分队(3)
    一轮项目冲刺——移山小分队(2)
    一轮项目冲刺——移山小分队(1)
    C# 记录循环消耗时间
  • 原文地址:https://www.cnblogs.com/ssgao/p/8829342.html
Copyright © 2011-2022 走看看