예제 #1
0
        /// <summary>
        /// 远程调用。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="parameters">参数字典。</param>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>调用结果。</returns>
        protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId)
        {
            object result  = default(T);
            var    command = await _commandProvider.GetCommand(serviceId);

            RemoteInvokeResultMessage message;

            if (!command.RequestCacheEnabled)
            {
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey);

                if (message == null)
                {
                    var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString());
                    return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey));
                }
            }
            else
            {
                var invocation = GetInvocation(parameters, serviceId, typeof(T));
                await _interceptor.Intercept(invocation);

                message = invocation.ReturnValue is RemoteInvokeResultMessage
                    ? invocation.ReturnValue as RemoteInvokeResultMessage : null;
                result = invocation.ReturnValue;
            }

            if (message != null)
            {
                result = _typeConvertibleService.Convert(message.Result, typeof(T));
            }
            return((T)result);
        }
예제 #2
0
        /// <summary>
        /// 远程调用。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="parameters">参数字典。</param>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>调用结果。</returns>
        protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId)
        {
            object result  = default(T);
            var    vt      = _commandProvider.GetCommand(serviceId);
            var    command = vt.IsCompletedSuccessfully ? vt.Result : await vt;
            RemoteInvokeResultMessage message = null;
            var         decodeJOject          = typeof(T) == TypeHelper.ObjectType;
            IInvocation invocation            = null;
            var         existsInterceptor     = _interceptors.Any();
            var         serviceRoute          = await _serviceRouteProvider.Locate(serviceId);

            if ((serviceRoute == null || !serviceRoute.ServiceDescriptor.ExistIntercept()) || decodeJOject)
            {
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey,
                                                                       decodeJOject);

                if (message == null)
                {
                    if (command.FallBackName != null &&
                        _serviceProvider.IsRegistered <IFallbackInvoker>(command.FallBackName) &&
                        command.Strategy == StrategyType.FallBack)
                    {
                        var invoker = _serviceProvider.GetInstances <IFallbackInvoker>(command.FallBackName);
                        return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey));
                    }
                    else
                    {
                        var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString());
                        return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey,
                                                        typeof(T) == TypeHelper.ObjectType));
                    }
                }
            }
            else
            {
                invocation = invocation == null?GetInvocation(parameters, serviceId, typeof(T)) : invocation;

                foreach (var interceptor in _interceptors)
                {
                    var interceptReuslt = await Intercept(interceptor, invocation);

                    message = interceptReuslt.Item1;
                    result  = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2;
                }
            }

            if (message != null)
            {
                if (message.Result == null)
                {
                    result = message.Result;
                }
                else
                {
                    result = _typeConvertibleService.Convert(message.Result, typeof(T));
                }
            }

            return((T)result);
        }
예제 #3
0
        /// <summary>
        /// 远程调用。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="parameters">参数字典。</param>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>调用结果。</returns>
        protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId)
        {
            object result  = default(T);
            var    command = await _commandProvider.GetCommand(serviceId);

            RemoteInvokeResultMessage message = null;
            var         decodeJOject          = typeof(T) == UtilityType.ObjectType;
            IInvocation invocation            = null;
            var         existsInterceptor     = _interceptors.Any();

            if ((_cacheInterceptor == null || !command.RequestCacheEnabled) && !existsInterceptor)
            {
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject);

                if (message == null || !message.IsSucceedRemoteInvokeCalled())
                {
                    return(await FallBackRetryInvoke <T>(parameters, serviceId, command));
                }
            }
            if (_cacheInterceptor != null && command.RequestCacheEnabled)
            {
                invocation = GetCacheInvocation(parameters, serviceId, typeof(T));
                if (invocation != null)
                {
                    var interceptReuslt = await Intercept(_cacheInterceptor, invocation);

                    message = interceptReuslt.Item1;
                    result  = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2;
                }
                else
                {
                    message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject);

                    if (message == null || !message.IsSucceedRemoteInvokeCalled())
                    {
                        return(await FallBackRetryInvoke <T>(parameters, serviceId, command));
                    }
                }
            }
            if (existsInterceptor)
            {
                invocation = invocation == null?GetInvocation(parameters, serviceId, typeof(T)) : invocation;

                foreach (var interceptor in _interceptors)
                {
                    var interceptReuslt = await Intercept(interceptor, invocation);

                    message = interceptReuslt.Item1;
                    result  = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2;
                }
            }
            if (message != null)
            {
                result = await GetInvokeResult <T>(message);
            }
            return((T)result);
        }
        /// <summary>
        /// 远程调用。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="parameters">参数字典。</param>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>调用结果。</returns>
        protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId)
        {
            object result  = default(T);
            var    command = await _commandProvider.GetCommand(serviceId);

            RemoteInvokeResultMessage message = null;
            var         decodeJOject          = typeof(T) == UtilityType.ObjectType;
            IInvocation invocation            = null;
            var         existsInterceptor     = _interceptors.Any();

            if ((!command.RequestCacheEnabled || decodeJOject) && !existsInterceptor)
            {
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject);

                if (message == null)
                {
                    if (command.FallBackName != null && _serviceProvider.IsRegistered <IFallbackInvoker>(command.FallBackName) && command.Strategy == StrategyType.FallBack)
                    {
                        var invoker = _serviceProvider.GetInstances <IFallbackInvoker>(command.FallBackName);
                        return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey));
                    }
                    else
                    {
                        var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString());
                        return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey, typeof(T) == UtilityType.ObjectType));
                    }
                }
            }
            if (command.RequestCacheEnabled && !decodeJOject)
            {
                invocation = GetCacheInvocation(parameters, serviceId, typeof(T));
                var interceptReuslt = await Intercept(_cacheInterceptor, invocation);

                message = interceptReuslt.Item1;
                result  = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2;
            }
            if (existsInterceptor)
            {
                invocation = invocation == null?GetInvocation(parameters, serviceId, typeof(T)) : invocation;

                foreach (var interceptor in _interceptors)
                {
                    var interceptReuslt = await Intercept(interceptor, invocation);

                    message = interceptReuslt.Item1;
                    result  = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2;
                }
            }
            if (message != null)
            {
                result = _typeConvertibleService.Convert(message.Result, typeof(T));
            }
            return((T)result);
        }
예제 #5
0
        public async Task Invoke(IDictionary <string, object> parameters, string serviceId, string serviceKey)
        {
            var command = _serviceCommandProvider.GetCommand(serviceId);
            var result  = await _serviceCommandProvider.Run(command.Injection, command.InjectionNamespaces);

            if (result is Boolean)
            {
                if ((bool)result)
                {
                    var entries = _serviceEntryManager.GetEntries().ToList();
                    var entry   = entries.Where(p => p.Descriptor.Id == serviceId).FirstOrDefault();
                    await entry.Func(serviceKey, parameters);
                }
            }
        }
예제 #6
0
        public async Task <RemoteInvokeResultMessage> InvokeAsync(IDictionary <string, object> parameters, string serviceId, string serviceKey, bool decodeJOject, bool isFailoverInvoke = false)
        {
            var serviceInvokeInfos = _serviceInvokeListenInfo.GetOrAdd(serviceId,
                                                                       new ServiceInvokeListenInfo()
            {
                FirstInvokeTime       = DateTime.Now,
                FinalRemoteInvokeTime = DateTime.Now
            });

            UpdateAttachments(parameters);
            RpcContext.GetContext().SetAttachment("isFailoverInvoke", isFailoverInvoke);
            var command = await _commandProvider.GetCommand(serviceId);

            var intervalSeconds = (DateTime.Now - serviceInvokeInfos.FinalRemoteInvokeTime).TotalSeconds;

            bool reachConcurrentRequest() => serviceInvokeInfos.ConcurrentRequests > command.MaxConcurrentRequests;
            bool reachRequestVolumeThreshold() => intervalSeconds <= 10 && serviceInvokeInfos.SinceFaultRemoteServiceRequests > command.BreakerRequestVolumeThreshold;

            bool reachErrorThresholdPercentage()
            {
                var errorThresholdPercent = serviceInvokeInfos.FaultRemoteServiceRequests / (serviceInvokeInfos.RemoteServiceRequests ?? 1) * 100;

                return(errorThresholdPercent > command.BreakeErrorThresholdPercentage && serviceInvokeInfos.RemoteServiceRequests.HasValue && serviceInvokeInfos.RemoteServiceRequests.Value > 1);
            }

            var item = GetHashItem(command, parameters);

            if (command.BreakerForceClosed)
            {
                _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); });
                return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item));
            }
            else
            {
                if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage())
                {
                    if (intervalSeconds * 1000 > command.BreakeSleepWindowInMilliseconds || isFailoverInvoke)
                    {
                        return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item));
                    }
                    else
                    {
                        _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); });
                        if (_logger.IsEnabled(LogLevel.Debug))
                        {
                            _logger.LogDebug($"当前服务{serviceId}-{serviceKey}当前不可用,请稍后重试");
                        }
                        var breakeSeconds = Math.Round((command.BreakeSleepWindowInMilliseconds - intervalSeconds * 1000) / 1000, 0);
                        return(new RemoteInvokeResultMessage()
                        {
                            ExceptionMessage = $"当前没有可用的服务{serviceId}-{serviceKey},请稍后{breakeSeconds}s后重试", StatusCode = StatusCode.ServiceUnavailability
                        });
                    }
                }
                else
                {
                    return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item));
                }
            }
        }
예제 #7
0
        /// <summary>
        /// 调用.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="serviceId">The service identifier.</param>
        /// <param name="serviceKey">The service key.</param>
        /// <param name="decodeJOject">if set to <c>true</c> [decode j oject].</param>
        /// <returns>Task.</returns>
        public async Task Invoke(IDictionary <string, object> parameters, string serviceId, string serviceKey,
                                 bool decodeJOject)
        {
            var vt      = _serviceCommandProvider.GetCommand(serviceId);
            var command = vt.IsCompletedSuccessfully ? vt.Result : await vt;
            var result  = await _serviceCommandProvider.Run(command.Injection, command.InjectionNamespaces);

            if (result is bool)
            {
                if ((bool)result)
                {
                    var entries = _serviceEntryManager.GetEntries().ToList();
                    var entry   = entries.Where(p => p.Descriptor.Id == serviceId).FirstOrDefault();
                    await entry.Func(serviceKey, parameters);
                }
            }
        }
예제 #8
0
        /// <summary>
        /// 解析服务地址。
        /// </summary>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>服务地址模型。</returns>
        /// 1.从字典中拿到serviceroute对象
        /// 2.从字典中拿到服务描述符集合
        /// 3.获取或添加serviceroute
        /// 4.添加服务id到白名单
        /// 5.根据服务描述符得到地址并判断地址是否是可用的(地址应该是多个)
        /// 6.添加到集合中
        /// 7.拿到服务命今
        /// 8.根据负载分流策略拿到一个选择器
        /// 9.返回addressmodel
        public async ValueTask <AddressModel> Resolver(string serviceId, string item)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"准备为服务id:{serviceId},解析可用地址。");
            }

            var serviceRouteTask = _serviceRouteProvider.Locate(serviceId);
            var serviceRoute     = serviceRouteTask.IsCompletedSuccessfully ? serviceRouteTask.Result : await serviceRouteTask;

            if (serviceRoute == null)
            {
                if (_logger.IsEnabled(LogLevel.Warning))
                {
                    _logger.LogWarning($"根据服务id:{serviceId},找不到相关服务信息。");
                }
                return(null);
            }
            _serviceHeartbeatManager.AddWhitelist(serviceId);
            var address = new List <AddressModel>();

            foreach (var addressModel in serviceRoute.Address)
            {
                _healthCheckService.Monitor(addressModel);
                var task = _healthCheckService.IsHealth(addressModel);
                if (!(task.IsCompletedSuccessfully ? task.Result : await task))
                {
                    continue;
                }
                address.Add(addressModel);
            }

            if (address.Count == 0)
            {
                if (_logger.IsEnabled(LogLevel.Warning))
                {
                    _logger.LogWarning($"根据服务id:{serviceId},找不到可用的地址。");
                }
                return(null);
            }

            if (_logger.IsEnabled(LogLevel.Information))
            {
                _logger.LogInformation($"根据服务id:{serviceId},找到以下可用地址:{string.Join(",", address.Select(i => i.ToString()))}。");
            }
            var vtCommand       = _commandProvider.GetCommand(serviceId);
            var command         = vtCommand.IsCompletedSuccessfully ? vtCommand.Result : await vtCommand;
            var addressSelector = _addressSelectors[command.ShuntStrategy.ToString()];

            var vt = addressSelector.SelectAsync(new AddressSelectContext
            {
                Descriptor = serviceRoute.ServiceDescriptor,
                Address    = address,
                Item       = item
            });

            return(vt.IsCompletedSuccessfully ? vt.Result : await vt);
        }
예제 #9
0
        /// <summary>
        /// 远程调用。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="parameters">参数字典。</param>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>调用结果。</returns>
        protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId)
        {
            var message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey);

            if (message == null)
            {
                var command = _commandProvider.GetCommand(serviceId);
                var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString());
                return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey));
            }
            if (message == null)
            {
                return(default(T));
            }
            var result = _typeConvertibleService.Convert(message.Result, typeof(T));

            return((T)result);
        }
        public async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId, string _serviceKey, bool decodeJOject)
        {
            var time   = 0;
            T   result = default(T);
            RemoteInvokeResultMessage message = null;
            var command = await _commandProvider.GetCommand(serviceId);

            do
            {
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject);

                if (message != null && message.Result != null)
                {
                    result = (T)_typeConvertibleService.Convert(message.Result, typeof(T));
                }
            } while (message == null && ++time < command.FailoverCluster);
            return(result);
        }
        public async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId, string _serviceKey, bool decodeJOject)
        {
            var time   = 0;
            T   result = default(T);
            RemoteInvokeResultMessage message = null;
            var command = await _commandProvider.GetCommand(serviceId);

            do
            {
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject, true);

                if (message != null)
                {
                    if (message.StatusCode == StatusCode.Success)
                    {
                        if (message.Result != null)
                        {
                            result = (T)_typeConvertibleService.Convert(message.Result, typeof(T));
                        }
                        else
                        {
                            result = default(T);
                        }
                    }
                    else if (message.IsFailedRemoteInvokeCalled())
                    {
                        continue;
                    }
                    else if (message.IsSucceedRemoteInvokeCalled())
                    {
                        throw message.GetExceptionByStatusCode();
                    }
                }
            } while ((message == null || !message.IsSucceedRemoteInvokeCalled()) && ++time < command.FailoverCluster);
            if (message == null)
            {
                throw new CPlatformException($"{serviceId}远程服务调用失败,暂不存在可用的服务实例");
            }
            if (message.StatusCode != StatusCode.Success)
            {
                throw message.GetExceptionByStatusCode();
            }
            return(result);
        }
예제 #12
0
        /// <summary>
        /// 远程调用。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="parameters">参数字典。</param>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>调用结果。</returns>
        protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId)
        {
            object result  = default(T);
            var    command = await _commandProvider.GetCommand(serviceId);

            RemoteInvokeResultMessage message;
            var decodeJOject = typeof(T) == UtilityType.ObjectType;

            if (!command.RequestCacheEnabled || decodeJOject)
            {
                var v = typeof(T).FullName;
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject);

                if (message == null)
                {
                    if (command.FallBackName != null && _serviceProvider.IsRegistered <IFallbackInvoker>(command.FallBackName) && command.Strategy == StrategyType.FallBack)
                    {
                        var invoker = _serviceProvider.GetInstances <IFallbackInvoker>(command.FallBackName);
                        return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey));
                    }
                    else
                    {
                        var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString());
                        return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey, typeof(T) == UtilityType.ObjectType));
                    }
                }
            }
            else
            {
                var invocation = GetInvocation(parameters, serviceId, typeof(T));
                await _interceptor.Intercept(invocation);

                message = invocation.ReturnValue is RemoteInvokeResultMessage
                    ? invocation.ReturnValue as RemoteInvokeResultMessage : null;
                result = invocation.ReturnValue;
            }

            if (message != null)
            {
                result = _typeConvertibleService.Convert(message.Result, typeof(T));
            }
            return((T)result);
        }
예제 #13
0
        public async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId, string _serviceKey, bool decodeJOject)
        {
            var time   = 0;
            T   result = default(T);
            RemoteInvokeResultMessage message = null;
            var vtCommand = _commandProvider.GetCommand(serviceId);
            var command   = vtCommand.IsCompletedSuccessfully ? vtCommand.Result : await vtCommand;

            do
            {
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject);

                if (message != null && message.Result != null)
                {
                    if (message.StatusCode != StatusCode.Success && time >= command.FailoverCluster)
                    {
                        throw new CPlatformException(message.ExceptionMessage, message.StatusCode);
                    }
                    result = (T)_typeConvertibleService.Convert(message.Result, typeof(T));
                }
            } while ((message == null || message.StatusCode == StatusCode.ServiceUnavailability) && ++time < command.FailoverCluster);
            return(result);
        }
예제 #14
0
        public async Task <RemoteInvokeResultMessage> InvokeAsync(IDictionary <string, object> parameters, string serviceId, string serviceKey, bool decodeJOject)
        {
            var serviceInvokeInfos = _serviceInvokeListenInfo.GetOrAdd(serviceId,
                                                                       new ServiceInvokeListenInfo()
            {
                FirstInvokeTime       = DateTime.Now,
                FinalRemoteInvokeTime = DateTime.Now
            });
            var command = await _commandProvider.GetCommand(serviceId);

            var intervalSeconds = (DateTime.Now - serviceInvokeInfos.FinalRemoteInvokeTime).TotalSeconds;

            bool reachConcurrentRequest() => serviceInvokeInfos.ConcurrentRequests > command.MaxConcurrentRequests;
            bool reachRequestVolumeThreshold() => intervalSeconds <= 10 &&
            serviceInvokeInfos.SinceFaultRemoteServiceRequests > command.BreakerRequestVolumeThreshold;
            bool reachErrorThresholdPercentage() =>
            (double)serviceInvokeInfos.FaultRemoteServiceRequests / (double)(serviceInvokeInfos.RemoteServiceRequests ?? 1) * 100 > command.BreakeErrorThresholdPercentage;

            var hashCode = GetHashCode(command, parameters);

            if (command.BreakerForceClosed)
            {
                _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); });
                return(null);
            }
            else
            {
                if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage())
                {
                    if (intervalSeconds * 1000 > command.BreakeSleepWindowInMilliseconds)
                    {
                        return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, hashCode));
                    }
                    else
                    {
                        _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); });
                        return(null);
                    }
                }
                else
                {
                    return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, hashCode));
                }
            }
        }
예제 #15
0
        public async Task <RemoteInvokeResultMessage> InvokeAsync(IDictionary <string, object> parameters, string serviceId, string serviceKey)
        {
            var serviceInvokeInfos = _serviceInvokeListenInfo.GetOrAdd(serviceId, new ServiceInvokeListenInfo());
            var command            = _commandProvider.GetCommand(serviceId);
            var intervalSeconds    = (DateTime.Now - serviceInvokeInfos.FinalRemoteInvokeTime).TotalSeconds;

            bool reachConcurrentRequest() => serviceInvokeInfos.ConcurrentRequests > command.MaxConcurrentRequests;
            bool reachRequestVolumeThreshold() => intervalSeconds <= 10 &&
            serviceInvokeInfos.SinceFaultRemoteServiceRequests > command.BreakerRequestVolumeThreshold;
            bool reachErrorThresholdPercentage() =>
            serviceInvokeInfos.FaultRemoteServiceRequests / (serviceInvokeInfos.RemoteServiceRequests ?? 1) * 100 > command.BreakeErrorThresholdPercentage;

            if (command.BreakerForceClosed)
            {
                _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); });
                return(null);
            }
            else
            {
                if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage())
                {
                    if (intervalSeconds * 1000 > command.BreakeSleepWindowInMilliseconds)
                    {
                        return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey));
                    }
                    else
                    {
                        _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); });
                        return(null);
                    }
                }
                else
                {
                    return(await  MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey));
                }
            }
            throw new NotImplementedException();
        }
        /// <summary>
        /// 解析服务地址。
        /// </summary>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>服务地址模型。</returns>
        /// 1.从字典中拿到serviceroute对象
        /// 2.从字典中拿到服务描述符集合
        /// 3.获取或添加serviceroute
        /// 4.添加服务id到白名单
        /// 5.根据服务描述符得到地址并判断地址是否是可用的(地址应该是多个)
        /// 6.添加到集合中
        /// 7.拿到服务命今
        /// 8.根据负载分流策略拿到一个选择器
        /// 9.返回addressmodel
        public async Task <AddressModel> Resolver(string serviceId, string item)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"准备为服务id:{serviceId},解析可用地址。");
            }

            var isFailoverInvoke = IsFailoverInvoke();
            var serviceRoute     = await _serviceRouteProvider.Locate(serviceId, !isFailoverInvoke);

            if (serviceRoute == null)
            {
                throw new CPlatformException($"根据服务id:{serviceId},找不到相关服务信息。【fromCache:{!isFailoverInvoke}】");
            }
            var address = await GetHealthAddress(serviceRoute);

            if (!address.Any())
            {
                throw new CPlatformException($"根据服务id:{serviceId},找不到可用的服务提供者的地址");
            }

            _serviceHeartbeatManager.AddWhitelist(serviceId);

            var command = await _commandProvider.GetCommand(serviceId);

            var addressSelector = _addressSelectors[command.ShuntStrategy.ToString()];

            var selectAddress = await addressSelector.SelectAsync(new AddressSelectContext
            {
                Descriptor = serviceRoute.ServiceDescriptor,
                Address    = address,
                Item       = item
            });

            return(selectAddress);
        }
        /// <summary>
        /// 解析服务地址。
        /// </summary>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>服务地址模型。</returns>
        public async ValueTask <AddressModel> Resolver(string serviceId, string item)
        {
            if (_logger.IsEnabled(LogLevel.Debug))
            {
                _logger.LogDebug($"准备为服务id:{serviceId},解析可用地址。");
            }

            _concurrent.TryGetValue(serviceId, out ServiceRoute descriptor);
            if (descriptor == null)
            {
                var descriptors = await _serviceRouteManager.GetRoutesAsync();

                descriptor = descriptors.FirstOrDefault(i => i.ServiceDescriptor.Id == serviceId);
                if (descriptor != null)
                {
                    _concurrent.GetOrAdd(serviceId, descriptor);
                    _serviceHeartbeatManager.AddWhitelist(serviceId);
                }
                else
                {
                    if (descriptor == null)
                    {
                        if (_logger.IsEnabled(LogLevel.Warning))
                        {
                            _logger.LogWarning($"根据服务id:{serviceId},找不到相关服务信息。");
                        }
                        return(null);
                    }
                }
            }

            var address = new List <AddressModel>();

            foreach (var addressModel in descriptor.Address)
            {
                _healthCheckService.Monitor(addressModel);
                if (!await _healthCheckService.IsHealth(addressModel))
                {
                    continue;
                }

                address.Add(addressModel);
            }

            if (address.Count == 0)
            {
                if (_logger.IsEnabled(LogLevel.Warning))
                {
                    _logger.LogWarning($"根据服务id:{serviceId},找不到可用的地址。");
                }
                return(null);
            }

            if (_logger.IsEnabled(LogLevel.Information))
            {
                _logger.LogInformation($"根据服务id:{serviceId},找到以下可用地址:{string.Join(",", address.Select(i => i.ToString()))}。");
            }
            var command = await _commandProvider.GetCommand(serviceId);

            var addressSelector = _addressSelectors[command.ShuntStrategy.ToString()];

            return(await addressSelector.SelectAsync(new AddressSelectContext
            {
                Descriptor = descriptor.ServiceDescriptor,
                Address = address,
                Item = item
            }));
        }
예제 #18
0
        /// <summary>
        /// 远程调用。
        /// </summary>
        /// <typeparam name="T">返回类型。</typeparam>
        /// <param name="parameters">参数字典。</param>
        /// <param name="serviceId">服务Id。</param>
        /// <returns>调用结果。</returns>
        protected async Task <T> Invoke <T>(IDictionary <string, object> parameters, string serviceId)
        {
            object result  = default(T);
            var    vt      = _commandProvider.GetCommand(serviceId);
            var    command = vt.IsCompletedSuccessfully ? vt.Result : await vt;
            RemoteInvokeResultMessage message = null;
            var         decodeJOject          = typeof(T) == UtilityType.ObjectType;
            IInvocation invocation            = null;
            var         existsInterceptor     = _interceptors.Any();

            if ((_cacheInterceptor == null || !command.RequestCacheEnabled) && !existsInterceptor)
            {
                message = await _breakeRemoteInvokeService.InvokeAsync(parameters, serviceId, _serviceKey, decodeJOject);

                if (message == null)
                {
                    if (command.FallBackName != null && _serviceProvider.IsRegistered <IFallbackInvoker>(command.FallBackName) && command.Strategy == StrategyType.FallBack)
                    {
                        var invoker = _serviceProvider.GetInstances <IFallbackInvoker>(command.FallBackName);
                        return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey));
                    }
                    else
                    {
                        var invoker = _serviceProvider.GetInstances <IClusterInvoker>(command.Strategy.ToString());
                        return(await invoker.Invoke <T>(parameters, serviceId, _serviceKey, typeof(T) == UtilityType.ObjectType));
                    }
                }
            }
            if (_cacheInterceptor != null && command.RequestCacheEnabled)
            {
                invocation = GetCacheInvocation(parameters, serviceId, typeof(T));
                var interceptReuslt = await Intercept(_cacheInterceptor, invocation);

                message = interceptReuslt.Item1;
                result  = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2;
            }
            if (existsInterceptor)
            {
                invocation = invocation == null?GetInvocation(parameters, serviceId, typeof(T)) : invocation;

                foreach (var interceptor in _interceptors)
                {
                    var interceptReuslt = await Intercept(interceptor, invocation);

                    message = interceptReuslt.Item1;
                    result  = interceptReuslt.Item2 == null ? default(T) : interceptReuslt.Item2;
                }
            }
            //if (message != null)
            //{
            //    if (message.Result == null) result = message.Result;
            //    else  result = _typeConvertibleService.Convert(message.Result, typeof(T));
            //}
            if (message != null)
            {
                if (message.StatusCode == StatusCode.Success)
                {
                    result = _typeConvertibleService.Convert(message.Result, typeof(T));
                }
                else
                {
                    switch (message.StatusCode)
                    {
                    case StatusCode.BusinessError:
                        throw new BusinessException(message.ExceptionMessage);

                    case StatusCode.CommunicationError:
                        throw new CommunicationException(message.ExceptionMessage);

                    case StatusCode.RequestError:
                    case StatusCode.CPlatformError:
                    case StatusCode.UnKnownError:
                        throw new CPlatformException(message.ExceptionMessage, message.StatusCode);

                    case StatusCode.DataAccessError:
                        throw new DataAccessException(message.ExceptionMessage);

                    case StatusCode.UnAuthentication:
                        throw new UnAuthenticationException(message.ExceptionMessage);

                    case StatusCode.UnAuthorized:
                        throw new UnAuthorizedException(message.ExceptionMessage);

                    case StatusCode.UserFriendly:
                        throw new UserFriendlyException(message.ExceptionMessage);

                    case StatusCode.ValidateError:
                        throw new ValidateException(message.ExceptionMessage);
                    }
                    throw new CPlatformException(message.ExceptionMessage, message.StatusCode);
                }
            }
            return((T)result);
        }
        public async Task <RemoteInvokeResultMessage> InvokeAsync(IDictionary <string, object> parameters, string serviceId, string serviceKey, bool decodeJOject)
        {
            var serviceInvokeInfos = _serviceInvokeListenInfo.GetOrAdd(serviceId,
                                                                       new ServiceInvokeListenInfo()
            {
                FirstInvokeTime       = DateTime.Now,
                FinalRemoteInvokeTime = DateTime.Now
            });
            var vt              = _commandProvider.GetCommand(serviceId);
            var command         = vt.IsCompletedSuccessfully ? vt.Result : await vt;
            var intervalSeconds = (DateTime.Now - serviceInvokeInfos.FinalRemoteInvokeTime).TotalSeconds;

            bool reachConcurrentRequest() => serviceInvokeInfos.ConcurrentRequests > command.MaxConcurrentRequests;
            bool reachRequestVolumeThreshold() => intervalSeconds <= 10 &&
            serviceInvokeInfos.SinceFaultRemoteServiceRequests > command.BreakerRequestVolumeThreshold;
            bool reachErrorThresholdPercentage() =>
            (double)serviceInvokeInfos.FaultRemoteServiceRequests / (double)(serviceInvokeInfos.RemoteServiceRequests ?? 1) * 100 > command.BreakeErrorThresholdPercentage;

            var item = GetHashItem(command, parameters);

            if (command.BreakerForceClosed)
            {
                _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); });
                if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage())
                {
                    return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item));
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                if (reachConcurrentRequest() || reachRequestVolumeThreshold() || reachErrorThresholdPercentage())
                {
                    if (intervalSeconds * 1000 > command.BreakeSleepWindowInMilliseconds)
                    {
                        return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item));
                    }
                    else
                    {
                        _serviceInvokeListenInfo.AddOrUpdate(serviceId, new ServiceInvokeListenInfo(), (k, v) => { v.LocalServiceRequests++; return(v); });
                        if (_logger.IsEnabled(LogLevel.Debug))
                        {
                            _logger.LogDebug("当前服务{serviceId}-{serviceKey}当前不可用,请稍后重试");
                        }
                        var breakeSeconds = Math.Round((command.BreakeSleepWindowInMilliseconds - intervalSeconds * 1000) / 1000, 0);
                        return(new RemoteInvokeResultMessage()
                        {
                            ExceptionMessage = $"当前服务{serviceId}-{serviceKey}当前不可用,请稍后{breakeSeconds}s后重试", StatusCode = StatusCode.ServiceUnavailability
                        });
                        //return null;
                    }
                }
                else
                {
                    return(await MonitorRemoteInvokeAsync(parameters, serviceId, serviceKey, decodeJOject, command.ExecutionTimeoutInMilliseconds, item));
                }
            }
        }