用apache commons-pool2建立thrift連接池


  Apache Thrift 是 Facebook 實現的一種高效的、支持多種編程語言的遠程服務調用的框架。具體的介紹可以看Apache的官方網站:http://thrift.apache.org/ 。今天並不介紹thrift如何使用,只是演示一下如何使用commons-pool2建立thrift連接池,這樣可以快速訪問服務端。

      我演示的thrift接口如下所示:

 

  public interface Iface {

    public String genNewKTVOrder(com.ethank.thrift.iface.service.TOrder torder) throws org.apache.thrift.TException;

    public String genWeiXinPreOrder(String orderId, String body) throws org.apache.thrift.TException;

    public String genPreKTVGoodsOrder(String reserveGoodsId, String reserveBoxId, String goodsList, String sumPrice, int userId, String ktvId) throws org.apache.thrift.TException;

    public String genWeiXinQRCode(String orderId, String body) throws org.apache.thrift.TException;

  }

 

 

       

這些代碼都是通過thrift自動生成的,具體如何操作可以看網上搜索一些thrift教程。

thrift客戶端是這樣一個內部類:

       public static class Client extends org.apache.thrift.TServiceClient implements Iface   

我的思路實在pool中放入org.apache.thrift.transport.TSocket對象,其工廠方法如下:

 

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.thrift.transport.TSocket;


public class ConnectionFactory extends BasePooledObjectFactory<TSocket>{

    @Override
    public TSocket create() throws Exception {
        TSocket transport = new TSocket("192.168.1.222", 34568, 2000); //建立TSocket,根據具體情況可以修改
        transport.open();
        return transport;
    }
    
    @Override
    public boolean validateObject(org.apache.commons.pool2.PooledObject<TSocket> p){  //校驗對象有效性
        TSocket transport = p.getObject();return transport.isOpen();
    }
    

    @Override
    public PooledObject<TSocket> wrap(TSocket obj) {    //創建包裝對象,包裝對象是真正放在pool中的對象
        return new DefaultPooledObject<TSocket>(obj);
    }
    
    @Override
    public void destroyObject(PooledObject<TSocket> p) throws Exception { //銷毀對象,關閉鏈接
        if (p.getObject().isOpen()) {
            p.getObject().close();
        }
    }

}

 

實際調用中並不是用的TSocket,而是Client對象,為此建立ConnectionManager利用TSocket建立Client對象:

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ethank.thrift.iface.service.EthankOrderService;

public class ConnectionManager {
    
     private static final Logger LGR = LoggerFactory.getLogger(ConnectionManager.class);
    
    private static GenericObjectPool<TSocket> pool;
    
    static {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMaxIdle(10);   //最大空閑數量
        config.setMaxTotal(20);  //連接池最大數量
        config.setMinIdle(3);    //最小空閑數量
        config.setTestOnBorrow(true);  //在從pool中去對象時進行有效性檢查,會調用工廠中的validateObject
        config.setMaxWaitMillis(1000); //提取對象時最大等待時間,超時會拋出異常
        config.setMinEvictableIdleTimeMillis(60000); // 最小的空閑對象驅除時間間隔,空閑超過指定的時間的對象,會被清除掉
        config.setTimeBetweenEvictionRunsMillis(30000);//后台驅逐線程休眠時間
        config.setNumTestsPerEvictionRun(3); //設置驅逐線程每次檢測對象的數量
        config.setTestWhileIdle(true);  //是否對空閑對象使用PoolableObjectFactory的validateObject校驗,
        pool = new GenericObjectPool<TSocket>(connectionFactory, config);
    }    
    
    
    public static EthankOrderService.Client getThriftConnetion(){
            TSocket socket;
            try {
                socket = pool.borrowObject();
                TProtocol protocol = new TCompactProtocol(socket);
                EthankOrderService.Client client= new EthankOrderService.Client(protocol);
                client.socket = socket;
                return client;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
    }
    
    public static void returnThriftConnetion(EthankOrderService.Client client){
            pool.returnObject(client.socket);
    }
    
    public static int getPoolObjectNum() {
        return pool.getNumIdle();
    }
    
    

}

 

測試類做測試:

    public static void main(String[] args)  {
        for (int i = 0; i < 20; i++) {
            try {
                new Thread(new Runnable() {
                    public void run() {
                        EthankOrderService.Client client = null;
                        try {
                            client = ConnectionManager.getThriftConnetion();
                            String re = client.genWeiXinPreOrder("1111111", "222");
                            System.out.println(re+"   "+ client.socket.hashCode());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }finally{
                            ConnectionManager.returnThriftConnetion(client);
                        }
                        
                    }
                }).start();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
}

 

       這只是一個最簡單的pool使用實例,可以做很多的改進,如優化pool中對象,加入動態代理以屏蔽client其他接口。此實例盡起拋磚引玉!

 

參考資料:

      1.  apache commons-pool的配置參數    http://www.thinksaas.cn/group/topic/96620/    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM