77import java .util .concurrent .Executors ;
88import java .util .concurrent .ScheduledExecutorService ;
99import java .util .concurrent .TimeUnit ;
10+ import java .util .concurrent .atomic .AtomicBoolean ;
1011import java .util .concurrent .atomic .AtomicReference ;
1112
1213import org .slf4j .Logger ;
1718import com .ctrip .framework .apollo .core .ConfigConsts ;
1819import com .ctrip .framework .apollo .core .dto .ApolloConfig ;
1920import com .ctrip .framework .apollo .core .dto .ServiceDTO ;
21+ import com .ctrip .framework .apollo .core .schedule .ExponentialSchedulePolicy ;
22+ import com .ctrip .framework .apollo .core .schedule .SchedulePolicy ;
2023import com .ctrip .framework .apollo .core .utils .ApolloThreadFactory ;
2124import com .ctrip .framework .apollo .exceptions .ApolloConfigException ;
2225import com .ctrip .framework .apollo .exceptions .ApolloConfigStatusCodeException ;
@@ -51,6 +54,8 @@ public class RemoteConfigRepository extends AbstractConfigRepository {
5154 private final static ScheduledExecutorService m_executorService ;
5255 private AtomicReference <ServiceDTO > m_longPollServiceDto ;
5356 private RateLimiter m_loadConfigRateLimiter ;
57+ private AtomicBoolean m_configNeedForceRefresh ;
58+ private SchedulePolicy m_loadConfigFailSchedulePolicy ;
5459 private static final Escaper pathEscaper = UrlEscapers .urlPathSegmentEscaper ();
5560 private static final Escaper queryParamEscaper = UrlEscapers .urlFormParameterEscaper ();
5661
@@ -73,6 +78,9 @@ public RemoteConfigRepository(String namespace) {
7378 remoteConfigLongPollService = ApolloInjector .getInstance (RemoteConfigLongPollService .class );
7479 m_longPollServiceDto = new AtomicReference <>();
7580 m_loadConfigRateLimiter = RateLimiter .create (m_configUtil .getLoadConfigQPS ());
81+ m_configNeedForceRefresh = new AtomicBoolean (true );
82+ m_loadConfigFailSchedulePolicy = new ExponentialSchedulePolicy (m_configUtil .getOnErrorRetryInterval (),
83+ m_configUtil .getOnErrorRetryInterval () * 8 );
7684 this .trySync ();
7785 this .schedulePeriodicRefresh ();
7886 this .scheduleLongPollingRefresh ();
@@ -154,7 +162,8 @@ private ApolloConfig loadApolloConfig() {
154162 String cluster = m_configUtil .getCluster ();
155163 String dataCenter = m_configUtil .getDataCenter ();
156164 Tracer .logEvent ("Apollo.Client.ConfigMeta" , STRING_JOINER .join (appId , cluster , m_namespace ));
157- int maxRetries = 2 ;
165+ int maxRetries = m_configNeedForceRefresh .get () ? 2 : 1 ;
166+ long onErrorSleepTime = 0 ; // 0 means no sleep
158167 Throwable exception = null ;
159168
160169 List <ServiceDTO > configServices = getConfigServices ();
@@ -167,6 +176,18 @@ private ApolloConfig loadApolloConfig() {
167176 }
168177
169178 for (ServiceDTO configService : randomConfigServices ) {
179+ if (onErrorSleepTime > 0 ) {
180+ logger .warn (
181+ "Load config failed, will retry in {} {}. appId: {}, cluster: {}, namespaces: {}" ,
182+ onErrorSleepTime , m_configUtil .getOnErrorRetryIntervalTimeUnit (), appId , cluster , m_namespace );
183+
184+ try {
185+ m_configUtil .getOnErrorRetryIntervalTimeUnit ().sleep (onErrorSleepTime );
186+ } catch (InterruptedException e ) {
187+ //ignore
188+ }
189+ }
190+
170191 String url =
171192 assembleQueryConfigUrl (configService .getHomepageUrl (), appId , cluster , m_namespace ,
172193 dataCenter , m_configCache .get ());
@@ -179,6 +200,8 @@ private ApolloConfig loadApolloConfig() {
179200 try {
180201
181202 HttpResponse <ApolloConfig > response = m_httpUtil .doGet (request , ApolloConfig .class );
203+ m_configNeedForceRefresh .set (false );
204+ m_loadConfigFailSchedulePolicy .success ();
182205
183206 transaction .addData ("StatusCode" , response .getStatusCode ());
184207 transaction .setStatus (Transaction .SUCCESS );
@@ -215,13 +238,11 @@ private ApolloConfig loadApolloConfig() {
215238 transaction .complete ();
216239 }
217240
241+ // if force refresh, do normal sleep, if normal config load, do exponential sleep
242+ onErrorSleepTime = m_configNeedForceRefresh .get () ? m_configUtil .getOnErrorRetryInterval () :
243+ m_loadConfigFailSchedulePolicy .fail ();
218244 }
219245
220- try {
221- m_configUtil .getOnErrorRetryIntervalTimeUnit ().sleep (m_configUtil .getOnErrorRetryInterval ());
222- } catch (InterruptedException ex ) {
223- //ignore
224- }
225246 }
226247 String message = String .format (
227248 "Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s" ,
@@ -271,6 +292,7 @@ public void onLongPollNotified(ServiceDTO longPollNotifiedServiceDto) {
271292 m_executorService .submit (new Runnable () {
272293 @ Override
273294 public void run () {
295+ m_configNeedForceRefresh .set (true );
274296 trySync ();
275297 }
276298 });
0 commit comments