Search in sources :

Example 1 with ClientTransport

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();
        }
    }
}
Also used : NamedThreadFactory(com.alipay.sofa.rpc.common.struct.NamedThreadFactory) ClientTransport(com.alipay.sofa.rpc.transport.ClientTransport) CountDownLatch(java.util.concurrent.CountDownLatch) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 2 with ClientTransport

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();
                }
            }
        }
    });
}
Also used : ClientTransportConfig(com.alipay.sofa.rpc.transport.ClientTransportConfig) ClientTransport(com.alipay.sofa.rpc.transport.ClientTransport)

Example 3 with ClientTransport

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));
}
Also used : RpcInvokeContext(com.alipay.sofa.rpc.context.RpcInvokeContext) RpcInternalContext(com.alipay.sofa.rpc.context.RpcInternalContext) ClientTransport(com.alipay.sofa.rpc.transport.ClientTransport)

Example 4 with ClientTransport

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);
        }
    }
}
Also used : ClientTransport(com.alipay.sofa.rpc.transport.ClientTransport)

Example 5 with ClientTransport

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();
    }
}
Also used : ClientTransport(com.alipay.sofa.rpc.transport.ClientTransport) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Aggregations

ClientTransport (com.alipay.sofa.rpc.transport.ClientTransport)8 ClientTransportConfig (com.alipay.sofa.rpc.transport.ClientTransportConfig)3 NamedThreadFactory (com.alipay.sofa.rpc.common.struct.NamedThreadFactory)2 RpcInternalContext (com.alipay.sofa.rpc.context.RpcInternalContext)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 ConcurrentMap (java.util.concurrent.ConcurrentMap)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 ThreadPoolExecutor (java.util.concurrent.ThreadPoolExecutor)2 RpcInvokeContext (com.alipay.sofa.rpc.context.RpcInvokeContext)1 Callable (java.util.concurrent.Callable)1 ExecutorService (java.util.concurrent.ExecutorService)1