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(); } }