SOFA RPC服务端处理请求流程

SOFARPC 服务端处理请求的详细流程包含多个关键步骤,以下将基于你提供的代码片段,详细介绍服务端处理请求的完整过程:

1. 请求接收

当客户端发起请求时,服务端需要接收该请求。以 BoltServerProcessor 为例,它继承自 AsyncUserProcessor<SofaRequest>,用于处理接收到的 SofaRequest

public class BoltServerProcessor extends AsyncUserProcessor<SofaRequest> {
    @Override
    public void handleRequest(BizContext bizCtx, AsyncContext asyncCtx, SofaRequest request) {
        // RPC内置上下文
        RpcInternalContext context = RpcInternalContext.getContext();
        context.setProviderSide(true);
        // 其他处理逻辑...
    }
}

handleRequest 方法中,首先获取 RpcInternalContext 并标记为服务端侧,然后设置远程地址和异步上下文等信息。

2. 事件发布

服务端接收到请求后,会触发 ServerReceiveEvent 事件,用于通知其他组件请求已到达。

if (EventBus.isEnable(ServerReceiveEvent.class)) {
    EventBus.post(new ServerReceiveEvent(request));
}

3. 服务查找

服务端需要根据请求中的服务名查找对应的 Invoker

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;
    }
    // 其他处理逻辑...
}

如果服务端未启动、请求超时或未找到对应的 Invoker,会抛出相应的异常并构建错误响应。

4. 方法查找

找到服务对应的 Invoker 后,需要根据请求中的方法名查找具体的方法。

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);
}

如果未找到对应的方法,会抛出异常并构建错误响应。

5. 实际调用

找到服务和方法后,会调用 Invokerinvoke 方法进行实际的业务处理。

private SofaResponse doInvoke(String serviceName, Invoker invoker, SofaRequest request) throws SofaRpcException {
    // 开始调用,先记下当前的ClassLoader
    ClassLoader rpcCl = Thread.currentThread().getContextClassLoader();
    try {
        // 切换线程的ClassLoader到 服务 自己的ClassLoader
        ClassLoader serviceCl = ReflectCache.getServiceClassLoader(serviceName);
        Thread.currentThread().setContextClassLoader(serviceCl);
        return invoker.invoke(request);
    } finally {
        Thread.currentThread().setContextClassLoader(rpcCl);
    }
}

在调用过程中,会切换线程的 ClassLoader 到服务自己的 ClassLoader,以确保正确加载服务相关的类。

6. 响应处理

实际调用完成后,会得到一个 SofaResponse 对象,服务端需要对该响应进行处理并返回给客户端。

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 { 
            asyncCtx.sendResponse(response);
        } finally {
            if (EventBus.isEnable(ServerSendEvent.class)) {
                EventBus.post(new ServerSendEvent(request, response, throwable));
            }
        }
    }
}

如果响应不为空,会通过 AsyncContext 将响应发送给客户端,并触发 ServerSendEvent 事件。

7. 清理工作

最后,需要进行一些清理工作,如移除上下文信息等。

finally {
    RecordContextResolver.carryWithRequest(bizCtx.getInvokeContext().getRecordContext(), request);
    processingCount.decrementAndGet();
    if (!isAsyncChain) {
        if (EventBus.isEnable(ServerEndHandleEvent.class)) {
            EventBus.post(new ServerEndHandleEvent());
        }
    }
    RpcInvokeContext.removeContext();
    RpcInternalContext.removeAllContext();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值