コード例 #1
0
        /// <summary>
        /// 将满足中断条件的响应放入缓存
        /// </summary>
        /// <param name="argument"></param>
        /// <param name="result">响应结果</param>
        public void SetFunseResult(RetryPolicyArgument argument, ResponseWrapperResult result)
        {
            //未开启中断配置,或成功响应跳过
            if (argument.Option == null || !argument.Option.FuseEnabled || argument.IsSuccessResponse(result.Response))
            {
                return;
            }

            var       key   = $"{argument.Service}.{argument.Module}";
            FuseEntry entry = default;

            if (_cache.TryGetValue <FuseEntry>(key, out entry))
            {
                if (entry.FailedCount >= argument.Option.FuseEnabledWhenFailedCount)
                {
                    _logger.LogWarning($"服务{key}连续失败次数:{entry.FailedCount}已达阈值:{argument.Option.FuseEnabledWhenFailedCount},触发中断,时间:{argument.Option.FuseDuration}ms");
                    entry.Result       = result;
                    entry.Result.Fused = true;
                }
            }
            else
            {
                entry = new FuseEntry();
            }
            entry.FailedCount++;
            _cache.Set <FuseEntry>(key, entry, TimeSpan.FromMilliseconds(argument.Option.FuseDuration));
        }
コード例 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="argument"></param>
        /// <returns></returns>
        public async Task <ResponseWrapperResult> ProcessAsync(RetryPolicyArgument argument)
        {
            var fusedResult = TryGetFuseResult(argument.Service, argument.Module);

            if (fusedResult != null)
            {
                return(fusedResult);
            }

            var records = new List <RequestRecord>();
            var option  = argument.Option;

            await HandleException(argument.Request, async() =>
            {
                var timeoutToken = (option?.TotalTimeout ?? 0) > 0
                     ? new CancellationTokenSource(TimeSpan.FromMilliseconds(option.TotalTimeout))
                     : new CancellationTokenSource();
                return(await SendWithRetryAsync(option, argument.Request, argument.Sending, records, timeoutToken.Token));
            }, record =>
            {
                //只有执行超时才会抛ExecutionHttpException,意味着重试结束
                if (record.Exception is ExecutionHttpException executionEx)
                {
                    record.Request   = executionEx.Request;
                    record.Exception = executionEx.InnerException;
                    record.Duration  = GetDuration(record.Request.TimeStamp);
                    records.Add(record);
                }
                return(record);
            });

            var result = new ResponseWrapperResult
            {
                Request    = argument.Request,
                Records    = records,
                Duration   = GetDuration(argument.Request.TimeStamp),
                RetryCount = records.Count() > 1 ? records.Count() - 1 : 0
            };
            //获取有效请求记录
            RequestRecord vaildRecord = result.Records.LastOrDefault(x => x.Response != null)
                                        ?? result.Records.LastOrDefault();

            result.Response  = vaildRecord?.Response;
            result.Exception = vaildRecord?.Exception;
            _logger.LogInformation($"请求{argument.Request.RequestUri}执行完毕,用时:{result.Duration}ms");
            SetFunseResult(argument, result);
            return(result);
        }
コード例 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="descriptor"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task <ResponseWrapper> SendAndWrapAsync(RequestDescriptor descriptor, CancellationToken token = default)
        {
            var requestBuilder = _builderFactory.GetBuilder(descriptor.HttpOption.RequestBuilderType);
            var request        = requestBuilder.GetRequest(descriptor);

            var result = _cacheOperator.Read(request);

            if (!result.HasHitCache)
            {
                var argument = new RetryPolicyArgument
                {
                    Service           = descriptor.ServiceName,
                    Module            = descriptor.ModuleName,
                    Option            = descriptor.HttpOption.RetryOption,
                    Request           = request,
                    IsSuccessResponse = descriptor.HttpOption.IsSuccessResponse,
                    Sending           = async message =>
                    {
                        var client          = _clientFactory.CreateClient(descriptor.ServiceName);
                        var responseMessage = await client.SendAsync(message, token);

                        return(new HttpResponse(responseMessage));
                    }
                };
                result = await _retryProcessor.ProcessAsync(argument);

                //调用日志记录器,写缓存(如果符合条件)
                _cacheOperator.Write(result.Response, descriptor.HttpOption.CacheOption);
            }
            try
            {
                //保存请求信息,请求结果
                await _recordStore.WriteAsync(descriptor, result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"日志记录器{_recordStore.GetType().Name},写入日志时出错:{ex.Message}");
            }

            if (result.Exception != null)
            {
                throw result.Exception;
            }
            return(result);
        }