5.源码分析---SOFARPC调用服务 (2)

我们直接进入到doInvoke方法中,看是如何生成response对象的。

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

这里主要是为了获取缓存里面加载被暴露服务的类加载器,这样可以防止不同的类加载器之间一个类被加载多次。

然后调用过滤器链,最后进入到ProviderInvoker中

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) { // 业务代码抛出异常 cutCause(e.getCause()); sofaResponse.setAppResponse(e.getCause()); } finally { if (RpcInternalContext.isAttachmentEnable()) { long endTime = RpcRuntimeContext.now(); RpcInternalContext.getContext().setAttachment(RpcConstants.INTERNAL_KEY_IMPL_ELAPSE, endTime - startTime); } } return sofaResponse; }

到最后我们发现,服务端会通过反射调用被暴露服务的方法,封装成Response类返回。

我们再次回到BoltServerProcessor#handleRequest方法中

....//忽略其他内容 // 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)); } } } } ....//忽略其他内容

最后我们的response实例会使用netty传给客户端。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwjsp.html