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