提到池一般做过Java开发的肯定会想到ObjectPool,Apache Commons项目确实给我们的开发得来了很大的便利性,其中的pool项目正是我们实现thrift连接池的基础,当然也离不了spring。
在工程中添加依赖jar包:
org.apache.thrift
libthrift
0.9.2
org.slf4j
slf4j-log4j12
1.5.8
commons-pool
commons-pool
1.6
org.springframework
spring-context
4.0.9.RELEASE
1.定义thrift服务接口描述
UserService.thrift
namespace java cn.slimsmart.thrift.demo.pool
struct UserRequest
{
1:string id
}
struct UserResponse
{
1:string code
2:map params
}
service UserService
{
UserResponse userInfo(1:UserRequest request)
}
2.使用thrift服务接口描述生成java接口及对象类
使用命令:thrift-0.9.2.exe -r -gen java ./UserService.thrift 生成java接口及对象,并将生成的java类复制到java工程。
cd gen-java\cn\slimsmart\thrift\demo\pool
UserRequest.java
UserResponse.java
UserService.java
3.服务接口实现类
UserServiceImpl.java
package cn.slimsmart.thrift.demo.pool;
import java.util.HashMap;
import java.util.Map;
import org.apache.thrift.TException;
import org.springframework.stereotype.Service;
/**
* 业务接口实现
*/
@Service
public class UserServiceImpl implements UserService.Iface{
@Override
public UserResponse userInfo(UserRequest request) throws TException {
try{
UserResponse urp=new UserResponse();
if(request.id.equals("10000")){
urp.setCode("0");
Map params= new HashMap();
params.put("name", "lucy");
urp.setParams(params);
}
System.out.println("接收参数是:id="+request.id);
return urp;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
4.服务端服务提供者实现
UserServiceServer.java
package cn.slimsmart.thrift.demo.pool;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.springframework.beans.factory.annotation.Autowired;
/**
* 服务端服务提供者
*/
public class UserServiceServer {
/** 服务的端口 */
private int servicePort;
@Autowired
private UserService.Iface iface;
public void start() {
try {
TServerSocket serverTransport = new TServerSocket(servicePort);
// 关联处理器与 服务的实现
TProcessor processor = new UserService.Processor(iface);
// TBinaryProtocol 二进制编码格式进行数据传输
// 设置协议工厂为 TBinaryProtocol.Factory
TBinaryProtocol.Factory proFactory = new TBinaryProtocol.Factory(true, true);
TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverTransport);
args.processor(processor);
args.protocolFactory(proFactory);
// 多线程服务器端使用标准的阻塞式 I/O
TServer server = new TThreadPoolServer(args);
System.out.println("Starting server on port " + servicePort + "......");
server.serve();
} catch (Exception e) {
e.printStackTrace();
}
}
public int getServicePort() {
return servicePort;
}
public void setServicePort(int servicePort) {
this.servicePort = servicePort;
}
}
5.配置server spring,pool/applicationContext-server.xml
thrift配置文件
6.服务端启动类
ServerTest.java
package cn.slimsmart.thrift.demo.pool;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ServerTest {
@SuppressWarnings("resource")
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:pool/applicationContext-server.xml");
UserServiceServer userServiceServer = (UserServiceServer) context.getBean(UserServiceServer.class);
userServiceServer.start();
}
}
package cn.slimsmart.thrift.demo.pool;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 连接池工厂
*/
public class ThriftPoolableObjectFactory implements PoolableObjectFactory {
private final Logger logger = LoggerFactory.getLogger(getClass());
/** 服务的IP */
private String serviceIP;
/** 服务的端口 */
private int servicePort;
/** 超时设置 */
private int timeOut;
public ThriftPoolableObjectFactory(String serviceIP, int servicePort, int timeOut) {
super();
this.serviceIP = serviceIP;
this.servicePort = servicePort;
this.timeOut = timeOut;
}
/**
* 激活对象
*/
@Override
public void activateObject(TTransport tTransport) throws Exception {
}
/**
* 销毁对象
*/
@Override
public void destroyObject(TTransport tTransport) throws Exception {
if (tTransport.isOpen()) {
tTransport.close();
}
}
/**
* 创建对象
*/
@Override
public TTransport makeObject() throws Exception {
try {
TTransport transport = new TSocket(this.serviceIP, this.servicePort, this.timeOut);
transport.open();
return transport;
} catch (Exception e) {
logger.error("error ThriftPoolableObjectFactory()", e);
throw new RuntimeException(e);
}
}
/**
* 使无效 以备后用
*/
@Override
public void passivateObject(TTransport tTransport) throws Exception {
}
/**
* 检验对象是否可以由pool安全返回
*/
@Override
public boolean validateObject(TTransport tTransport) {
try {
if (tTransport instanceof TSocket) {
TSocket thriftSocket = (TSocket) tTransport;
if (thriftSocket.isOpen()) {
return true;
} else {
return false;
}
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
}
package cn.slimsmart.thrift.demo.pool;
import org.apache.thrift.transport.TSocket;
/**
* 连接池接口
*
*/
public interface ConnectionProvider {
/**
* 取链接池中的一个链接
* @return TSocket
*/
TSocket getConnection();
/**
* 返回链接
* @param socket
*/
void returnCon(TSocket socket);
}
package cn.slimsmart.thrift.demo.pool;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* 连接池实现
*/
public class ConnectionProviderImpl implements ConnectionProvider, InitializingBean, DisposableBean {
/** 服务的IP地址 */
private String serviceIP;
/** 服务的端口 */
private int servicePort;
/** 连接超时配置 */
private int conTimeOut;
/** 可以从缓存池中分配对象的最大数量 */
private int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
/** 缓存池中最大空闲对象数量 */
private int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
/** 缓存池中最小空闲对象数量 */
private int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
/** 阻塞的最大数量 */
private long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
/** 从缓存池中分配对象,是否执行PoolableObjectFactory.validateObject方法 */
private boolean testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
private boolean testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
private boolean testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
/** 对象缓存池 */
private ObjectPool objectPool = null;
@Override
public TSocket getConnection() {
try {
// 从对象池取对象
TSocket socket = (TSocket) objectPool.borrowObject();
return socket;
} catch (Exception e) {
throw new RuntimeException("error getConnection()", e);
}
}
@Override
public void returnCon(TSocket socket) {
try {
// 将对象放回对象池
objectPool.returnObject(socket);
} catch (Exception e) {
throw new RuntimeException("error returnCon()", e);
}
}
@Override
public void destroy() throws Exception {
try {
objectPool.close();
} catch (Exception e) {
throw new RuntimeException("erorr destroy()", e);
}
}
@SuppressWarnings("deprecation")
@Override
public void afterPropertiesSet() throws Exception {
// 对象池
objectPool = new GenericObjectPool();
//
((GenericObjectPool) objectPool).setMaxActive(maxActive);
((GenericObjectPool) objectPool).setMaxIdle(maxIdle);
((GenericObjectPool) objectPool).setMinIdle(minIdle);
((GenericObjectPool) objectPool).setMaxWait(maxWait);
((GenericObjectPool) objectPool).setTestOnBorrow(testOnBorrow);
((GenericObjectPool) objectPool).setTestOnReturn(testOnReturn);
((GenericObjectPool) objectPool).setTestWhileIdle(testWhileIdle);
((GenericObjectPool) objectPool).setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_BLOCK);
// 设置factory
ThriftPoolableObjectFactory thriftPoolableObjectFactory = new ThriftPoolableObjectFactory(serviceIP, servicePort, conTimeOut);
objectPool.setFactory(thriftPoolableObjectFactory);
}
public String getServiceIP() {
return serviceIP;
}
public void setServiceIP(String serviceIP) {
this.serviceIP = serviceIP;
}
public int getServicePort() {
return servicePort;
}
public void setServicePort(int servicePort) {
this.servicePort = servicePort;
}
public int getConTimeOut() {
return conTimeOut;
}
public void setConTimeOut(int conTimeOut) {
this.conTimeOut = conTimeOut;
}
public int getMaxActive() {
return maxActive;
}
public void setMaxActive(int maxActive) {
this.maxActive = maxActive;
}
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
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 isTestWhileIdle() {
return testWhileIdle;
}
public void setTestWhileIdle(boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
public ObjectPool getObjectPool() {
return objectPool;
}
public void setObjectPool(ObjectPool objectPool) {
this.objectPool = objectPool;
}
}
package cn.slimsmart.thrift.demo.pool;
import org.apache.thrift.transport.TSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 连接池管理
*/
@Service
public class ConnectionManager {
/** 日志记录器 */
private final Logger logger = LoggerFactory.getLogger(getClass());
/** 保存local对象 */
ThreadLocal socketThreadSafe = new ThreadLocal();
/** 连接提供池 */
@Autowired
private ConnectionProvider connectionProvider;
public TSocket currentSocket() {
return socketThreadSafe.get();
}
public void close() {
connectionProvider.returnCon(socketThreadSafe.get());
socketThreadSafe.remove();
}
public TSocket getSocket() {
TSocket socket = null;
try {
socket = connectionProvider.getConnection();
socketThreadSafe.set(socket);
return socket;
} catch (Exception e) {
logger.error("error ConnectionManager.invoke()", e);
}
return socket;
}
}
package cn.slimsmart.thrift.demo.pool;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TTransportException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 服务客户端调用
*/
@Service
public class UserServiceClient {
@Autowired
private ConnectionManager connectionManager;
public void invoke() {
try {
TProtocol protocol = new TBinaryProtocol(connectionManager.getSocket());
UserService.Client client = new UserService.Client(protocol);
UserRequest request = new UserRequest();
request.setId("10000");
UserResponse urp = client.userInfo(request);
if (urp.code != null && !urp.code.equals("")) {
System.out.println("返回代码:" + urp.code + "; 参数是:" + urp.params.get("name"));
}
} catch (TTransportException e) {
e.printStackTrace();
} catch (TException e) {
e.printStackTrace();
}finally {
connectionManager.close();
}
}
}
thrift配置文件
package cn.slimsmart.thrift.demo.pool;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ClientTest {
@SuppressWarnings("resource")
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:pool/applicationContext-client.xml");
UserServiceClient userServiceClient = (UserServiceClient) context.getBean(UserServiceClient.class);
userServiceClient.invoke();
}
}
启动ServerTest.java,在运行客户端测试ClientTest.java。