/// <summary>
 /// 反序列化
 /// </summary>
 /// <param name="input">待序列化消息</param>
 /// <returns>消息响应体</returns>
 protected abstract TProtocol SerializeMessage(MessageResponse input);
        /// <summary>
        /// 请求调用
        /// </summary>
        /// <param name="buffer">已序列化的消息请求</param>
        /// <returns>序列化消息</returns>
        public async Task <TProtocol> InvokeAsync(TProtocol buffer)
        {
            MessageResponse response = new MessageResponse();

            try
            {
                Dictionary <string, object> logs = new Dictionary <string, object>();
                MessageRequest request           = DeserializeMessage(buffer);
                try
                {
                    if (request.ClusterToken != _clusterToken)
                    {
                        throw new IllegalClusterTokenException($"Cluster token({request.ClusterToken}) is illegal.");
                    }

                    MethodReflectionInfo methodInfo = EnsureMethodInfo(request);
                    var    serviceInstance          = _serverStub.GetServiceInstance(request.Service);
                    object result = null;
                    object ret    = methodInfo.Method.Invoke(serviceInstance, request.Args?.ToArray());

                    if (methodInfo.IsAwaitable) //处理异步
                    {
                        dynamic task = (Task)ret;
                        if (methodInfo.ReturnType.IsGenericType)
                        {
                            result = await task.ConfigureAwait(false);
                        }
                        else
                        {
                            await task.ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        result = ret;
                    }

                    response.MessageId  = request.MessageId;
                    response.Data       = result;
                    response.ReturnType = result?.GetType()?.AssemblyQualifiedName;
                    response.Success    = true;
                    return(SerializeMessage(response));
                }
                catch (Exception ex)
                {
                    logs.Add(TextLog.ExceptionKey, ex);
                    throw;
                }
                finally
                {
                    logs.Add(TextLog.MethodNameKey, request?.Method);
                    logs.Add(TextLog.LogTimeKey, DateTime.Now);
                    logs.Add(TextLog.TraceIdKey, request?.TraceContext?.TraceId);
                    logs.Add(nameof(TraceContext.SpanId), request?.TraceContext?.SpanId);
                    if (logs.ContainsKey(TextLog.ExceptionKey))
                    {
                        _logger.WriteErrorLog(logs);
                    }
                    else
                    {
                        _logger.WriteInfoLog(logs);
                    }
                }
            }
            catch (Exception ex)
            {
                response.Message = ex.InnerException != null ? ex.InnerException.Message : ex.Message;
                _logger.WriteErrorLog(ex);
            }
            return(SerializeMessage(response));
        }
Beispiel #3
0
        /// <summary>
        /// 调用入口
        /// </summary>
        /// <param name="binder">请求的绑定对象</param>
        /// <param name="args">参数集合</param>
        /// <param name="result">返回结果</param>
        /// <returns></returns>
        public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
        {
            //处理参数
            MethodReflectionInfo methodInfo = _serviceInfo.EnsureMethodInfo(binder.Name, args, null, binder.CallInfo.ArgumentCount);

            //序列化消息数据
            bool isExisted = _clientStub.TraceChain.GetCurrentTraceContext() != null;
            var  request   = new MessageRequest
            {
                MessageId    = Guid.NewGuid().ToString(),
                TraceContext = isExisted ? _clientStub.TraceChain.GetCurrentTraceContext() : _clientStub.TraceChain.Begin(),
                Service      = _serviceInfo.ServiceType.Name,
                Method       = binder.Name,
                ClusterToken = _clientStub.ClusterToken,
                ArgTypes     = methodInfo.Parameters.Any() ? new List <string>() : null,
                Args         = methodInfo.Parameters.Any() ? new List <object>() : null
            };

            for (int i = 0; i < methodInfo.Parameters.Length; i++)
            {
                request.ArgTypes.Add(methodInfo.Parameters[i].ParameterType.AssemblyQualifiedName); //todo 但继承的子类不在同个程序集的时候无法反射
                request.Args.Add(args[i]);
            }

            TProtocol message = SerializeMessage(request);

            result = null;
            if (_clientStub.EnableServiceDiscovery)
            {
                bool success = InvokeTolerably(request.MessageId, message, out Exception lastException, out object ret);
                if (!success && lastException != null)
                {
                    throw lastException;
                }
                result = ret;
            }
            else
            {
                MessageResponse response = Invoke(request.MessageId, message, _clientStub.EndPoint);
                result = response.Data;
            }

            if (methodInfo.IsAwaitable) //处理异步返回值
            {
                if (methodInfo.ReturnType.IsGenericType)
                {
                    Type    genericParamType = methodInfo.Method.ReturnType.GenericTypeArguments.First();
                    dynamic value            = Utility.ChangeType(result, genericParamType);
                    if (value == null)
                    {
                        result = Utility.GetTaskByType(genericParamType);
                    }
                    else
                    {
                        result = Task.FromResult(value);
                    }
                }
                else
                {
                    result = Task.CompletedTask;
                }
            }

            //完成链路
            if (!isExisted)
            {
                _clientStub.TraceChain.Finish();
            }
            return(true);
        }