All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.zhizus.forest.thrift.client.cluster.privoder.PooledClusterProvider Maven / Gradle / Ivy

The newest version!
package com.zhizus.forest.thrift.client.cluster.privoder;

import com.zhizus.forest.thrift.client.PingValidate;
import com.zhizus.forest.thrift.client.ServerInfo;
import com.zhizus.forest.thrift.client.cluster.IClusterProvider;
import com.zhizus.forest.thrift.client.cluster.IsolationStrategy;
import com.zhizus.forest.thrift.client.utils.ThriftClientUtils;
import javassist.util.proxy.MethodFilter;
import javassist.util.proxy.MethodHandler;
import javassist.util.proxy.Proxy;
import javassist.util.proxy.ProxyFactory;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.apache.thrift.TServiceClient;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * Created by Dempe on 2016/12/26.
 */
public class PooledClusterProvider implements IClusterProvider {

    private GenericKeyedObjectPool pool;

    private IsolationStrategy isolationStrategy;

    public PooledClusterProvider(GenericKeyedObjectPoolConfig poolConfig, IsolationStrategy isolationStrategy, PingValidate pingValidate) {
        this.isolationStrategy = isolationStrategy;
        pool = new GenericKeyedObjectPool(new KeyedPooledThriftConnFactory(isolationStrategy, pingValidate), poolConfig);
    }

    public PooledClusterProvider(PingValidate pingValidate) {
        this(new GenericKeyedObjectPoolConfig(), new IsolationStrategy(), pingValidate);
    }

    @Override
    public  X iface(final ServerInfo serverInfo, final Class ifaceClass) throws Exception {
        final TTransport transport = pool.borrowObject(serverInfo);
        // 代理
        ProxyFactory factory = new ProxyFactory();
        factory.setSuperclass(ifaceClass);
        factory.setFilter(new MethodFilter() {
            @Override
            public boolean isHandled(Method m) {
                return ThriftClientUtils.getInterfaceMethodNames(ifaceClass).contains(m.getName());
            }
        });
        try {
            X x = (X) factory.create(new Class[]{TProtocol.class}, new Object[]{new TBinaryProtocol(transport)});
            ((Proxy) x).setHandler(new MethodHandler() {
                @Override
                public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
                    boolean success = false;
                    try {
                        Object result = proceed.invoke(self, args);
                        success = true;
                        //统计调用次数
                        serverInfo.incrementAndGet();
                        return result;
                    } finally {
                        if (success) {
                            pool.returnObject(serverInfo, transport);
                        } else {
                            isolationStrategy.fail(serverInfo);
                            pool.invalidateObject(serverInfo, transport);
                        }
                    }
                }
            });
            return x;
        } catch (NoSuchMethodException | IllegalArgumentException | InstantiationException | IllegalAccessException
                | InvocationTargetException e) {
            throw new RuntimeException("fail to create proxy.", e);
        }
    }

    public void clear(ServerInfo key) {
        pool.clear(key);
    }

    /**
     * Created by Dempe on 2016/12/23.
     */
    public static class KeyedPooledThriftConnFactory implements KeyedPooledObjectFactory {

        private static final Logger logger = LoggerFactory.getLogger(KeyedPooledThriftConnFactory.class);

        private int timeout;
        private IsolationStrategy isolationStrategy;

        private PingValidate pingValidate;

        public KeyedPooledThriftConnFactory(IsolationStrategy isolationStrategy, PingValidate pingValidate) {
            this.isolationStrategy = isolationStrategy;
            this.pingValidate = pingValidate;
            this.timeout = (int) TimeUnit.SECONDS.toMillis(5L);
        }

        @Override
        public PooledObject makeObject(ServerInfo info) throws Exception {
            TSocket tsocket = new TSocket(info.getHost(), info.getPort());
            tsocket.setTimeout(timeout);
            TFramedTransport transport = new TFramedTransport(tsocket);
            transport.open();
            logger.trace("make new thrift connection:{}", info);
            return new DefaultPooledObject(transport);
        }


        @Override
        public void destroyObject(ServerInfo key, PooledObject p) throws Exception {

        }

        @Override
        public boolean validateObject(ServerInfo key, PooledObject p) {
            boolean validate = p.getObject().isOpen() && (pingValidate == null || pingValidate.ping(key, p.getObject()));
            if (!validate) {
                isolationStrategy.fail(key);
            }
            return validate;
        }


        @Override
        public void activateObject(ServerInfo key, PooledObject p) throws Exception {

        }

        @Override
        public void passivateObject(ServerInfo key, PooledObject p) throws Exception {

        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy