@@ -37,7 +37,12 @@ public abstract class AbstractClient implements MessageDispatcher {
37
37
protected HashMap <List <String >, List <String >> users = new HashMap <>();
38
38
protected boolean isClose_ = false ;
39
39
protected LinkedBlockingQueue <DBConnection > connList = new LinkedBlockingQueue <>();
40
+ protected static boolean ifUseBackupSite ;
41
+ protected String lastBackupSiteTopic = "" ;
40
42
protected Map <String , Integer > currentSiteIndexMap = new ConcurrentHashMap <>();
43
+ protected static Map <String , Long > lastExceptionTopicTimeMap = new ConcurrentHashMap <>();
44
+ protected static Integer resubTimeout ;
45
+ protected static boolean subOnce ;
41
46
42
47
private Daemon daemon = null ;
43
48
@@ -166,6 +171,17 @@ public Site getSiteByName(String site) {
166
171
return null ;
167
172
}
168
173
174
+ public Site getCurrentSiteByName (String site ) {
175
+ List <String > topics = this .getAllTopicsBySite (site );
176
+ if (topics .size () > 0 ) {
177
+ Site [] sites = trueTopicToSites .get (topics .get (0 ));
178
+ Integer currentSiteIndex = currentSiteIndexMap .get (topics .get (0 ));
179
+ return sites [currentSiteIndex ];
180
+ }
181
+
182
+ return null ;
183
+ }
184
+
169
185
public Map <String , StreamDeserializer > getSubInfos (){
170
186
return subInfos_ ;
171
187
}
@@ -227,32 +243,65 @@ public boolean tryReconnect(String topic) {
227
243
}
228
244
229
245
boolean reconnected = false ;
230
- for (int i = 0 ; i < sites .length ; i ++) {
231
- Integer currentSiteIndex = currentSiteIndexMap .get (topic );
232
- if (currentSiteIndexMap .get (topic ) != -1 )
233
- i = currentSiteIndex ;
234
- Site site = sites [i ];
235
- boolean siteReconnected = false ;
236
- for (int attempt = 0 ; attempt < 2 ; attempt ++) {
237
- // try twice every site
238
- if (doReconnect (site )) {
239
- siteReconnected = true ;
240
- // if site current connect successfully, break
246
+ Integer currentSiteIndex = currentSiteIndexMap .get (topic );
247
+ if (currentSiteIndex != null && currentSiteIndex != -1 ) {
248
+ int totalSites = sites .length ;
249
+ // set successfulSiteIndex init value to -1.
250
+ int successfulSiteIndex = -1 ;
251
+
252
+ // Starting from currentSiteIndex, go around in a circle until you return to the position just before it (circular looping).
253
+ for (int offset = 0 ; offset < totalSites ; offset ++) {
254
+ // Implement wrapping around using modulo operation
255
+ int i = (currentSiteIndex + offset ) % totalSites ;
256
+
257
+ Site site = sites [i ];
258
+ boolean siteReconnected = false ;
259
+
260
+ for (int attempt = 0 ; attempt < 1 ; attempt ++) {
261
+ // try twice for every site.
262
+ if (doReconnect (site )) {
263
+ siteReconnected = true ;
264
+ // if site reconnect successfully, break.
265
+ break ;
266
+ }
267
+ }
268
+
269
+ if (siteReconnected ) {
270
+ reconnected = true ;
271
+ successfulSiteIndex = i ;
272
+ // if current site reconnect successfully, no continue try other sites, break.
241
273
break ;
242
274
}
243
275
}
244
- if (siteReconnected ) {
245
- reconnected = true ;
246
- currentSiteIndexMap .put (topic , i );
247
- // if current site connect successfully, no tryReconnect other site, break
248
- break ;
276
+
277
+ // Determine whether to delete the original currentSiteIndex node based on the subOnce parameter.
278
+ if (subOnce && reconnected ) {
279
+ List <Site > siteList = new ArrayList <>(Arrays .asList (sites ));
280
+ // Remove the original currentSiteIndex node from the list.
281
+ siteList .remove ((int ) currentSiteIndex );
282
+ // update sites
283
+ sites = siteList .toArray (new Site [0 ]);
284
+
285
+ // Calculate the index of the newly successful connection node after a successful deletion.
286
+ if (successfulSiteIndex > currentSiteIndex ) {
287
+ // If the successfully connected node is after the deleted node, reduce the index by 1.
288
+ successfulSiteIndex -= 1 ;
289
+ }
290
+ // update currentSiteIndexMap to new successfully connected site's index;
291
+ currentSiteIndexMap .put (topic , successfulSiteIndex );
292
+ } else if (reconnected ) {
293
+ // not delete site, but update successfulSiteIndex.
294
+ currentSiteIndexMap .put (topic , successfulSiteIndex );
249
295
}
250
296
}
251
297
298
+ log .info ("Successfully switched to node: " + sites [currentSiteIndexMap .get (topic )].host + ":" + sites [currentSiteIndexMap .get (topic )].port );
299
+
252
300
if (!reconnected ) {
253
301
waitReconnectTopic .add (topic );
254
302
return false ;
255
303
} else {
304
+ reconnectTable .remove (topic .substring (0 , topic .indexOf ("/" )));
256
305
waitReconnectTopic .remove (topic );
257
306
return true ;
258
307
}
@@ -438,13 +487,14 @@ protected BlockingQueue<List<IMessage>> subscribeInternal(String host, int port,
438
487
long offset , boolean reconnect , Vector filter , StreamDeserializer deserializer ,
439
488
boolean allowExistTopic , String userName , String passWord , boolean msgAsTable )
440
489
throws IOException , RuntimeException {
441
- return subscribeInternal (host , port , tableName , actionName , handler , offset , reconnect , filter , deserializer , allowExistTopic , userName , passWord , msgAsTable , null );
490
+ return subscribeInternal (host , port , tableName , actionName , handler , offset , reconnect , filter , deserializer , allowExistTopic , userName , passWord , msgAsTable , null , 100 , false );
442
491
}
443
492
444
493
protected BlockingQueue <List <IMessage >> subscribeInternal (String host , int port ,
445
494
String tableName , String actionName , MessageHandler handler ,
446
495
long offset , boolean reconnect , Vector filter , StreamDeserializer deserializer ,
447
- boolean allowExistTopic , String userName , String passWord , boolean msgAsTable , List <String > backupSites ) throws IOException , RuntimeException {
496
+ boolean allowExistTopic , String userName , String passWord , boolean msgAsTable ,
497
+ List <String > backupSites , int resubTimeout , boolean subOnce ) throws IOException , RuntimeException {
448
498
Entity re ;
449
499
String topic = "" ;
450
500
DBConnection dbConn ;
@@ -455,6 +505,9 @@ protected BlockingQueue<List<IMessage>> subscribeInternal(String host, int port,
455
505
456
506
List <Site > parsedBackupSites = new ArrayList <>();
457
507
if (Objects .nonNull (backupSites ) && !backupSites .isEmpty ()) {
508
+ AbstractClient .resubTimeout = resubTimeout ;
509
+ AbstractClient .subOnce = subOnce ;
510
+ AbstractClient .ifUseBackupSite = true ;
458
511
// prepare backupSites
459
512
for (int i = 0 ; i < backupSites .size () + 1 ; i ++) {
460
513
if (i == 0 ) {
@@ -494,6 +547,7 @@ protected BlockingQueue<List<IMessage>> subscribeInternal(String host, int port,
494
547
params .add (new BasicString (actionName ));
495
548
re = dbConn .run ("getSubscriptionTopic" , params );
496
549
topic = ((BasicAnyVector ) re ).getEntity (0 ).getString ();
550
+ lastBackupSiteTopic = topic ;
497
551
params .clear ();
498
552
499
553
// set current site index
@@ -598,7 +652,20 @@ protected BlockingQueue<List<IMessage>> subscribeInternal(String host, int port,
598
652
599
653
re = dbConn .run ("publishTable" , params );
600
654
connList .add (dbConn );
601
- if (re instanceof BasicAnyVector ) {
655
+ if (ifUseBackupSite ) {
656
+ synchronized (subInfos_ ){
657
+ subInfos_ .put (topic , deserializer );
658
+ }
659
+ synchronized (tableNameToTrueTopic ) {
660
+ tableNameToTrueTopic .put (host + ":" + port + "/" + tableName + "/" + actionName , topic );
661
+ }
662
+ synchronized (HATopicToTrueTopic ) {
663
+ HATopicToTrueTopic .put (topic , topic );
664
+ }
665
+ synchronized (trueTopicToSites ) {
666
+ trueTopicToSites .put (topic , trueTopicToSites .get (lastBackupSiteTopic ));
667
+ }
668
+ } else if (re instanceof BasicAnyVector ) {
602
669
BasicStringVector HASiteStrings = (BasicStringVector ) (((BasicAnyVector ) re ).getEntity (1 ));
603
670
int HASiteNum = HASiteStrings .rows ();
604
671
Site [] sites = new Site [HASiteNum ];
0 commit comments