private async Task DoLongPollingRefresh(string appId, string cluster, string dataCenter, CancellationToken cancellationToken) { var random = new Random(); ServiceDto lastServiceDto = null; while (!cancellationToken.IsCancellationRequested) { var sleepTime = 50; //default 50 ms string url = null; try { if (lastServiceDto == null) { var configServices = await _serviceLocator.GetConfigServices().ConfigureAwait(false); lastServiceDto = configServices[random.Next(configServices.Count)]; } url = AssembleLongPollRefreshUrl(lastServiceDto.HomepageUrl, appId, cluster, dataCenter); Logger().Debug($"Long polling from {url}"); var response = await _httpUtil.DoGetAsync <IList <ApolloConfigNotification> >(url, 600000).ConfigureAwait(false); Logger().Debug($"Long polling response: {response.StatusCode}, url: {url}"); if (response.StatusCode == HttpStatusCode.OK && response.Body != null) { UpdateNotifications(response.Body); UpdateRemoteNotifications(response.Body); Notify(lastServiceDto, response.Body); _longPollSuccessSchedulePolicyInMs.Success(); } else { sleepTime = _longPollSuccessSchedulePolicyInMs.Fail(); } //try to load balance if (response.StatusCode == HttpStatusCode.NotModified && random.NextDouble() >= 0.5) { lastServiceDto = null; } _longPollFailSchedulePolicyInSecond.Success(); } catch (Exception ex) { lastServiceDto = null; var sleepTimeInSecond = _longPollFailSchedulePolicyInSecond.Fail(); Logger().Warn($"Long polling failed, will retry in {sleepTimeInSecond} seconds. appId: {appId}, cluster: {cluster}, namespace: {string.Join(ConfigConsts.ClusterNamespaceSeparator, _longPollNamespaces.Keys)}, long polling url: {url}, reason: {ex.GetDetailMessage()}"); sleepTime = sleepTimeInSecond * 1000; } finally { await Task.Delay(sleepTime, cancellationToken).ConfigureAwait(false); } } }
private async Task <ApolloConfig?> LoadApolloConfig(bool isFirst) { var appId = _options.AppId; var cluster = _options.Cluster; var dataCenter = _options.DataCenter; var configServices = await _serviceLocator.GetConfigServices().ConfigureAwait(false); Exception?exception = null; string? url = null; var notFound = false; for (var i = 0; i < (isFirst ? 1 : 2); i++) { IList <ServiceDto> randomConfigServices = new List <ServiceDto>(configServices); randomConfigServices.Shuffle(); //Access the server which notifies the client first var longPollServiceDto = Interlocked.Exchange(ref _longPollServiceDto, null); if (longPollServiceDto != null) { randomConfigServices.Insert(0, longPollServiceDto); } foreach (var configService in randomConfigServices) { url = AssembleQueryConfigUrl(configService.HomepageUrl, appId, cluster, Namespace, dataCenter, _remoteMessages !, _configCache !); Logger().Debug($"Loading config from {url}"); try { var response = await _httpUtil.DoGetAsync <ApolloConfig>(url).ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.NotModified) { Logger().Debug("Config server responds with 304 HTTP status code."); return(_configCache !); } var result = response.Body; Logger().Debug( $"Loaded config for {Namespace}: {result?.Configurations?.Count ?? 0}"); return(result); } catch (ApolloConfigStatusCodeException ex) { var statusCodeException = ex; //config not found if (ex.StatusCode == HttpStatusCode.NotFound) { notFound = true; var message = $"Could not find config for namespace - appId: {appId}, cluster: {cluster}, namespace: {Namespace}, please check whether the configs are released in Apollo!"; statusCodeException = new ApolloConfigStatusCodeException(ex.StatusCode, message); } Logger().Warn(statusCodeException); exception = statusCodeException; } catch (Exception ex) { Logger().Warn(ex); exception = ex; } } #if NET40 await TaskEx.Delay(1000).ConfigureAwait(false); #else await Task.Delay(1000).ConfigureAwait(false); #endif } if (notFound) { return(null); } var fallbackMessage = $"Load Apollo Config failed - appId: {appId}, cluster: {cluster}, namespace: {Namespace}, url: {url}"; throw new ApolloConfigException(fallbackMessage, exception !); }