Exemple #1
0
 public CobCommonClientProxy(ICobRequestResolver requestResolver, IServiceRegistration serviceDiscovery, CobServiceDescription desc, ILoggerFactory loggerFactory)
 {
     _desc            = desc;
     _requestResolver = requestResolver;
     _loggerFactory   = loggerFactory;
     _selector        = new DefaultServiceSelector(serviceDiscovery, _desc.ServiceName, loggerFactory?.CreateLogger <DefaultServiceSelector>());
 }
Exemple #2
0
        //public object Execute(Type returnType, CobServiceDescription desc, Func<ServiceInfo, object> action)
        //{
        //    var realType = TaskHelper.GetUnderlyingType(returnType, out bool isTask);

        //    var task = Task.Factory.StartNew(() => {
        //        Func<ServiceInfo, object> method = null;
        //        if (isTask)
        //        {
        //            method = s => TaskHelper.GetResult((Task)action(s));//todo:使用token改为异步等待
        //        }
        //        else
        //        {
        //            method = action;
        //        }

        //        return ExecuteSync(desc, method);
        //    });

        //    if (isTask)
        //        return TaskHelper.ConvertToGeneric(realType, task);

        //    return task.ConfigureAwait(false).GetAwaiter().GetResult();
        //}

        ////同步执行
        //private object ExecuteSync(CobServiceDescription desc, Func<ServiceInfo, object> action)
        //{
        //    var sw = new Stopwatch();
        //    Exception error = null;
        //    object result = null;

        //    //重试
        //    ServiceInfo service = null;
        //    var runTimes = 0;
        //    while (true)
        //    {
        //        service = _selector.GetOne();
        //        if (service != null)
        //        {
        //            runTimes++;
        //            sw.Restart();

        //            try
        //            {
        //                result = action(service);
        //            }
        //            catch (Exception ex)
        //            {
        //                if (desc.RetryTimes > 0 && runTimes < desc.RetryTimes && desc.RetryExceptionTypes != null && desc.RetryExceptionTypes.Length > 0 && desc.RetryExceptionTypes.Contains(ex.GetBaseException().GetType()))
        //                {
        //                    //tofo:等待一段时间后再重试,还要避免出现大量重试请求
        //                    continue;
        //                }

        //                error = ex.GetBaseException();
        //            }

        //            break;
        //        }

        //        _logger.LogError("can not get available service for:{0}", desc.ServiceName);

        //        //todo:无服务可用,降级?
        //        throw new Exception("service select failover");
        //    }

        //    sw.Stop();
        //    SetState(service, sw, error);

        //    return result;
        //}

        //private void SetState(ServiceInfo target, Stopwatch sw, Exception error = null)
        //{
        //    //todo:熔断?
        ////    if (error != null)
        ////    {
        ////        _selector.SetServiceFailed(target);
        ////    }

        //    //todo:设置时间 or 异常
        //    _selector.SetServiceResponseTime(target, sw.Elapsed);
        //}

        #endregion


        #region 都转为Task执行

        /// <summary>
        /// 包状代理,添加重试、超时等机制
        /// </summary>
        public object Execute(Type returnType, CobServiceDescription desc, Func <ServiceInfo, Task <object> > action, MethodInfo method = null, Dictionary <string, object> parameters = null)
        {
            Func <ServiceInfo, Task> asyncAction = action;

            //wrap timeout task
            if (desc.Timeout.TotalSeconds > 0)
            {
                asyncAction = s => {
                    var taskTimeout  = Task.Delay(desc.Timeout.TotalSeconds > 0 ? desc.Timeout : TimeSpan.FromSeconds(_requestOptions.DefaultTimeout));//不为空且大于0的超时时间
                    var taskOriginal = action(s);

                    var taskWrapped = Task.WhenAny(taskOriginal, taskTimeout).ContinueWith(t =>
                    {
                        if (t.Result == taskTimeout && taskOriginal.Status < TaskStatus.Running)
                        {
                            throw new TimeoutException();
                        }

                        var result = taskOriginal.Result;

                        if (desc.Filters != null)
                        {
                            desc.Filters.ForEach(f => f.OnAfterResponse(method, result));
                        }

                        return(result);
                    });

                    return(taskWrapped);
                };
            }

            return(ExecuteAsync(returnType, desc, asyncAction, method, parameters));
        }
Exemple #3
0
        private object ExecuteAsync(Type returnType, CobServiceDescription desc, Func <ServiceInfo, Task> action, MethodInfo method = null, Dictionary <string, object> parameters = null)
        {
            var retry = new ServiceTaskRetryContainer(_loggerFactory, _selector, desc.RetryTimes, desc.RetryExceptionTypes);

            var taskResult = retry.RunForResult(action).ContinueWith(t => {
                foreach (var item in t.Result)
                {
                    if (item.Service != null)
                    {
                        //set exception,超过阈值后熔断
                        if (item.Exception != null)
                        {
                            _selector.MarkServiceFailed(item.Service, false);
                        }
                        else if (item.Duration.HasValue)
                        {
                            _selector.MarkServiceHealthy(item.Service, item.Duration.Value);
                        }
                    }
                }

                if (t.Result.All(i => i.Exception != null))
                {
                    var ex = t.Result.First().Exception.GetInnerException();

                    //failover
                    //降级 fallback
                    if (desc.FallbackHandler != null)
                    {
                        _logger.LogInformation("使用缺省值处理类返回");
                        var handler = _fallbackHandlers.GetOrAdd(desc.FallbackHandler, k => Activator.CreateInstance(k) as ICobFallbackHandler);

                        return(handler?.GetValue(new CobFallbackHandlerContext {
                            ReturnType = returnType, Exception = ex, ServiceName = desc.ServiceName, Path = desc.Path, Method = method, Parameters = parameters
                        }));
                    }
                    else if (!string.IsNullOrWhiteSpace(desc.FallbackValue))
                    {
                        _logger.LogInformation("使用缺省值返回");
                        return(_scripts.GetOrAdd(desc.FallbackValue, k => CSharpScript.EvaluateAsync(k).ConfigureAwait(false).GetAwaiter().GetResult()));//todo:处理是否为Task
                    }

                    //没有缺省值时,抛出异常
                    throw ex;
                }

                return(t.Result.FirstOrDefault(i => i.Exception == null)?.Result);
            });

            var realType = TaskHelper.GetUnderlyingType(returnType, out bool isTask);

            //匹配返回的类型
            if (isTask)
            {
                return(TaskHelper.ConvertToGeneric(realType, taskResult));
            }
            else if (realType != null)
            {
                return(taskResult.ConfigureAwait(false).GetAwaiter().GetResult());//todo:在beforeRequest时抛出异常,这里就会一直等待?
            }

            return(null);//todo:change to default(T) ??
        }
Exemple #4
0
 public ICobClientProxy GetProxy(CobServiceDescription desc)//指定post
 {
     return(new CobCommonClientProxy(_requestResolver, _serviceDiscovery, desc, _loggerFactory, _requestOptions));
 }