コード例 #1
0
        protected async Task <PutRecordsResult> InnerPutRecordsWithRetry(PutRecordsRequest putRecordsParam, PutRecordAsyncMethod putRecordMethod)
        {
            //数据上传的结果集
            PutRecordsResult putRecordsResult = null;

            //用该数组来汇总每次请求后的结果
            PutRecordsResultEntry[] putRecordsResultEntryList = null;

            //记录每次请求失败的下标位置
            int[] retryIndex = null;

            //每次需要上传的请求数据
            PutRecordsRequest retryPutRecordsRequest = putRecordsParam;

            int retryCount             = -1;
            int currentFailed          = 0;
            ExponentialBackOff backOff = null;

            try
            {
                do
                {
                    retryCount++;
                    if (retryCount > 0)
                    {
                        // 等待一段时间再发起重试
                        if (backOff == null)
                        {
                            Monitor.Enter(objlock, ref acquireLock);
                            logger.Info("Put records retry lock.");
                            backOff = new ExponentialBackOff(ExponentialBackOff.DEFAULT_INITIAL_INTERVAL,
                                                             ExponentialBackOff.DEFAULT_MULTIPLIER, _disConfig.GetBackOffMaxIntervalMs(),
                                                             ExponentialBackOff.DEFAULT_MAX_ELAPSED_TIME);
                        }

                        if (putRecordsResult != null && currentFailed != putRecordsResult.Records.Count)
                        {
                            // 部分失败则重置退避时间
                            backOff.resetCurrentInterval();
                        }

                        long sleepMs = backOff.getNextBackOff();

                        if (retryPutRecordsRequest.Records.Count > 0)
                        {
                            logger.DebugFormat(
                                "Put {0} records but {1} failed, will re-try after backoff {2} ms, current retry count is {3}.",
                                putRecordsResult != null ? putRecordsResult.Records.Count
                                    : putRecordsParam.Records.Count,
                                currentFailed,
                                sleepMs,
                                retryCount);
                        }

                        backOff.backOff(sleepMs);
                    }

                    try
                    {
                        putRecordsResult = await putRecordMethod(retryPutRecordsRequest);
                    }
                    catch (Exception t)
                    {
                        if (putRecordsResultEntryList != null)
                        {
                            logger.Error(t.Message, t);
                            break;
                        }
                        throw t;
                    }

                    if (putRecordsResult != null)
                    {
                        currentFailed = putRecordsResult.FailedRecordCount;

                        if (putRecordsResultEntryList == null && currentFailed == 0 || _disConfig.GetRecordsRetries() == 0)
                        {
                            // 第一次发送全部成功或者不需要重试,则直接返回结果
                            return(putRecordsResult);
                        }

                        if (putRecordsResultEntryList == null)
                        {
                            // 存在发送失败的情况,需要重试,则使用数组来汇总每次请求后的结果。
                            putRecordsResultEntryList = new PutRecordsResultEntry[putRecordsParam.Records.Count];
                        }

                        // 需要重试发送数据的原始下标
                        List <int> retryIndexTemp = new List <int>(currentFailed);

                        if (currentFailed > 0)
                        {
                            // 初始化重试发送的数据请求
                            retryPutRecordsRequest            = new PutRecordsRequest();
                            retryPutRecordsRequest.StreamName = putRecordsParam.StreamName;
                            retryPutRecordsRequest.Records    = new List <PutRecordsRequestEntry>(currentFailed);
                        }

                        // 对每条结果分析,更新结果数据
                        for (int i = 0; i < putRecordsResult.Records.Count; i++)
                        {
                            // 获取重试数据在原始数据中的下标位置
                            int originalIndex = retryIndex == null ? i : retryIndex[i];
                            PutRecordsResultEntry putRecordsResultEntry = putRecordsResult.Records[i];
                            // 对所有异常进行重试 && "DIS.4303".equals(putRecordsResultEntry.getErrorCode())
                            if (!string.IsNullOrEmpty(putRecordsResultEntry.ErrorCode))
                            {
                                retryIndexTemp.Add(originalIndex);
                                retryPutRecordsRequest.Records.Add(putRecordsParam.Records[originalIndex]);
                            }
                            putRecordsResultEntryList[originalIndex] = putRecordsResultEntry;
                        }
                        retryIndex = retryIndexTemp.Count > 0 ? retryIndexTemp.ToArray()
                            : new int[0];
                    }
                } while ((retryIndex == null || retryIndex.Length > 0) && retryCount < _disConfig.GetRecordsRetries());
            }
            finally
            {
                if (retryCount > 0)
                {
                    Monitor.Exit(objlock);
                    logger.Info("Put records retry unlock.");
                }
            }
            //putRecordsResult.Result = new PutRecordsResult();
            if (retryIndex == null)
            {
                // 不可能存在此情况,完全没有发送出去会直接抛出异常
                putRecordsResult.FailedRecordCount = putRecordsParam.Records.Count;
            }
            else
            {
                putRecordsResult.FailedRecordCount = retryIndex.Length;
                putRecordsResult.Records           = new List <PutRecordsResultEntry>(putRecordsResultEntryList);
            }

            return(putRecordsResult);
        }
コード例 #2
0
        protected async Task <PutRecordsResult> InnerPutRecordsSupportingCache(PutRecordsRequest putRecordsParam, PutRecordAsyncMethod putRecordMethod)
        {
            if (_disConfig.IsDataCacheEnabled())
            {
                // 开启本地缓存
                PutRecordsResult putRecordsResult = null;
                try
                {
                    putRecordsResult = await InnerPutRecordsWithRetry(putRecordsParam, putRecordMethod);
                }
                catch (Exception e)
                {
                    string errorMsg   = e.Message;
                    int    statusCode = int.Parse(errorMsg.Split('\n')[0]);
                    // 如果不是可以重试的异常 或者 已达到重试次数,则直接抛出异常
                    if (Utils.IsCacheData(statusCode))
                    {
                        // 网络异常 全部记录上传失败
                        logger.Info("Local data cache is enabled, try to put failed records to local.");
                        CacheUtils.PutToCache(putRecordsParam, _disConfig); // 写入本地缓存
                    }
                    throw new Exception(e.Message.Substring(statusCode.ToString().Length + 1));
                }

                try
                {
                    // 部分记录上传失败
                    if (putRecordsResult.FailedRecordCount > 0)
                    {
                        // 过滤出上传失败的记录
                        List <PutRecordsResultEntry>  putRecordsResultEntries        = putRecordsResult.Records;
                        List <PutRecordsRequestEntry> failedPutRecordsRequestEntries = new List <PutRecordsRequestEntry>();
                        int index = 0;
                        foreach (PutRecordsResultEntry putRecordsResultEntry in putRecordsResultEntries)
                        {
                            if (!String.IsNullOrEmpty(putRecordsResultEntry.ErrorCode))
                            {
                                failedPutRecordsRequestEntries.Add(putRecordsParam.Records[index]);
                            }
                            index++;
                        }
                        putRecordsParam.Records = failedPutRecordsRequestEntries;

                        logger.Info("Local data cache is enabled, try to put failed records to local.");

                        CacheUtils.PutToCache(putRecordsParam, _disConfig); // 写入本地缓存
                    }
                }
                catch (Exception e)
                {
                    throw e;
                }

                return(putRecordsResult);
            }
            else
            {
                return(await InnerPutRecordsWithRetry(putRecordsParam, putRecordMethod));
            }
        }