实现一个简单的HttpClient连接池(转自博客园)

来源:互联网 发布:腾讯算法面试题 编辑:程序博客网 时间:2024/05/29 17:06

一、为什么要用Http连接池

1、降低延迟:如果不采用连接池,每次连接发起Http请求的时候都会重新建立TCP连接(经历3次握手),用完就会关闭连接(4次挥手),如果采用连接池则减少了这部分时间损耗,别小看这几次握手,本人经过测试发现,基本上3倍的时间延迟

2、支持更大的并发:如果不采用连接池,每次连接都会打开一个端口,在大并发的情况下系统的端口资源很快就会被用完,导致无法建立新的连接


代码示例:

                                                              //继承BasePooledObjectFactory抽象类

public class StringFactory extends BasePooledObjectFactory{


    public StringFactory(){
        System.out.println("init string factory..");
    }
    
    //生成对象
    public PooledObject<HttpClient> makeObject() throws Exception {
        HttpClient httpClient = new HttpClient();
        System.out.println("创建了:"+httpClient);
        return new DefaultPooledObject<HttpClient>(httpClient);
    }
    //销毁对象
    public void destroyObject(GenericObjectPool<HttpClient> pool ) throws Exception {
        HttpClient httpClient = pool.borrowObject();
        httpClient= null;
    }
    
    

    public static void main(String[] args) throws Exception {
        StringFactory factory = new StringFactory();
        GenericObjectPoolConfig conf = new GenericObjectPoolConfig();
        conf.setMaxTotal(10);//创建数量
        @SuppressWarnings("unchecked")
        GenericObjectPool<HttpClient> pool = new GenericObjectPool<HttpClient>(new StringFactory(), conf);
        for(int i=0;i<15;i++){
            System.out.println(i+":");
            try {
                HttpClient http1 = pool.borrowObject();
                HttpClient http2 = pool.borrowObject();
                HttpClient http3 = pool.borrowObject();
                pool.returnObject(http1);
            } catch (Exception e) {
                e.printStackTrace();
            }           
        }
        factory.destroyObject(pool);//销毁对象
    }

}

二、原理及注意事项

连接池中连接都是在发起请求的时候建立,并且都是长连接

HaoMaiClient.java中的in.close();作用就是将用完的连接释放,下次请求可以复用,这里特别注意的是,如果不使用in.close();而仅仅使用response.close();结果就是连接会被关闭,并且不能被复用,这样就失去了采用连接池的意义。

连接池释放连接的时候,并不会直接对TCP连接的状态有任何改变,只是维护了两个Set,leased和avaliabled,leased代表被占用的连接集合,avaliabled代表可用的连接的集合,释放连接的时候仅仅是将连接从leased中remove掉了,并把连接放到avaliabled集合