Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alibaba.tmq.client.remoting.ClientRemoting Maven / Gradle / Ivy
package com.alibaba.tmq.client.remoting;
import java.lang.reflect.InvocationHandler;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.CollectionUtils;
import com.alibaba.tmq.client.context.ClientContext;
import com.alibaba.tmq.client.remoting.processor.ClientRequestProcessor;
import com.alibaba.tmq.client.remoting.proxy.ClientInvocationHandler;
import com.alibaba.tmq.client.remoting.timer.ClientHeartBeatTimer;
import com.alibaba.tmq.client.util.StringUtil;
import com.alibaba.tmq.common.constants.Constants;
import com.alibaba.tmq.common.context.InvocationContext;
import com.alibaba.tmq.common.domain.ConnectionKey;
import com.alibaba.tmq.common.domain.remoting.ConnectionChannel;
import com.alibaba.tmq.common.domain.result.Result;
import com.alibaba.tmq.common.exception.InitException;
import com.alibaba.tmq.common.exception.RemotingConnectException;
import com.alibaba.tmq.common.exception.RemotingSendRequestException;
import com.alibaba.tmq.common.exception.RemotingTimeoutException;
import com.alibaba.tmq.common.remoting.netty.NettyClientConfig;
import com.alibaba.tmq.common.remoting.netty.NettyRemotingClient;
import com.alibaba.tmq.common.remoting.protocol.RemotingCommand;
import com.alibaba.tmq.common.service.ServerService;
import com.alibaba.tmq.common.util.ListUtil;
import com.alibaba.tmq.common.util.RandomUtil;
import com.alibaba.tmq.common.util.TableUtil;
import io.netty.channel.Channel;
/**
* 客户端远程通信服务
* @author tianyao.myc
*
*/
public class ClientRemoting extends ClientContext implements Constants {
private static final Log logger = LogFactory.getLog(ClientRemoting.class);
/** 远程通信客户端 */
private NettyRemotingClient client = null;
/** 定时调度服务 */
private ScheduledExecutorService executorService = Executors
.newScheduledThreadPool(1, new ThreadFactory() {
int index = 0;
public Thread newThread(Runnable runnable) {
index ++;
return new Thread(runnable, "TMQ-heart-beat-thread-" + index);
}
});
/** 客户端代理调用接口 */
private static InvocationHandler invocationHandler = new ClientInvocationHandler();
public static ServerService serverService = proxyInterface(ServerService.class);
/** RPC响应线程池 */
private ThreadPoolExecutor executors = null;
/** 请求队列 */
private LinkedBlockingQueue requestQueue;
/** 服务器列表缓存 */
private volatile List cachedServerListForProducer;
/** 服务器列表缓存 */
private volatile List cachedBackupServerListForProducer;
/** 服务器列表缓存 */
private volatile List cachedServerListForConsumer;
/** 服务器列表缓存 */
private volatile List cachedBackupServerListForConsumer;
private volatile boolean isolated = false;
/**
* 初始化
* InitException
*/
public void init() throws InitException {
/** 初始化远程通信客户端 */
initRemotingClient();
/** 初始化心跳定时器 */
initHeartBeatTimer();
}
/**
* 初始化远程通信客户端
* InitException
*/
private void initRemotingClient() throws InitException {
NettyClientConfig config = new NettyClientConfig();
this.requestQueue = new LinkedBlockingQueue(clientConfig.getQueueSize());
ClientRequestProcessor processor = new ClientRequestProcessor(this.requestQueue);
processor.init();
client = new NettyRemotingClient(config);
executors = new ThreadPoolExecutor(clientConfig.getCoreRemotingThreads(), clientConfig.getMaxRemotingThreads(),
60 * 1000L, TimeUnit.MILLISECONDS,
requestQueue,
new ThreadFactory(){
int index = 0;
public Thread newThread(Runnable runnable) {
index ++;
return new Thread(runnable, "TMQ-remoting-thread-" + index);
}
});
client.registerProcessor(REQUEST_CODE, processor, executors);
try {
client.start();
} catch (Throwable e) {
throw new InitException("[ClientRemoting]: initRemotingClient error", e);
}
}
/**
* 初始化连接
* 向服务端所有机器建立长连接
* instanceName
* roleType
* roleId
* topic
* tag
* InitException
*/
public void initConnection(String instanceName, int roleType, String roleId, String topic, String tag) throws InitException {
List serverList;
List backupServerList;
if (roleType == ROLE_TYPE_PRODUCER) {
serverList = getServerListForProducer();
backupServerList = getbackupServerListForProducer();
} else {
serverList = getServerListForConsumer();
backupServerList = getbackupServerListForConsumer();
}
if(StringUtil.isNotBlank(clientConfig.getBackupDomainName())) {
if(! CollectionUtils.isEmpty(backupServerList)) {
serverList.addAll(backupServerList);
}
}
if (clientRemoting.isIsolated()) {
logger.warn("this machine was isolated, has no reason to init connection!!!");
return;
}
if(ListUtil.isEmpty(serverList)) {
logger.error("[ClientRemoting]: initConnection error, serverList is empty"
+ ", roleType:" + roleType
+ ", roleId:" + roleId
+ ", topic:" + topic
+ ", tag:" + tag);
throw new InitException("initConnection error, serverList is empty");
}
for(String server : serverList) {
/** 连接服务器 */
connectServer(instanceName, server, roleType, roleId, topic, tag);
}
}
/**
* 清除连接
* instanceName
* roleType
* roleId
* topic
* tag
* InitException
*/
public void removeConnection(String instanceName, int roleType, String roleId, String topic, String tag) throws InitException {
List serverList;
List backupServerList;
if (roleType == ROLE_TYPE_PRODUCER) {
serverList = getServerListForProducer();
backupServerList = getbackupServerListForProducer();
} else {
serverList = getServerListForConsumer();
backupServerList = getbackupServerListForConsumer();
}
if(StringUtil.isNotBlank(clientConfig.getBackupDomainName())) {
if(! CollectionUtils.isEmpty(backupServerList)) {
serverList.addAll(backupServerList);
}
}
if(ListUtil.isEmpty(serverList)) {
logger.error("[ClientRemoting]: removeConnection error, serverList is empty"
+ ", roleType:" + roleType
+ ", roleId:" + roleId
+ ", topic:" + topic
+ ", tag:" + tag);
return ;
}
for(String server : serverList) {
//断开服务器连接
disconnectServer(instanceName, server, roleType, roleId, topic, tag);
}
}
/**
* 连接服务器
* instanceName
* server
* roleType
* roleId
* topic
* tag
*/
public void connectServer(String instanceName, String server, int roleType, String roleId, String topic, String tag) {
Result connectResult = null;
try {
ConnectionChannel connectionChannel = new ConnectionChannel(server, roleType, roleId);
connectionChannel.setInstanceName(instanceName);
InvocationContext.setConnectionChannel(connectionChannel);
connectResult = serverService.connect(topic, tag);
} catch (Throwable e) {
logger.error("[ClientRemoting]: connectServer error"
+ ", clientConfig:" + clientConfig
+ ", server:" + server
+ ", roleType:" + roleType
+ ", roleId:" + roleId
+ ", topic:" + topic
+ ", tag:" + tag
+ ", instanceName" + instanceName, e);
}
if(connectResult != null && connectResult.getData().booleanValue()) {
} else {
logger.error("[ClientRemoting]: connectServer failed"
+ ", clientConfig:" + clientConfig
+ ", server:" + server
+ ", roleType:" + roleType
+ ", roleId:" + roleId
+ ", topic:" + topic
+ ", tag:" + tag
+ ", connectResult:" + connectResult);
}
}
/**
* 断开服务器连接
* instanceName
* server
* roleType
* roleId
* topic
* tag
*/
public void disconnectServer(String instanceName, String server, int roleType, String roleId, String topic, String tag) {
Result disconnectResult = null;
try {
ConnectionChannel connectionChannel = new ConnectionChannel(server, roleType, roleId);
connectionChannel.setInstanceName(instanceName);
InvocationContext.setConnectionChannel(connectionChannel);
disconnectResult = serverService.disconnect(new ConnectionKey(roleId, topic, tag));
} catch (Throwable e) {
logger.error("[ClientRemoting]: disconnectServer error"
+ ", clientConfig:" + clientConfig
+ ", server:" + server
+ ", roleType:" + roleType
+ ", roleId:" + roleId
+ ", topic:" + topic
+ ", tag:" + tag
+ ", instanceName" + instanceName, e);
}
if(disconnectResult != null && disconnectResult.getData().booleanValue()) {
} else {
logger.error("[ClientRemoting]: disconnectServer failed"
+ ", clientConfig:" + clientConfig
+ ", server:" + server
+ ", roleType:" + roleType
+ ", roleId:" + roleId
+ ", topic:" + topic
+ ", tag:" + tag
+ ", disconnectResult:" + disconnectResult);
}
}
/**
* 获取该消息要触发的那台Server
* messageKey
*
*/
public String acquireFireServer(String messageKey) {
if(StringUtil.isNotBlank(clientConfig.getBackupDomainName())) {
if(ListUtil.isEmpty(this.cachedBackupServerListForProducer)) {
return null;
}
return TableUtil.acquireFireServer(this.cachedBackupServerListForProducer, messageKey);
}
if(ListUtil.isEmpty(this.cachedServerListForProducer)) {
return null;
}
return TableUtil.acquireFireServer(this.cachedServerListForProducer, messageKey);
}
/**
* 从ZK获取服务器列表
*
*/
public List getServerListForProducer() {
if(null == this.cachedServerListForProducer) {
this.cachedServerListForProducer = zookeeper.getServerListForProducer();
}
return this.cachedServerListForProducer;
}
public List getbackupServerListForProducer() {
if(null == this.cachedBackupServerListForProducer) {
this.cachedBackupServerListForProducer = zookeeper.getbackupServerListForProducer();
}
return this.cachedBackupServerListForProducer;
}
/**
* 从ZK获取服务器列表
*
*/
public List getServerListForConsumer() {
if(null == this.cachedServerListForConsumer) {
this.cachedServerListForConsumer = zookeeper.getServerListForConsumer();
}
return this.cachedServerListForConsumer;
}
public List getbackupServerListForConsumer() {
if(null == this.cachedBackupServerListForConsumer) {
this.cachedBackupServerListForConsumer = zookeeper.getbackupServerListForConsumer();
}
return this.cachedBackupServerListForConsumer;
}
/**
* 初始化心跳定时器
* InitException
*/
private void initHeartBeatTimer() throws InitException {
try {
executorService.scheduleAtFixedRate(new ClientHeartBeatTimer(),
clientConfig.getHeartBeatIntervalTime(),
clientConfig.getHeartBeatIntervalTime(), TimeUnit.MILLISECONDS);
} catch (Throwable e) {
throw new InitException("[ClientRemoting]: initHeartBeatTimer error"
+ ", heartBeatIntervalTime:" + clientConfig.getHeartBeatIntervalTime(), e);
}
logger.warn("[ClientRemoting]: initHeartBeatTimer success"
+ ", heartBeatIntervalTime:" + clientConfig.getHeartBeatIntervalTime());
}
/**
* 代理接口
* interfaceClass
*
*/
public static T proxyInterface(Class interfaceClass) {
return proxyService.proxyInterface(interfaceClass, invocationHandler);
}
/**
* 获取连接
* addr
*
* InterruptedException
*/
public Channel getAndCreateChannel(final String addr) throws InterruptedException {
return client.getAndCreateChannel(addr);
}
/**
* 远程方法同步调用
* addr
* request
* timeoutMillis
*
* InterruptedException
* RemotingConnectException
* RemotingSendRequestException
* RemotingTimeoutException
*/
public RemotingCommand invokeSync(String addr, final RemotingCommand request, long timeoutMillis)
throws InterruptedException, RemotingConnectException, RemotingSendRequestException,
RemotingTimeoutException {
return client.invokeSync(addr, request, timeoutMillis);
}
/**
* 多线程环境同一个key拿到同一个counter
* key
*
*/
public AtomicLong getCounter(ConcurrentHashMap heartBeatCounter, String key) {
AtomicLong counter = heartBeatCounter.get(key);
if(null == counter) {
counter = new AtomicLong(0L);
AtomicLong existCounter = heartBeatCounter.putIfAbsent(key, counter);
if(existCounter != null) {
counter = existCounter;
}
}
return counter;
}
/**
* 心跳计数器递增
* connectionChannel
*/
public void increaseCounter(ConnectionChannel connectionChannel) {
switch(connectionChannel.getRoleType()) {
case ROLE_TYPE_PRODUCER:
//生产者计数器递增
break ;
case ROLE_TYPE_CONSUMER:
//消费者计数器递增
break ;
default:
}
}
public void setCachedServerListForProducer(List cachedServerList) {
this.cachedServerListForProducer = cachedServerList;
}
public void setCachedServerListForConsumer(List cachedServerList) {
this.cachedServerListForConsumer = cachedServerList;
}
public void setCachedBackupServerListForProducer(List cachedBackupServerList) {
this.cachedBackupServerListForProducer = cachedBackupServerList;
}
public void setCachedBackupServerListForConsumer(List cachedBackupServerList) {
this.cachedBackupServerListForConsumer = cachedBackupServerList;
}
public boolean isIsolated() {
return isolated;
}
public void setIsolated(boolean isolated) {
this.isolated = isolated;
}
}