Search in sources :

Example 16 with RpcInvokeContext

use of com.alipay.sofa.rpc.context.RpcInvokeContext 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 17 with RpcInvokeContext

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

the class AbstractInvokeCallback method pickupBaggage.

protected void pickupBaggage(SofaResponse response) {
    if (RpcInvokeContext.isBaggageEnable()) {
        RpcInvokeContext old = null;
        RpcInvokeContext newContext = null;
        if (context != null) {
            old = (RpcInvokeContext) context.getAttachment(RpcConstants.HIDDEN_KEY_INVOKE_CONTEXT);
        }
        if (old == null) {
            newContext = RpcInvokeContext.getContext();
        } else {
            RpcInvokeContext.setContext(old);
            newContext = RpcInvokeContext.getContext();
        }
        BaggageResolver.pickupFromResponse(newContext, response);
        if (old != null) {
            old.getAllResponseBaggage().putAll(newContext.getAllResponseBaggage());
            old.getAllRequestBaggage().putAll(newContext.getAllRequestBaggage());
        }
    }
}
Also used : RpcInvokeContext(com.alipay.sofa.rpc.context.RpcInvokeContext)

Example 18 with RpcInvokeContext

use of com.alipay.sofa.rpc.context.RpcInvokeContext 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 19 with RpcInvokeContext

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

the class TripleClientTransport method syncSend.

@Override
public SofaResponse syncSend(SofaRequest request, int timeout) throws SofaRpcException {
    SofaResponse sofaResponse = null;
    SofaRpcException throwable = null;
    try {
        RpcInternalContext context = RpcInternalContext.getContext();
        beforeSend(context, request);
        RpcInvokeContext invokeContext = RpcInvokeContext.getContext();
        invokeContext.put(TripleContants.SOFA_REQUEST_KEY, request);
        invokeContext.put(TripleContants.SOFA_CONSUMER_CONFIG_KEY, transportConfig.getConsumerConfig());
        sofaResponse = tripleClientInvoker.invoke(request, timeout);
        return sofaResponse;
    } catch (Exception e) {
        throwable = convertToRpcException(e);
        throw throwable;
    } finally {
        if (EventBus.isEnable(ClientSyncReceiveEvent.class)) {
            EventBus.post(new ClientSyncReceiveEvent(transportConfig.getConsumerConfig(), transportConfig.getProviderInfo(), request, sofaResponse, throwable));
        }
    }
}
Also used : 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) StatusException(io.grpc.StatusException) SofaTimeOutException(com.alipay.sofa.rpc.core.exception.SofaTimeOutException) SofaRpcException(com.alipay.sofa.rpc.core.exception.SofaRpcException)

Example 20 with RpcInvokeContext

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

the class RpcSofaTracer method serverSend.

@Override
public void serverSend(SofaRequest request, SofaResponse response, Throwable exception) {
    SofaTraceContext sofaTraceContext = SofaTraceContextHolder.getSofaTraceContext();
    SofaTracerSpan serverSpan = sofaTraceContext.pop();
    if (serverSpan == null) {
        return;
    }
    // Record server send event
    serverSpan.log(LogData.SERVER_SEND_EVENT_VALUE);
    RpcInternalContext context = RpcInternalContext.getContext();
    RpcInvokeContext invokeContext = RpcInvokeContext.getContext();
    serverSpan.setTag(RpcSpanTags.RESP_SERIALIZE_TIME, (Number) context.getAttachment(RpcConstants.INTERNAL_KEY_RESP_SERIALIZE_TIME));
    serverSpan.setTag(RpcSpanTags.REQ_DESERIALIZE_TIME, (Number) context.getAttachment(RpcConstants.INTERNAL_KEY_REQ_DESERIALIZE_TIME));
    serverSpan.setTag(RpcSpanTags.RESP_SIZE, (Number) context.getAttachment(RpcConstants.INTERNAL_KEY_RESP_SIZE));
    serverSpan.setTag(RpcSpanTags.REQ_SIZE, (Number) context.getAttachment(RpcConstants.INTERNAL_KEY_REQ_SIZE));
    // 当前线程名
    serverSpan.setTag(RpcSpanTags.CURRENT_THREAD_NAME, Thread.currentThread().getName());
    serverSpan.setTag(RpcSpanTags.SERVER_PHASE_TIME_COST, generateServerPhaseTimeCostSpan(invokeContext));
    serverSpan.setTag(RpcSpanTags.SERVER_SPECIAL_TIME_MARK, generateServerSpecialTimeMark(invokeContext));
    Throwable throwableShow = exception;
    String tracerErrorCode = StringUtils.EMPTY;
    String errorSourceApp = StringUtils.EMPTY;
    String resultCode = StringUtils.EMPTY;
    if (throwableShow != null) {
        // 当前即服务端应用
        errorSourceApp = serverSpan.getTagsWithStr().get(RpcSpanTags.LOCAL_APP);
        // 结果码(00=成功/01=业务异常/02=RPC逻辑错误)
        // 不会业务异常
        resultCode = TracerResultCode.RPC_RESULT_RPC_FAILED;
        tracerErrorCode = TracerResultCode.RPC_ERROR_TYPE_UNKNOWN_ERROR;
    } else if (response != null) {
        // 判断是否是业务异常
        if (response.isError()) {
            errorSourceApp = serverSpan.getTagsWithStr().get(RpcSpanTags.LOCAL_APP);
            resultCode = TracerResultCode.RPC_RESULT_RPC_FAILED;
            tracerErrorCode = TracerResultCode.RPC_ERROR_TYPE_UNKNOWN_ERROR;
            // 改变打印的 throwable
            throwableShow = new SofaRpcException(RpcErrorType.SERVER_UNDECLARED_ERROR, response.getErrorMsg());
        } else {
            Object ret = response.getAppResponse();
            if (ret instanceof Throwable) {
                throwableShow = (Throwable) ret;
                errorSourceApp = serverSpan.getTagsWithStr().get(RpcSpanTags.LOCAL_APP);
                // 业务异常
                resultCode = TracerResultCode.RPC_RESULT_BIZ_FAILED;
                tracerErrorCode = TracerResultCode.RPC_RESULT_BIZ_FAILED;
            } else {
                resultCode = TracerResultCode.RPC_RESULT_SUCCESS;
            }
        }
    }
    if (throwableShow != null) {
        // 打印错误
        // result code
        Map<String, String> errorContext = new HashMap<String, String>();
        // 记录的上下文信息
        this.generateServerErrorContext(errorContext, request, serverSpan);
        // report
        serverSpan.reportError(tracerErrorCode, errorContext, throwableShow, errorSourceApp, ERROR_SOURCE);
    }
    // 结果码(00=成功/01=业务异常/02=RPC逻辑错误)
    serverSpan.setTag(RpcSpanTags.RESULT_CODE, resultCode);
    serverSpan.finish();
}
Also used : SofaTracerSpan(com.alipay.common.tracer.core.span.SofaTracerSpan) RpcInvokeContext(com.alipay.sofa.rpc.context.RpcInvokeContext) SofaTraceContext(com.alipay.common.tracer.core.context.trace.SofaTraceContext) HashMap(java.util.HashMap) RpcInternalContext(com.alipay.sofa.rpc.context.RpcInternalContext) SofaRpcException(com.alipay.sofa.rpc.core.exception.SofaRpcException)

Aggregations

RpcInvokeContext (com.alipay.sofa.rpc.context.RpcInvokeContext)37 SofaRpcException (com.alipay.sofa.rpc.core.exception.SofaRpcException)12 RequestBase (com.alipay.sofa.rpc.core.request.RequestBase)10 ConsumerConfig (com.alipay.sofa.rpc.config.ConsumerConfig)7 ProviderConfig (com.alipay.sofa.rpc.config.ProviderConfig)7 RpcInternalContext (com.alipay.sofa.rpc.context.RpcInternalContext)7 ApplicationConfig (com.alipay.sofa.rpc.config.ApplicationConfig)6 ServerConfig (com.alipay.sofa.rpc.config.ServerConfig)6 SofaResponseCallback (com.alipay.sofa.rpc.core.invoke.SofaResponseCallback)6 CountDownLatch (java.util.concurrent.CountDownLatch)6 BoltSendableResponseCallback (com.alipay.sofa.rpc.message.bolt.BoltSendableResponseCallback)5 EchoResponse (com.alipay.sofa.rpc.server.bolt.pb.EchoResponse)5 MethodConfig (com.alipay.sofa.rpc.config.MethodConfig)4 Future (java.util.concurrent.Future)4 SofaTraceContext (com.alipay.common.tracer.core.context.trace.SofaTraceContext)3 SofaTracerSpan (com.alipay.common.tracer.core.span.SofaTracerSpan)3 HashMap (java.util.HashMap)3 SofaResponseFuture (com.alipay.sofa.rpc.api.future.SofaResponseFuture)2 SofaTimeOutException (com.alipay.sofa.rpc.core.exception.SofaTimeOutException)2 SofaResponse (com.alipay.sofa.rpc.core.response.SofaResponse)2