Thrift和Spring集成

1.服務端通過TMultiplexedProcessor同時暴露多個服務

/**
 * Thrift通用服務啓動類 可以和spring集成
 */
public class CommonServerDemo {

    private int port;

    private Map<String, Object> exposedServerMap;

    public CommonServerDemo(int port, Map<String, Object> exposedServerMap) {
        this.port = port;
        this.exposedServerMap = exposedServerMap;
    }

    public void start() {
        try {
            TNonblockingServerTransport socket = new TNonblockingServerSocket(port);

            TMultiplexedProcessor mp = new TMultiplexedProcessor();

            //同時暴露多個服務
            for (Map.Entry<String, Object> entry : exposedServerMap.entrySet()) {
                String serviceInterface = entry.getKey();
                Class<?> processorClass = Class.forName(serviceInterface + "$Processor");
                Class<?> ifaceClass = Class.forName(serviceInterface + "$Iface");
                Constructor<?> constructor = processorClass.getConstructor(ifaceClass);
                Object impl = entry.getValue();
                TProcessor processor = (TProcessor) constructor.newInstance(impl);

                mp.registerProcessor(serviceInterface, processor);
            }

            TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(socket);
            args.processor(mp);
            args.transportFactory(new TFramedTransport.Factory());
            args.protocolFactory(new TCompactProtocol.Factory());

            TServer server = new TThreadedSelectorServer(args);
            server.serve();

            //TODO 註冊服務
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Map<String, Object> exposedServerMap = new HashMap<>();
        exposedServerMap.put(HelloWorldService.class.getName(), new HelloWorldImpl());
        new CommonServerDemo(8089, exposedServerMap).start();
    }
}

2.客戶端構建一個連接池

2.1連接提供者接口

public interface ConnectionProvider {

    TTransport getConnection();

    void returnConnection(TTransport tSocket);

}

2.2連接提供者實現

我們使用的是apache 的commons-pool實現連接池
public class ConnectionProviderImpl implements ConnectionProvider {

    private String ip;

    private int port;

    private int readTimeout;

    private int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;

    private int maxIdel = GenericObjectPool.DEFAULT_MAX_IDLE;

    private int minIdel = GenericObjectPool.DEFAULT_MIN_IDLE;

    private long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;

    /**
     * 取對象時 是否測試可用
     */
    private boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;

    /**
     * 還對象時 是否測試可用
     */
    private boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;

    /**
     * 空閒的時候 是否測試可用
     */
    private boolean testWhileIdel = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;

    private GenericObjectPool<TTransport> objectPool;

    public void init() {
        ThriftPoolableObjectFactory factory = new ThriftPoolableObjectFactory(ip, port, readTimeout);
        objectPool = new GenericObjectPool<>(factory);

        objectPool.setMaxActive(maxActive);
        objectPool.setMaxIdle(maxIdel);
        objectPool.setMinIdle(minIdel);
        objectPool.setMaxWait(maxWait);
        objectPool.setTestOnBorrow(testOnBorrow);
        objectPool.setTestOnReturn(testOnReturn);
        objectPool.setTestWhileIdle(testWhileIdel);
        //鏈接耗盡時應該怎麼做
        objectPool.setWhenExhaustedAction(GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION);
    }

    public void destory() {
        try {
            objectPool.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public TTransport getConnection() {
        try {
            return objectPool.borrowObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void returnConnection(TTransport tSocket) {
        try {
            objectPool.returnObject(tSocket);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getReadTimeout() {
        return readTimeout;
    }

    public void setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
    }

    public int getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(int maxActive) {
        this.maxActive = maxActive;
    }

    public int getMaxIdel() {
        return maxIdel;
    }

    public void setMaxIdel(int maxIdel) {
        this.maxIdel = maxIdel;
    }

    public int getMinIdel() {
        return minIdel;
    }

    public void setMinIdel(int minIdel) {
        this.minIdel = minIdel;
    }

    public long getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public boolean isTestOnBorrow() {
        return testOnBorrow;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public boolean isTestOnReturn() {
        return testOnReturn;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public boolean isTestWhileIdel() {
        return testWhileIdel;
    }

    public void setTestWhileIdel(boolean testWhileIdel) {
        this.testWhileIdel = testWhileIdel;
    }
}

/**
 * 連接的管理
 */
public class ThriftPoolableObjectFactory implements PoolableObjectFactory<TTransport> {

    private String ip;
    private int port;
    private int readTimeOut;

    public ThriftPoolableObjectFactory(String ip, int port, int readTimeOut) {
        this.ip = ip;
        this.port = port;
        this.readTimeOut = readTimeOut;
    }

    @Override
    public TTransport makeObject() throws Exception {
        TTransport tTransport = new TSocket(ip, port, readTimeOut);
        tTransport.open();
        return tTransport;
    }

    @Override
    public void destroyObject(TTransport tTransport) throws Exception {
        if (tTransport.isOpen()) {
            tTransport.close();
        }

    }

    @Override
    public boolean validateObject(TTransport tTransport) {
        try {
            if (tTransport.isOpen()) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }

    /**
     * 激活對象
     */
    @Override
    public void activateObject(TTransport tTransport) throws Exception {

    }

    /**
     * 鈍化對象
     */
    @Override
    public void passivateObject(TTransport tTransport) throws Exception {

    }
}

2.3通過ThreadLocal 實現連接的獲取和返還

public class ConnectionManager {

    private static final ThreadLocal<TTransport> transportThreadLocal = new ThreadLocal<>();

    private ConnectionProvider connectionProvider;

    public TTransport getConnection() {
        TTransport connection = connectionProvider.getConnection();
        transportThreadLocal.set(connection);
        return connection;
    }

    public void returnConnection() {
        try {
            TTransport tTransport = transportThreadLocal.get();
            connectionProvider.returnConnection(tTransport);
        }finally {
            transportThreadLocal.remove();
        }
    }
    public void setConnectionProvider(ConnectionProvider connectionProvider) {
        this.connectionProvider = connectionProvider;
    }
}

3.客戶端通過FactoryBean生成代理

public class CommonClientDemo<T> implements FactoryBean<T> {

    /**
     * 獲取連接和返還連接
     */
    private ConnectionManager connectionManager;

    /**
     * 服務的Iface接口
     */
    private Class interfaces;

    /**
     * 服務的Client類構造器
     */
    private Constructor<?> constructor;

    /**
     * 服務類完整路徑
     */
    private String serviceName;

    public CommonClientDemo(String hostName, int port, int timeOut, Class serviceClazz) {
        try {
            ConnectionProviderImpl connectionProvider = new ConnectionProviderImpl();
            connectionProvider.setIp(hostName);
            connectionProvider.setPort(port);
            connectionProvider.setReadTimeout(timeOut);
            connectionProvider.init();

            connectionManager = new ConnectionManager();
            connectionManager.setConnectionProvider(connectionProvider);
            serviceName = serviceClazz.getName();
            //獲得service裏面的Iface 接口
            interfaces = Class.forName(serviceName + "$Iface");
            //獲得service裏面的Client            Class<?> clientClass = Class.forName(serviceName + "$Client");
            constructor = clientClass.getConstructor(TProtocol.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public T getObject() {
        try {
            //創建代理
            ClassLoader classLoader = this.getClass().getClassLoader();
            return (T) newProxyInstance(classLoader, new Class[]{interfaces}, new InvocationHandler() {
                @Override
                public Object invoke(Object o, Method method, Object[] params) throws Throwable {
                    try {
                        TTransport tTransport = connectionManager.getConnection();
                        TFramedTransport tFramedTransport = new TFramedTransport(tTransport);
                        TProtocol protocol = new TCompactProtocol(tFramedTransport);

                        TMultiplexedProtocol map = new TMultiplexedProtocol(protocol, serviceName);

                        //創建client實例
                        Object target = constructor.newInstance(map);

                        return method.invoke(target, params);
                    } finally {
                        connectionManager.returnConnection();
                    }
                }
            });
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Class<?> getObjectType() {
        return interfaces;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    public static void main(String[] args) throws TException {
        CommonClientDemo<HelloWorldService.Iface> commonClientDemo = new CommonClientDemo<>("localhost", 8089, 1000, HelloWorldService.class);
        HelloWorldService.Iface client = commonClientDemo.getObject();
        System.out.println(commonClientDemo.getObjectType());
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10000; i++) {
            final int index = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        String zhp = client.sayHello("zhp" + index);
                        System.out.println(zhp);
                    } catch (TException e) {
                        e.printStackTrace();
                    }

                }
            });

        }
        executorService.shutdown();
    }

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章