use of com.alipay.sofa.rpc.transport.ClientTransport in project sofa-rpc by sofastack.
the class AllConnectConnectionHolder method closeAllClientTransports.
/**
* 销毁全部连接
*
* @param destroyHook 销毁钩子
*/
@Override
public void closeAllClientTransports(DestroyHook destroyHook) {
// 清空所有列表,不让再调了
Map<ProviderInfo, ClientTransport> all = clearProviders();
if (destroyHook != null) {
try {
destroyHook.preDestroy();
} catch (Exception e) {
if (LOGGER.isWarnEnabled(consumerConfig.getAppName())) {
LOGGER.warnWithApp(consumerConfig.getAppName(), e.getMessage(), e);
}
}
}
// 多线程销毁已经建立的连接
int providerSize = all.size();
if (providerSize > 0) {
int timeout = consumerConfig.getDisconnectTimeout();
// 最大10个
int threads = Math.min(10, providerSize);
final CountDownLatch latch = new CountDownLatch(providerSize);
ThreadPoolExecutor closePool = new ThreadPoolExecutor(threads, threads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(providerSize), new NamedThreadFactory("CLI-DISCONN-" + consumerConfig.getInterfaceId(), true));
for (Map.Entry<ProviderInfo, ClientTransport> entry : all.entrySet()) {
final ProviderInfo providerInfo = entry.getKey();
final ClientTransport transport = entry.getValue();
closePool.execute(new Runnable() {
@Override
public void run() {
try {
ClientTransportFactory.releaseTransport(transport, 0);
} catch (Exception e) {
if (LOGGER.isWarnEnabled(consumerConfig.getAppName())) {
LOGGER.warnWithApp(consumerConfig.getAppName(), "catch exception but ignore it when close alive client : {}", providerInfo);
}
} finally {
latch.countDown();
}
}
});
}
try {
int totalTimeout = ((providerSize % threads == 0) ? (providerSize / threads) : ((providerSize / threads) + 1)) * timeout + 500;
// 一直等到
latch.await(totalTimeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
LOGGER.errorWithApp(consumerConfig.getAppName(), "Exception when close transport", e);
} finally {
closePool.shutdown();
}
}
}
use of com.alipay.sofa.rpc.transport.ClientTransport in project sofa-rpc by sofastack.
the class AllConnectConnectionHolder method initClientRunnable.
/**
* 线程池建立长连接
*/
protected void initClientRunnable(ThreadPoolExecutor initPool, final CountDownLatch latch, final ProviderInfo providerInfo) {
final ClientTransportConfig config = providerToClientConfig(providerInfo);
initPool.execute(new Runnable() {
@Override
public void run() {
ClientTransport transport = ClientTransportFactory.getClientTransport(config);
if (consumerConfig.isLazy()) {
uninitializedConnections.put(providerInfo, transport);
latch.countDown();
} else {
try {
initClientTransport(consumerConfig.getInterfaceId(), providerInfo, transport);
} finally {
// 连上或者抛异常
latch.countDown();
}
}
}
});
}
use of com.alipay.sofa.rpc.transport.ClientTransport in project sofa-rpc by sofastack.
the class AbstractCluster method select.
/**
* 根据规则进行负载均衡
*
* @param message 调用对象
* @param invokedProviderInfos 已调用列表
* @return 一个可用的provider
* @throws SofaRpcException rpc异常
*/
protected ProviderInfo select(SofaRequest message, List<ProviderInfo> invokedProviderInfos) throws SofaRpcException {
// 粘滞连接,当前连接可用
if (consumerConfig.isSticky()) {
if (lastProviderInfo != null) {
ProviderInfo providerInfo = lastProviderInfo;
ClientTransport lastTransport = connectionHolder.getAvailableClientTransport(providerInfo);
if (lastTransport != null && lastTransport.isAvailable()) {
checkAlias(providerInfo, message);
return providerInfo;
}
}
}
// R1:Record routing address time
// 原始服务列表数据 --> 路由结果
long routerStartTime = System.nanoTime();
List<ProviderInfo> providerInfos = routerChain.route(message, null);
RpcInternalContext context = RpcInternalContext.peekContext();
RpcInvokeContext rpcInvokeContext = RpcInvokeContext.getContext();
rpcInvokeContext.put(RpcConstants.INTERNAL_KEY_CLIENT_ROUTER_TIME_NANO, System.nanoTime() - routerStartTime);
// 保存一下原始地址,为了打印
List<ProviderInfo> originalProviderInfos;
if (CommonUtils.isEmpty(providerInfos)) {
/**
* 如果注册中心没有provider,可能上下文中指定了provider
*
* 注册中心如果没有provider可用列表,需要识别上下文中是否存在直连Provider:
* 1. RpcInvokeContext.getContext().getTargetUrl()
*/
if (context != null) {
String targetIP = (String) context.getAttachment(RpcConstants.HIDDEN_KEY_PINPOINT);
if (StringUtils.isNotBlank(targetIP)) {
// 如果上下文指定provider,直接返回
ProviderInfo providerInfo = selectPinpointProvider(targetIP, providerInfos);
return providerInfo;
}
}
throw noAvailableProviderException(message.getTargetServiceUniqueName());
} else {
originalProviderInfos = new ArrayList<>(providerInfos);
}
if (CommonUtils.isNotEmpty(invokedProviderInfos)) {
// 已经调用异常的本次不再重试
providerInfos.removeAll(invokedProviderInfos);
// If all providers have retried once, then select by loadBalancer without filter.
if (CommonUtils.isEmpty(providerInfos)) {
providerInfos = originalProviderInfos;
}
}
String targetIP = null;
ProviderInfo providerInfo;
if (context != null) {
targetIP = (String) context.getAttachment(RpcConstants.HIDDEN_KEY_PINPOINT);
}
if (StringUtils.isNotBlank(targetIP)) {
// 如果指定了调用地址
providerInfo = selectPinpointProvider(targetIP, providerInfos);
ClientTransport clientTransport = selectByProvider(message, providerInfo);
if (clientTransport == null) {
// 指定的不存在或已死,抛出异常
throw unavailableProviderException(message.getTargetServiceUniqueName(), targetIP);
}
return providerInfo;
} else {
do {
// R4:Record load balancing time
// 再进行负载均衡筛选
long loadBalanceStartTime = System.nanoTime();
providerInfo = loadBalancer.select(message, providerInfos);
rpcInvokeContext.put(RpcConstants.INTERNAL_KEY_CLIENT_BALANCER_TIME_NANO, System.nanoTime() - loadBalanceStartTime);
ClientTransport transport = selectByProvider(message, providerInfo);
if (transport != null) {
return providerInfo;
}
providerInfos.remove(providerInfo);
} while (!providerInfos.isEmpty());
}
throw unavailableProviderException(message.getTargetServiceUniqueName(), convertProviders2Urls(originalProviderInfos));
}
use of com.alipay.sofa.rpc.transport.ClientTransport in project sofa-rpc by sofastack.
the class AllConnectConnectionHolder method removeNode.
public void removeNode(List<ProviderInfo> providerInfos) {
// first update last all providers
lastAddresses.removeAll(providerInfos);
String interfaceId = consumerConfig.getInterfaceId();
String appName = consumerConfig.getAppName();
if (LOGGER.isInfoEnabled(appName)) {
LOGGER.infoWithApp(appName, "Remove provider of {}, size is : {}", interfaceId, providerInfos.size());
}
for (ProviderInfo providerInfo : providerInfos) {
try {
// 从存活和重试列表里都删除
// 判断一个删成功 就不走下一个
ClientTransport transport = remove(providerInfo);
if (LOGGER.isInfoEnabled(appName)) {
LOGGER.infoWithApp(appName, "Remove provider of {}: {} from list success !", interfaceId, providerInfo);
}
if (transport != null) {
ClientTransportFactory.releaseTransport(transport, consumerConfig.getDisconnectTimeout());
}
} catch (Exception e) {
LOGGER.errorWithApp(appName, LogCodes.getLog(LogCodes.ERROR_DELETE_PROVIDERS, consumerConfig.getInterfaceId(), providerInfo), e);
}
}
}
use of com.alipay.sofa.rpc.transport.ClientTransport in project sofa-rpc by sofastack.
the class AllConnectConnectionHolder method doReconnect.
/**
* 重连断开和死亡的节点
*/
private void doReconnect() {
String interfaceId = consumerConfig.getInterfaceId();
String appName = consumerConfig.getAppName();
int thisTime = reconnectFlag.incrementAndGet();
// 是否打印error,每6次打印一次
boolean print = thisTime % 6 == 0;
boolean isAliveEmptyFirst = isAvailableEmpty();
// 检查可用连接 todo subHealth
for (Map.Entry<ProviderInfo, ClientTransport> alive : aliveConnections.entrySet()) {
ClientTransport connection = alive.getValue();
if (connection != null && !connection.isAvailable()) {
aliveToRetry(alive.getKey(), connection);
}
}
for (Map.Entry<ProviderInfo, ClientTransport> entry : getRetryConnections().entrySet()) {
ProviderInfo providerInfo = entry.getKey();
int providerPeriodCoefficient = CommonUtils.parseNum((Integer) providerInfo.getDynamicAttr(ProviderInfoAttrs.ATTR_RC_PERIOD_COEFFICIENT), 1);
if (thisTime % providerPeriodCoefficient != 0) {
// 如果命中重连周期,则进行重连
continue;
}
ClientTransport transport = entry.getValue();
if (LOGGER.isDebugEnabled(appName)) {
LOGGER.debugWithApp(appName, "Retry connect to {} provider:{} ...", interfaceId, providerInfo);
}
try {
transport.connect();
if (doubleCheck(interfaceId, providerInfo, transport)) {
providerInfo.setDynamicAttr(ProviderInfoAttrs.ATTR_RC_PERIOD_COEFFICIENT, 1);
retryToAlive(providerInfo, transport);
}
} catch (Exception e) {
if (print) {
if (LOGGER.isWarnEnabled(appName)) {
LOGGER.warnWithApp(appName, "Retry connect to {} provider:{} error ! The exception is " + e.getMessage(), interfaceId, providerInfo);
}
} else {
if (LOGGER.isDebugEnabled(appName)) {
LOGGER.debugWithApp(appName, "Retry connect to {} provider:{} error ! The exception is " + e.getMessage(), interfaceId, providerInfo);
}
}
}
}
if (isAliveEmptyFirst && !isAvailableEmpty()) {
// 原来空,变成不空
notifyStateChangeToAvailable();
}
}
Aggregations