11package org .tron .core .net .service .effective ;
22
33import java .util .Comparator ;
4+ import java .util .HashMap ;
45import java .util .List ;
6+ import java .util .Map ;
57import java .util .Optional ;
68import java .util .Random ;
79import java .util .concurrent .ScheduledExecutorService ;
@@ -29,6 +31,7 @@ public class ResilienceService {
2931 //when node is isolated, retention percent peers will not be disconnected
3032 public static final double retentionPercent = 0.8 ;
3133 private static final int initialDelay = 300 ;
34+ public static final int minBroadcastPeerSize = 3 ;
3235 private static final String esName = "resilience-service" ;
3336 private final ScheduledExecutorService executor = ExecutorServiceManager
3437 .newSingleThreadScheduledExecutor (esName );
@@ -47,7 +50,7 @@ public void init() {
4750 } catch (Exception e ) {
4851 logger .error ("DisconnectRandom node failed" , e );
4952 }
50- }, initialDelay , 60 , TimeUnit .SECONDS );
53+ }, initialDelay , 30 , TimeUnit .SECONDS );
5154 } else {
5255 logger .info ("OpenFullTcpDisconnect is disabled" );
5356 }
@@ -71,21 +74,50 @@ public void init() {
7174
7275 private void disconnectRandom () {
7376 int peerSize = tronNetDelegate .getActivePeer ().size ();
74- if (peerSize >= CommonParameter .getInstance ().getMaxConnections ()) {
77+ if (peerSize < CommonParameter .getInstance ().getMaxConnections ()) {
78+ return ;
79+ }
80+ List <PeerConnection > peers = tronNetDelegate .getActivePeer ().stream ()
81+ .filter (peer -> !peer .getChannel ().isTrustPeer ())
82+ .filter (peer -> !peer .isNeedSyncFromUs () && !peer .isNeedSyncFromPeer ())
83+ .collect (Collectors .toList ());
84+
85+ if (peers .size () >= minBroadcastPeerSize ) {
7586 long now = System .currentTimeMillis ();
76- List <PeerConnection > peers = tronNetDelegate .getActivePeer ().stream ()
77- .filter (peer -> now - peer .getLastInteractiveTime () >= inactiveThreshold )
87+ Map <Object , Integer > weights = new HashMap <>();
88+ peers .forEach (peer -> {
89+ int weight = (int ) Math .ceil ((double ) (now - peer .getLastInteractiveTime ()) / 500 );
90+ weights .put (peer , Math .max (weight , 1 ));
91+ });
92+ WeightedRandom weightedRandom = new WeightedRandom (weights );
93+ PeerConnection one = (PeerConnection ) weightedRandom .next ();
94+ disconnectFromPeer (one , ReasonCode .RANDOM_ELIMINATION , DisconnectCause .RANDOM_ELIMINATION );
95+ return ;
96+ }
97+
98+ int needSyncFromPeerCount = (int ) tronNetDelegate .getActivePeer ().stream ()
99+ .filter (peer -> !peer .getChannel ().isTrustPeer ())
100+ .filter (PeerConnection ::isNeedSyncFromPeer )
101+ .count ();
102+ if (needSyncFromPeerCount >= 2 ) {
103+ peers = tronNetDelegate .getActivePeer ().stream ()
78104 .filter (peer -> !peer .getChannel ().isTrustPeer ())
79- .filter (peer -> !peer .isNeedSyncFromUs () && !peer .isNeedSyncFromPeer ())
105+ .filter (peer -> peer .isNeedSyncFromUs () || peer .isNeedSyncFromPeer ())
106+ .collect (Collectors .toList ());
107+ } else {
108+ peers = tronNetDelegate .getActivePeer ().stream ()
109+ .filter (peer -> !peer .getChannel ().isTrustPeer ())
110+ .filter (PeerConnection ::isNeedSyncFromUs )
80111 .collect (Collectors .toList ());
81- if (! peers . isEmpty ()) {
82- int index = new Random (). nextInt ( peers .size ());
83- disconnectFromPeer ( peers .get ( index ), ReasonCode . RANDOM_ELIMINATION ,
84- DisconnectCause .RANDOM_ELIMINATION );
85- }
112+ }
113+ if (! peers .isEmpty ()) {
114+ int index = new Random (). nextInt ( peers .size ());
115+ disconnectFromPeer ( peers . get ( index ), ReasonCode .RANDOM_ELIMINATION ,
116+ DisconnectCause . RANDOM_ELIMINATION );
86117 }
87118 }
88119
120+
89121 private void disconnectLan () {
90122 if (!isLanNode ()) {
91123 return ;
@@ -198,6 +230,32 @@ private enum DisconnectCause {
198230 ISOLATE2_PASSIVE ,
199231 }
200232
233+ static class WeightedRandom {
234+
235+ private final Map <Object , Integer > weights ;
236+ private final Random random ;
237+
238+ public WeightedRandom (Map <Object , Integer > weights ) {
239+ this .weights = weights ;
240+ this .random = new Random ();
241+ }
242+
243+ public Object next () {
244+ int totalWeight = 0 ;
245+ for (int weight : weights .values ()) {
246+ totalWeight += weight ;
247+ }
248+ int randomNum = random .nextInt (totalWeight );
249+ for (Object key : weights .keySet ()) {
250+ randomNum -= weights .get (key );
251+ if (randomNum < 0 ) {
252+ return key ;
253+ }
254+ }
255+ throw new IllegalStateException ("Sum of weights should not be negative." );
256+ }
257+ }
258+
201259 public void close () {
202260 ExecutorServiceManager .shutdownAndAwaitTermination (executor , esName );
203261 }
0 commit comments