Search in sources :

Example 6 with RpcInternalContext

use of com.alipay.sofa.rpc.context.RpcInternalContext in project sofa-rpc by sofastack.

the class RpcServiceContextFilter method invoke.

@Override
public SofaResponse invoke(FilterInvoker invoker, SofaRequest request) throws SofaRpcException {
    RpcServiceContext serviceCtx = new RpcServiceContext();
    RpcInternalContext internalCtx = RpcInternalContext.getContext();
    serviceCtx.setServiceName(request.getTargetServiceUniqueName());
    serviceCtx.setMethodName(request.getMethodName());
    serviceCtx.setTraceId((String) internalCtx.getAttachment(RpcConstants.INTERNAL_KEY_TRACE_ID));
    serviceCtx.setRpcId((String) internalCtx.getAttachment(RpcConstants.INTERNAL_KEY_SPAN_ID));
    serviceCtx.setCallerAppName((String) request.getRequestProp(RemotingConstants.HEAD_APP_NAME));
    serviceCtx.setCallerUrl(internalCtx.getRemoteHostName());
    RpcInvokeContext.getContext().put(RemotingConstants.INVOKE_CTX_RPC_SER_CTX, serviceCtx);
    return invoker.invoke(request);
}
Also used : RpcInternalContext(com.alipay.sofa.rpc.context.RpcInternalContext) RpcServiceContext(com.alipay.sofa.rpc.api.context.RpcServiceContext)

Example 7 with RpcInternalContext

use of com.alipay.sofa.rpc.context.RpcInternalContext in project sofa-rpc by sofastack.

the class BoltSendableResponseCallback method init.

/**
 * 初始化数据
 */
protected void init() {
    // 从ThreadLocal取出当前长连接,request等信息设置进去,需要接到请求时提前设置到ThreadLocal里
    RpcInternalContext context = RpcInternalContext.getContext();
    asyncContext = (AsyncContext) context.getAttachment(RpcConstants.HIDDEN_KEY_ASYNC_CONTEXT);
    request = (SofaRequest) context.getAttachment(RpcConstants.HIDDEN_KEY_ASYNC_REQUEST);
}
Also used : RpcInternalContext(com.alipay.sofa.rpc.context.RpcInternalContext)

Example 8 with RpcInternalContext

use of com.alipay.sofa.rpc.context.RpcInternalContext in project sofa-rpc by sofastack.

the class BoltServerProcessor method handleRequest.

@Override
public void handleRequest(BizContext bizCtx, AsyncContext asyncCtx, SofaRequest request) {
    // RPC内置上下文
    RpcInternalContext context = RpcInternalContext.getContext();
    context.setProviderSide(true);
    String appName = request.getTargetAppName();
    if (appName == null) {
        // 默认全局appName
        appName = (String) RpcRuntimeContext.get(RpcRuntimeContext.KEY_APPNAME);
    }
    // 是否链路异步化中
    boolean isAsyncChain = false;
    try {
        // 这个 try-finally 为了保证Context一定被清理
        // 统计值加1
        processingCount.incrementAndGet();
        // 远程地址
        context.setRemoteAddress(bizCtx.getRemoteHost(), bizCtx.getRemotePort());
        // 远程返回的通道
        context.setAttachment(RpcConstants.HIDDEN_KEY_ASYNC_CONTEXT, asyncCtx);
        InvokeContext boltInvokeCtx = bizCtx.getInvokeContext();
        if (RpcInternalContext.isAttachmentEnable()) {
            if (boltInvokeCtx != null) {
                // rpc线程池等待时间 Long
                putToContextIfNotNull(boltInvokeCtx, InvokeContext.BOLT_PROCESS_WAIT_TIME, context, RpcConstants.INTERNAL_KEY_PROCESS_WAIT_TIME);
            }
        }
        putToContext(boltInvokeCtx);
        if (EventBus.isEnable(ServerReceiveEvent.class)) {
            EventBus.post(new ServerReceiveEvent(request));
        }
        // 开始处理
        // 响应,用于返回
        SofaResponse response = null;
        // 异常,用于记录
        Throwable throwable = null;
        ProviderConfig providerConfig = null;
        String serviceName = request.getTargetServiceUniqueName();
        try {
            // 这个try-catch 保证一定有Response
            invoke: {
                if (!boltServer.isStarted()) {
                    // 服务端已关闭
                    throwable = new SofaRpcException(RpcErrorType.SERVER_CLOSED, LogCodes.getLog(LogCodes.WARN_PROVIDER_STOPPED, SystemInfo.getLocalHost() + ":" + boltServer.serverConfig.getPort()));
                    response = MessageBuilder.buildSofaErrorResponse(throwable.getMessage());
                    break invoke;
                }
                if (bizCtx.isRequestTimeout()) {
                    // 加上丢弃超时的请求的逻辑
                    throwable = clientTimeoutWhenReceiveRequest(appName, serviceName, bizCtx.getRemoteAddress());
                    break invoke;
                }
                // 查找服务
                Invoker invoker = boltServer.findInvoker(serviceName);
                if (invoker == null) {
                    throwable = cannotFoundService(appName, serviceName);
                    response = MessageBuilder.buildSofaErrorResponse(throwable.getMessage());
                    break invoke;
                }
                if (invoker instanceof ProviderProxyInvoker) {
                    providerConfig = ((ProviderProxyInvoker) invoker).getProviderConfig();
                    // 找到服务后,打印服务的appName
                    appName = providerConfig != null ? providerConfig.getAppName() : null;
                }
                // 查找方法
                String methodName = request.getMethodName();
                Method serviceMethod = ReflectCache.getOverloadMethodCache(serviceName, methodName, request.getMethodArgSigs());
                if (serviceMethod == null) {
                    throwable = cannotFoundServiceMethod(appName, methodName, serviceName);
                    response = MessageBuilder.buildSofaErrorResponse(throwable.getMessage());
                    break invoke;
                } else {
                    request.setMethod(serviceMethod);
                }
                // 真正调用
                response = doInvoke(serviceName, invoker, request);
                if (bizCtx.isRequestTimeout()) {
                    // 加上丢弃超时的响应的逻辑
                    throwable = clientTimeoutWhenSendResponse(appName, serviceName, bizCtx.getRemoteAddress());
                    break invoke;
                }
            }
        } catch (Exception e) {
            // 服务端异常,不管是啥异常
            LOGGER.errorWithApp(appName, "Server Processor Error!", e);
            throwable = e;
            response = MessageBuilder.buildSofaErrorResponse(e.getMessage());
        }
        // Response不为空,代表需要返回给客户端
        if (response != null) {
            RpcInvokeContext invokeContext = RpcInvokeContext.peekContext();
            isAsyncChain = CommonUtils.isTrue(invokeContext != null ? (Boolean) invokeContext.remove(RemotingConstants.INVOKE_CTX_IS_ASYNC_CHAIN) : null);
            // 如果是服务端异步代理模式,特殊处理,因为该模式是在业务代码自主异步返回的
            if (!isAsyncChain) {
                // 其它正常请求
                try {
                    // 这个try-catch 保证一定要记录tracer
                    asyncCtx.sendResponse(response);
                } finally {
                    if (EventBus.isEnable(ServerSendEvent.class)) {
                        EventBus.post(new ServerSendEvent(request, response, throwable));
                    }
                }
            }
        }
    } catch (Throwable e) {
        // 可能有返回时的异常
        if (LOGGER.isErrorEnabled(appName)) {
            LOGGER.errorWithApp(appName, e.getMessage(), e);
        }
    } finally {
        processingCount.decrementAndGet();
        if (!isAsyncChain) {
            if (EventBus.isEnable(ServerEndHandleEvent.class)) {
                EventBus.post(new ServerEndHandleEvent());
            }
        }
        RpcInvokeContext.removeContext();
        RpcInternalContext.removeAllContext();
    }
}
Also used : InvokeContext(com.alipay.remoting.InvokeContext) RpcInvokeContext(com.alipay.sofa.rpc.context.RpcInvokeContext) RpcInvokeContext(com.alipay.sofa.rpc.context.RpcInvokeContext) ServerSendEvent(com.alipay.sofa.rpc.event.ServerSendEvent) ProviderConfig(com.alipay.sofa.rpc.config.ProviderConfig) RpcInternalContext(com.alipay.sofa.rpc.context.RpcInternalContext) ServerEndHandleEvent(com.alipay.sofa.rpc.event.ServerEndHandleEvent) Method(java.lang.reflect.Method) SofaRpcException(com.alipay.sofa.rpc.core.exception.SofaRpcException) SofaRpcException(com.alipay.sofa.rpc.core.exception.SofaRpcException) ProviderProxyInvoker(com.alipay.sofa.rpc.server.ProviderProxyInvoker) Invoker(com.alipay.sofa.rpc.invoke.Invoker) ProviderProxyInvoker(com.alipay.sofa.rpc.server.ProviderProxyInvoker) ServerReceiveEvent(com.alipay.sofa.rpc.event.ServerReceiveEvent) SofaResponse(com.alipay.sofa.rpc.core.response.SofaResponse)

Example 9 with RpcInternalContext

use of com.alipay.sofa.rpc.context.RpcInternalContext in project sofa-rpc by sofastack.

the class BoltClientTransport method syncSend.

@Override
public SofaResponse syncSend(SofaRequest request, int timeout) throws SofaRpcException {
    checkConnection();
    RpcInternalContext context = RpcInternalContext.getContext();
    InvokeContext boltInvokeContext = createInvokeContext(request);
    SofaResponse response = null;
    SofaRpcException throwable = null;
    try {
        beforeSend(context, request);
        response = doInvokeSync(request, boltInvokeContext, timeout);
        return response;
    } catch (Exception e) {
        // 其它异常
        throwable = convertToRpcException(e);
        throw throwable;
    } finally {
        afterSend(context, boltInvokeContext, request);
        if (EventBus.isEnable(ClientSyncReceiveEvent.class)) {
            EventBus.post(new ClientSyncReceiveEvent(transportConfig.getConsumerConfig(), transportConfig.getProviderInfo(), request, response, throwable));
        }
    }
}
Also used : InvokeContext(com.alipay.remoting.InvokeContext) RpcInvokeContext(com.alipay.sofa.rpc.context.RpcInvokeContext) RpcInternalContext(com.alipay.sofa.rpc.context.RpcInternalContext) SofaResponse(com.alipay.sofa.rpc.core.response.SofaResponse) ClientSyncReceiveEvent(com.alipay.sofa.rpc.event.ClientSyncReceiveEvent) SofaRpcException(com.alipay.sofa.rpc.core.exception.SofaRpcException) InvokeServerException(com.alipay.remoting.rpc.exception.InvokeServerException) InvokeSendFailedException(com.alipay.remoting.rpc.exception.InvokeSendFailedException) SofaTimeOutException(com.alipay.sofa.rpc.core.exception.SofaTimeOutException) DeserializationException(com.alipay.remoting.exception.DeserializationException) InvokeTimeoutException(com.alipay.remoting.rpc.exception.InvokeTimeoutException) SerializationException(com.alipay.remoting.exception.SerializationException) RemotingException(com.alipay.remoting.exception.RemotingException) ConnectionClosedException(com.alipay.remoting.exception.ConnectionClosedException) InvokeServerBusyException(com.alipay.remoting.rpc.exception.InvokeServerBusyException) SofaRpcException(com.alipay.sofa.rpc.core.exception.SofaRpcException) SofaRpcRuntimeException(com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException)

Example 10 with RpcInternalContext

use of com.alipay.sofa.rpc.context.RpcInternalContext 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)

Aggregations

RpcInternalContext (com.alipay.sofa.rpc.context.RpcInternalContext)52 SofaRpcException (com.alipay.sofa.rpc.core.exception.SofaRpcException)15 SofaTraceContext (com.alipay.common.tracer.core.context.trace.SofaTraceContext)13 SofaTracerSpan (com.alipay.common.tracer.core.span.SofaTracerSpan)12 SofaResponse (com.alipay.sofa.rpc.core.response.SofaResponse)12 RpcInvokeContext (com.alipay.sofa.rpc.context.RpcInvokeContext)10 SofaTimeOutException (com.alipay.sofa.rpc.core.exception.SofaTimeOutException)6 ProviderInfo (com.alipay.sofa.rpc.client.ProviderInfo)5 HashMap (java.util.HashMap)5 InvokeContext (com.alipay.remoting.InvokeContext)4 SofaRpcRuntimeException (com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException)4 SofaRequest (com.alipay.sofa.rpc.core.request.SofaRequest)4 ClientSyncReceiveEvent (com.alipay.sofa.rpc.event.ClientSyncReceiveEvent)4 Test (org.junit.Test)4 SofaTracerSpanContext (com.alipay.common.tracer.core.context.span.SofaTracerSpanContext)3 ConnectionClosedException (com.alipay.remoting.exception.ConnectionClosedException)3 DeserializationException (com.alipay.remoting.exception.DeserializationException)3 RemotingException (com.alipay.remoting.exception.RemotingException)3 SerializationException (com.alipay.remoting.exception.SerializationException)3 InvokeSendFailedException (com.alipay.remoting.rpc.exception.InvokeSendFailedException)3