sofa server端处理client端请求流程

背景:以sofa-rpc-master:5.6.0-SNAPSHOT版本为例,下载 代码,以

com.alipay.sofa.rpc.quickstart.QuickStartClient 和
com.alipay.sofa.rpc.quickstart.QuickStartServer 2个类运行作为举例说明

先debug运行QuickStartServer类的main方法,再运行QuickStartClient的main方法,然后。。。开始分析:

1.运行QuickStartClient之后,首先server端会在com.alipay.remoting.rpc.RpcHandler类中的channelRead(ChannelHandlerContext ctx, Object msg)方法中获取到client端的请求,如下所示:
server端获取client请求
2.进入handleCommand(RemotingContext ctx, Object msg)方法实现,走到 com.alipay.remoting.rpc.protocol.RpcCommandHandler#handle(...)中。接着进入到
rpc handler处理器
3.进入com.alipay.remoting.rpc.protocol.RpcRequestProcessor#process(...)中

@Override
    public void process(RemotingContext ctx, RpcRequestCommand cmd, ExecutorService defaultExecutor)
                                                                                                    throws Exception {
        /*
         * 序列化类名称:requestClass=com.alipay.sofa.rpc.core.request.SofaRequest
         */                                                                                             
        if (!deserializeRequestCommand(ctx, cmd, RpcDeserializeLevel.DESERIALIZE_CLAZZ)) {
            return;
        }
        UserProcessor userProcessor = ctx.getUserProcessor(cmd.getRequestClass());
        if (userProcessor == null) {
            String errMsg = "No user processor found for request: " + cmd.getRequestClass();
            logger.error(errMsg);
            sendResponseIfNecessary(ctx, cmd.getType(), this.getCommandFactory()
                .createExceptionResponse(cmd.getId(), errMsg));
            return;// must end process
        }

        // set timeout check state from user's processor
        ctx.setTimeoutDiscard(userProcessor.timeoutDiscard());

        ...
        ...

        Executor executor = ...;
        
		// 代码走到这里,下面在ProcessTask中run打断点
        // use the final executor dispatch process task
        executor.execute(new ProcessTask(ctx, cmd));
    }

task执行
4.开始处理:

@Override
    public void doProcess(final RemotingContext ctx, RpcRequestCommand cmd) throws Exception {
        long currentTimestamp = System.currentTimeMillis();

        preProcessRemotingContext(ctx, cmd, currentTimestamp);
        if (ctx.isTimeoutDiscard() && ctx.isRequestTimeout()) {
            timeoutLog(cmd, currentTimestamp, ctx);// do some log
            return;// then, discard this request
        }
        debugLog(ctx, cmd, currentTimestamp);
        // 看这里,1.序列化类;
        // 2. 序列化头部:requestHeader值( requestCommand.setRequestHeader(headerMap);)
        // 3. 序列化内容
        // decode request all
        if (!deserializeRequestCommand(ctx, cmd, RpcDeserializeLevel.DESERIALIZE_ALL)) {
            return;
        }
        // 调度到用户处理器中处理
        dispatchToUserProcessor(ctx, cmd);
    }

序列化成功后的显示:
序列化成功之后数据显示
5. 进入到 com.alipay.sofa.rpc.server.bolt.BoltServerProcessor#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一定被清理
            processingCount.incrementAndGet(); // 统计值加1

            context.setRemoteAddress(bizCtx.getRemoteHost(), bizCtx.getRemotePort()); // 远程地址
            context.setAttachment(RpcConstants.HIDDEN_KEY_ASYNC_CONTEXT, asyncCtx); // 远程返回的通道

            if (RpcInternalContext.isAttachmentEnable()) {
                InvokeContext boltInvokeCtx = bizCtx.getInvokeContext();
                if (boltInvokeCtx != null) {
                    putToContextIfNotNull(boltInvokeCtx, InvokeContext.BOLT_PROCESS_WAIT_TIME,
                        context, RpcConstants.INTERNAL_KEY_PROCESS_WAIT_TIME); // rpc线程池等待时间 Long
                }
            }
            // 事件总线数据模型:发送 server receive event 事件通知
            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;
                    }
                    // 查找服务【server export服务时创建好的Invoker】
                    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();
        }
    }

6.进入上面的 com.alipay.sofa.rpc.server.bolt.BoltServerProcessor#doInvoke(...)
doInvoke
进入拦截器调用链:
filterChain
来回这样调着玩
最后真正的调用代码在com.alipay.sofa.rpc.filter.ProviderInvoker#invoke(...)

@Override
    public SofaResponse invoke(SofaRequest request) throws SofaRpcException {

        SofaResponse sofaResponse = new SofaResponse();
        long startTime = RpcRuntimeContext.now();
        try {
            // 反射 真正调用业务代码
            Method method = request.getMethod();
            if (method == null) {
                throw new SofaRpcException(RpcErrorType.SERVER_FILTER, "Need decode method first!");
            }
            Object result = method.invoke(providerConfig.getRef(), request.getMethodArgs());

            sofaResponse.setAppResponse(result);
        } catch (IllegalArgumentException e) { // 非法参数,可能是实现类和接口类不对应) 
            sofaResponse.setErrorMsg(e.getMessage());
        } catch (IllegalAccessException e) { // 如果此 Method 对象强制执行 Java 语言访问控制,并且底层方法是不可访问的
            sofaResponse.setErrorMsg(e.getMessage());
        } catch (InvocationTargetException e) { // 业务代码抛出异常
            sofaResponse.setAppResponse(e.getCause());
        } finally {
            if (RpcInternalContext.isAttachmentEnable()) {
                long endTime = RpcRuntimeContext.now();
           RpcInternalContext.getContext().setAttachment(RpcConstants.INTERNAL_KEY_IMPL_ELAPSE,
                    endTime - startTime);
            }
        }

        return sofaResponse;
    }

这样就进到了example中,真正的业务方法调用了:
业务方法调用

7.最后回到com.alipay.sofa.rpc.server.bolt.BoltServerProcessor#handleRequest(...)
真正调用后返回处理
如上所示:server处理完成后,发送响应数据给client,并在事件总线上发送 server send event 事件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值