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