package com.ganji.as.thrift.protocol.finagle.client.test;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.commons.lang.StringUtils;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.slf4j.LoggerFactory;
import com.ganji.as.thrift.protocol.builder.ThriftProtocolClientBuilder;
import com.ganji.as.thrift.protocol.service.intf.ThriftProtocolService;
import com.twitter.finagle.Service;
import com.twitter.finagle.builder.ClientBuilder;
import com.twitter.finagle.thrift.ThriftClientFramedCodec;
import com.twitter.finagle.thrift.ThriftClientRequest;
import com.twitter.util.Duration;
/**
*
* @author zhangzhenyu
*
*/
public abstract class BaseFinagleClient {
private final static int HOST_MODE = 0;// host+port模式
private final static int ZKPATH_MODE = 1;// zkPath模式
protected static final int AWAIT_TIME = 10000;// 等待回调超时时间限制,单位毫秒
private static Map<String, Service<ThriftClientRequest, byte[]>> hashCache = new HashMap<String, Service<ThriftClientRequest, byte[]>>();
protected int cur_mode;
protected String host;
protected int port;
protected String zkPath;
public void init(String _host, int _port) {
this.host = _host;
this.port = _port;
this.cur_mode = HOST_MODE;
getServiceToClientRefrence();
}
public void init(String _zkPath) {
this.zkPath = _zkPath;
this.cur_mode = ZKPATH_MODE;
getServiceToClientRefrence();
}
public void clear() {
}
protected TProtocolFactory getTProtocolFactory() {
return new TBinaryProtocol.Factory();
}
private String getCacheKey() {
StringBuffer sbKey = new StringBuffer();
sbKey.append(this.cur_mode);
sbKey.append("-");
sbKey.append(this.host);
sbKey.append("-");
sbKey.append(this.port);
sbKey.append("-");
sbKey.append(this.zkPath);
sbKey.append("-");
return sbKey.toString();
}
protected Service<ThriftClientRequest, byte[]> getClientRequest() {
if (this.cur_mode == HOST_MODE
&& (StringUtils.isBlank(this.host) || this.port == 0))
throw new RuntimeException("param is invalide");
if (this.cur_mode == ZKPATH_MODE && (StringUtils.isBlank(this.zkPath)))
throw new RuntimeException("param is invalide");
String cacheKey = getCacheKey();
if (hashCache.containsKey(cacheKey)
&& hashCache.get(cacheKey).isAvailable())
return hashCache.get(cacheKey);
Service<ThriftClientRequest, byte[]> clientRequest = null;
switch (this.cur_mode) {
case HOST_MODE:
InetSocketAddress inetSocketAddress = new InetSocketAddress(
this.host, this.port);
clientRequest = ClientBuilder.safeBuild(ClientBuilder.get()
.hosts(inetSocketAddress)
.codec(ThriftClientFramedCodec.get()).retries(3)
.tcpConnectTimeout(Duration.fromSeconds(30))
.hostConnectionLimit(100));
break;
case ZKPATH_MODE:
clientRequest = ClientBuilder.safeBuild(ClientBuilder.get()
.dest(this.zkPath).codec(ThriftClientFramedCodec.get())
.retries(3).tcpConnectTimeout(Duration.fromSeconds(30))
.hostConnectionLimit(100).keepAlive(true));
break;
default:
break;
}
hashCache.put(cacheKey, clientRequest);
return clientRequest;
}
static final private ConcurrentMap<String, ThriftProtocolService<com.ganji.as.thrift.protocol.client.request.ThriftClientRequest, byte[]>> serviceOfCache = new ConcurrentHashMap<>();
protected ThriftProtocolService<com.ganji.as.thrift.protocol.client.request.ThriftClientRequest, byte[]> getServiceToClientRefrence() {
if (this.cur_mode == HOST_MODE
&& (StringUtils.isBlank(this.host) || this.port == 0))
throw new RuntimeException("param is invalide");
if (this.cur_mode == ZKPATH_MODE && (StringUtils.isBlank(this.zkPath)))
throw new RuntimeException("param is invalide");
final String cacheKey = getCacheKey();
if (serviceOfCache.containsKey(cacheKey))
return serviceOfCache.get(cacheKey);
ThriftProtocolService<com.ganji.as.thrift.protocol.client.request.ThriftClientRequest, byte[]> serviceToClientRefrence = null;
switch (this.cur_mode) {
case HOST_MODE:
final InetSocketAddress inetSocketAddress = new InetSocketAddress(
this.host, this.port);
serviceToClientRefrence = ThriftProtocolClientBuilder
.safeBuild(ThriftProtocolClientBuilder
.get()
.codec(new TBinaryProtocol.Factory())
.retries(6)
.hosts(inetSocketAddress)
.hostConnectionLimit(2)
.logger(LoggerFactory
.getLogger("thrift-protocol-client")));
break;
case ZKPATH_MODE:
serviceToClientRefrence = ThriftProtocolClientBuilder
.safeBuild(ThriftProtocolClientBuilder
.get()
.codec(new TBinaryProtocol.Factory())
.retries(6)
.dest(this.zkPath)
.hostConnectionLimit(2)
.logger(LoggerFactory
.getLogger("thrift-protocol-client")));
break;
default:
break;
}
serviceOfCache.putIfAbsent(cacheKey, serviceToClientRefrence);
return serviceToClientRefrence;
}
/* added by yikangfeng */
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// TODO Auto-generated method stub
for (final String key : serviceOfCache.keySet()) {
if (key == null || key.isEmpty())
continue;
if (!(serviceOfCache.get(key) == null)) {
try {
serviceOfCache.get(key).close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
serviceOfCache.clear();
}
});
}
}