mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 23:18:17 +01:00
Merge pull request #434 from ivilata/PeerManagerInstanceMaxConn
Per-instance max connections in PeerManager
This commit is contained in:
commit
c745bb37a7
6 changed files with 78 additions and 54 deletions
|
@ -55,9 +55,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
public class P2PService implements SetupListener, MessageListener, ConnectionListener, RequestDataManager.Listener,
|
||||
HashMapChangedListener {
|
||||
private static final Logger log = LoggerFactory.getLogger(P2PService.class);
|
||||
public static final int MAX_CONNECTIONS_DEFAULT = 12;
|
||||
|
||||
private final SeedNodesRepository seedNodesRepository;
|
||||
private final int port;
|
||||
private final int maxConnections;
|
||||
private final File torDir;
|
||||
private Clock clock;
|
||||
private final Optional<EncryptionService> optionalEncryptionService;
|
||||
|
@ -104,8 +106,32 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
|
|||
Clock clock,
|
||||
@Nullable EncryptionService encryptionService,
|
||||
@Nullable KeyRing keyRing) {
|
||||
this(
|
||||
seedNodesRepository,
|
||||
port, MAX_CONNECTIONS_DEFAULT,
|
||||
torDir,
|
||||
useLocalhost,
|
||||
networkId,
|
||||
storageDir,
|
||||
clock,
|
||||
encryptionService,
|
||||
keyRing
|
||||
);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public P2PService(SeedNodesRepository seedNodesRepository,
|
||||
int port, int maxConnections,
|
||||
File torDir,
|
||||
boolean useLocalhost,
|
||||
int networkId,
|
||||
File storageDir,
|
||||
Clock clock,
|
||||
@Nullable EncryptionService encryptionService,
|
||||
@Nullable KeyRing keyRing) {
|
||||
this.seedNodesRepository = seedNodesRepository;
|
||||
this.port = port;
|
||||
this.maxConnections = maxConnections;
|
||||
this.torDir = torDir;
|
||||
this.clock = clock;
|
||||
|
||||
|
@ -124,7 +150,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
|
|||
networkNode.addMessageListener(this);
|
||||
|
||||
Set<NodeAddress> seedNodeAddresses = seedNodesRepository.getSeedNodeAddresses(useLocalhost, networkId);
|
||||
peerManager = new PeerManager(networkNode, seedNodeAddresses, storageDir, clock);
|
||||
peerManager = new PeerManager(networkNode, maxConnections, seedNodeAddresses, storageDir, clock);
|
||||
|
||||
broadcaster = new Broadcaster(networkNode, peerManager);
|
||||
|
||||
|
|
|
@ -28,32 +28,28 @@ public class PeerManager implements ConnectionListener {
|
|||
// Use a long delay as the bootstrapping peer might need a while until it knows its onion address
|
||||
private static final long REMOVE_ANONYMOUS_PEER_SEC = Timer.STRESS_TEST ? 10 : 120;
|
||||
|
||||
private static int MAX_CONNECTIONS;
|
||||
private static int MIN_CONNECTIONS;
|
||||
private static int MAX_CONNECTIONS_PEER;
|
||||
private static int MAX_CONNECTIONS_NON_DIRECT;
|
||||
|
||||
|
||||
private static int MAX_CONNECTIONS_ABSOLUTE;
|
||||
private final boolean printReportedPeersDetails = true;
|
||||
private boolean lostAllConnections;
|
||||
|
||||
public static void setMaxConnections(int maxConnections) {
|
||||
MAX_CONNECTIONS = maxConnections;
|
||||
MIN_CONNECTIONS = Math.max(1, maxConnections - 4);
|
||||
MAX_CONNECTIONS_PEER = MAX_CONNECTIONS + 4;
|
||||
MAX_CONNECTIONS_NON_DIRECT = MAX_CONNECTIONS + 8;
|
||||
MAX_CONNECTIONS_ABSOLUTE = MAX_CONNECTIONS + 18;
|
||||
}
|
||||
|
||||
static {
|
||||
setMaxConnections(12);
|
||||
}
|
||||
|
||||
private static final int MAX_REPORTED_PEERS = 1000;
|
||||
private static final int MAX_PERSISTED_PEERS = 500;
|
||||
private static final long MAX_AGE = TimeUnit.DAYS.toMillis(14); // max age for reported peers is 14 days
|
||||
|
||||
private final boolean printReportedPeersDetails = true;
|
||||
private boolean lostAllConnections;
|
||||
|
||||
private int maxConnections;
|
||||
private int minConnections;
|
||||
private int maxConnectionsPeer;
|
||||
private int maxConnectionsNonDirect;
|
||||
private int maxConnectionsAbsolute;
|
||||
|
||||
// Modify this to change the relationships between connection limits.
|
||||
private void setConnectionLimits(int maxConnections) {
|
||||
this.maxConnections = maxConnections;
|
||||
minConnections = Math.max(1, maxConnections - 4);
|
||||
maxConnectionsPeer = maxConnections + 4;
|
||||
maxConnectionsNonDirect = maxConnections + 8;
|
||||
maxConnectionsAbsolute = maxConnections + 18;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Listener
|
||||
|
@ -90,7 +86,9 @@ public class PeerManager implements ConnectionListener {
|
|||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public PeerManager(NetworkNode networkNode, Set<NodeAddress> seedNodeAddresses, File storageDir, Clock clock) {
|
||||
public PeerManager(NetworkNode networkNode, int maxConnections, Set<NodeAddress> seedNodeAddresses,
|
||||
File storageDir, Clock clock) {
|
||||
setConnectionLimits(maxConnections);
|
||||
this.networkNode = networkNode;
|
||||
this.clock = clock;
|
||||
// seedNodeAddresses can be empty (in case there is only 1 seed node, the seed node starting up has no other seed nodes)
|
||||
|
@ -139,7 +137,7 @@ public class PeerManager implements ConnectionListener {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public int getMaxConnections() {
|
||||
return MAX_CONNECTIONS_ABSOLUTE;
|
||||
return maxConnectionsAbsolute;
|
||||
}
|
||||
|
||||
public void addListener(Listener listener) {
|
||||
|
@ -199,7 +197,7 @@ public class PeerManager implements ConnectionListener {
|
|||
removeSuperfluousSeedNodes();
|
||||
removeTooOldReportedPeers();
|
||||
removeTooOldPersistedPeers();
|
||||
checkMaxConnections(MAX_CONNECTIONS);
|
||||
checkMaxConnections(maxConnections);
|
||||
} else {
|
||||
log.warn("We have stopped already. We ignore that checkMaxConnectionsTimer.run call.");
|
||||
}
|
||||
|
@ -223,8 +221,8 @@ public class PeerManager implements ConnectionListener {
|
|||
|
||||
if (candidates.size() == 0) {
|
||||
log.info("No candidates found. We check if we exceed our " +
|
||||
"MAX_CONNECTIONS_PEER limit of {}", MAX_CONNECTIONS_PEER);
|
||||
if (size > MAX_CONNECTIONS_PEER) {
|
||||
"maxConnectionsPeer limit of {}", maxConnectionsPeer);
|
||||
if (size > maxConnectionsPeer) {
|
||||
log.info("Lets try to remove ANY connection of type PEER.");
|
||||
candidates = allConnections.stream()
|
||||
.filter(e -> e.getPeerType() == Connection.PeerType.PEER)
|
||||
|
@ -232,8 +230,8 @@ public class PeerManager implements ConnectionListener {
|
|||
|
||||
if (candidates.size() == 0) {
|
||||
log.info("No candidates found. We check if we exceed our " +
|
||||
"MAX_CONNECTIONS_NON_DIRECT limit of {}", MAX_CONNECTIONS_NON_DIRECT);
|
||||
if (size > MAX_CONNECTIONS_NON_DIRECT) {
|
||||
"maxConnectionsNonDirect limit of {}", maxConnectionsNonDirect);
|
||||
if (size > maxConnectionsNonDirect) {
|
||||
log.info("Lets try to remove any connection which is not of type DIRECT_MSG_PEER.");
|
||||
candidates = allConnections.stream()
|
||||
.filter(e -> e.getPeerType() != Connection.PeerType.DIRECT_MSG_PEER)
|
||||
|
@ -241,8 +239,8 @@ public class PeerManager implements ConnectionListener {
|
|||
|
||||
if (candidates.size() == 0) {
|
||||
log.info("No candidates found. We check if we exceed our " +
|
||||
"MAX_CONNECTIONS_ABSOLUTE limit of {}", MAX_CONNECTIONS_ABSOLUTE);
|
||||
if (size > MAX_CONNECTIONS_ABSOLUTE) {
|
||||
"maxConnectionsAbsolute limit of {}", maxConnectionsAbsolute);
|
||||
if (size > maxConnectionsAbsolute) {
|
||||
log.info("Lets try to remove any connection.");
|
||||
candidates = allConnections.stream().collect(Collectors.toList());
|
||||
}
|
||||
|
@ -288,7 +286,7 @@ public class PeerManager implements ConnectionListener {
|
|||
|
||||
private void removeSuperfluousSeedNodes() {
|
||||
Log.traceCall();
|
||||
if (networkNode.getConfirmedConnections().size() > MAX_CONNECTIONS) {
|
||||
if (networkNode.getConfirmedConnections().size() > maxConnections) {
|
||||
Set<Connection> connections = networkNode.getConfirmedConnections();
|
||||
if (hasSufficientConnections()) {
|
||||
List<Connection> candidates = connections.stream()
|
||||
|
@ -346,7 +344,7 @@ public class PeerManager implements ConnectionListener {
|
|||
printNewReportedPeers(reportedPeersToAdd);
|
||||
|
||||
// We check if the reported msg is not violating our rules
|
||||
if (reportedPeersToAdd.size() <= (MAX_REPORTED_PEERS + PeerManager.MAX_CONNECTIONS_ABSOLUTE + 10)) {
|
||||
if (reportedPeersToAdd.size() <= (MAX_REPORTED_PEERS + maxConnectionsAbsolute + 10)) {
|
||||
reportedPeers.addAll(reportedPeersToAdd);
|
||||
purgeReportedPeersIfExceeds();
|
||||
|
||||
|
@ -367,7 +365,7 @@ public class PeerManager implements ConnectionListener {
|
|||
private void purgeReportedPeersIfExceeds() {
|
||||
Log.traceCall();
|
||||
int size = reportedPeers.size();
|
||||
int limit = MAX_REPORTED_PEERS - MAX_CONNECTIONS_ABSOLUTE;
|
||||
int limit = MAX_REPORTED_PEERS - maxConnectionsAbsolute;
|
||||
if (size > limit) {
|
||||
log.trace("We have already {} reported peers which exceeds our limit of {}." +
|
||||
"We remove random peers from the reported peers list.", size, limit);
|
||||
|
@ -470,7 +468,7 @@ public class PeerManager implements ConnectionListener {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public boolean hasSufficientConnections() {
|
||||
return networkNode.getNodeAddressesOfConfirmedConnections().size() >= MIN_CONNECTIONS;
|
||||
return networkNode.getNodeAddressesOfConfirmedConnections().size() >= minConnections;
|
||||
}
|
||||
|
||||
public boolean isSeedNode(Peer reportedPeer) {
|
||||
|
|
|
@ -30,6 +30,7 @@ public class SeedNode {
|
|||
public static final int MAX_CONNECTIONS_DEFAULT = 50;
|
||||
|
||||
private NodeAddress mySeedNodeAddress = new NodeAddress("localhost:8001");
|
||||
private int maxConnections = MAX_CONNECTIONS_DEFAULT; // we keep default a higher connection size for seed nodes
|
||||
private boolean useLocalhost = false;
|
||||
private Set<NodeAddress> progArgSeedNodes;
|
||||
private P2PService seedNodeP2PService;
|
||||
|
@ -67,13 +68,9 @@ public class SeedNode {
|
|||
Version.setBtcNetworkId(networkId);
|
||||
if (args.length > 2) {
|
||||
String arg2 = args[2];
|
||||
int maxConnections = Integer.parseInt(arg2);
|
||||
maxConnections = Integer.parseInt(arg2);
|
||||
log.info("From processArgs: maxConnections=" + maxConnections);
|
||||
checkArgument(maxConnections < MAX_CONNECTIONS_LIMIT, "maxConnections seems to be a bit too high...");
|
||||
PeerManager.setMaxConnections(maxConnections);
|
||||
} else {
|
||||
// we keep default a higher connection size for seed nodes
|
||||
PeerManager.setMaxConnections(MAX_CONNECTIONS_DEFAULT);
|
||||
}
|
||||
if (args.length > 3) {
|
||||
String arg3 = args[3];
|
||||
|
@ -107,11 +104,13 @@ public class SeedNode {
|
|||
}
|
||||
|
||||
public void createAndStartP2PService(boolean useDetailedLogging) {
|
||||
createAndStartP2PService(mySeedNodeAddress, useLocalhost, Version.getBtcNetworkId(), useDetailedLogging, progArgSeedNodes, null);
|
||||
createAndStartP2PService(mySeedNodeAddress, maxConnections, useLocalhost,
|
||||
Version.getBtcNetworkId(), useDetailedLogging, progArgSeedNodes, null);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void createAndStartP2PService(NodeAddress mySeedNodeAddress,
|
||||
int maxConnections,
|
||||
boolean useLocalhost,
|
||||
int networkId,
|
||||
boolean useDetailedLogging,
|
||||
|
@ -144,7 +143,8 @@ public class SeedNode {
|
|||
log.info("Created torDir at " + torDir.getAbsolutePath());
|
||||
|
||||
seedNodesRepository.setNodeAddressToExclude(mySeedNodeAddress);
|
||||
seedNodeP2PService = new P2PService(seedNodesRepository, mySeedNodeAddress.port, torDir, useLocalhost, networkId, storageDir, new Clock(), null, null);
|
||||
seedNodeP2PService = new P2PService(seedNodesRepository, mySeedNodeAddress.port, maxConnections,
|
||||
torDir, useLocalhost, networkId, storageDir, new Clock(), null, null);
|
||||
seedNodeP2PService.start(listener);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.concurrent.CountDownLatch;
|
|||
// Run it once then lookup for onion address at: tor/hiddenservice/hostname and use that for the NodeAddress param.
|
||||
public class PeerServiceTest {
|
||||
private static final Logger log = LoggerFactory.getLogger(PeerServiceTest.class);
|
||||
private static final int MAX_CONNECTIONS = 100;
|
||||
|
||||
final boolean useLocalhost = true;
|
||||
private CountDownLatch latch;
|
||||
|
@ -37,7 +38,6 @@ public class PeerServiceTest {
|
|||
public void setup() throws InterruptedException {
|
||||
LocalhostNetworkNode.setSimulateTorDelayTorNode(50);
|
||||
LocalhostNetworkNode.setSimulateTorDelayHiddenService(8);
|
||||
PeerManager.setMaxConnections(100);
|
||||
|
||||
if (useLocalhost) {
|
||||
seedNodeAddresses.add(new NodeAddress("localhost:8001"));
|
||||
|
@ -127,7 +127,7 @@ public class PeerServiceTest {
|
|||
|
||||
/* latch = new CountDownLatch(2);
|
||||
|
||||
seedNode.createAndStartP2PService(nodeAddress, useLocalhost, 2, true,
|
||||
seedNode.createAndStartP2PService(nodeAddress, MAX_CONNECTIONS, useLocalhost, 2, true,
|
||||
seedNodeAddresses, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
|
@ -181,7 +181,7 @@ public class PeerServiceTest {
|
|||
latch = new CountDownLatch(6);
|
||||
|
||||
seedNode1 = new SeedNode("test_dummy_dir");
|
||||
seedNode1.createAndStartP2PService(nodeAddress1, useLocalhost, 2, true, seedNodeAddresses, new P2PServiceListener() {
|
||||
seedNode1.createAndStartP2PService(nodeAddress1, MAX_CONNECTIONS, useLocalhost, 2, true, seedNodeAddresses, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
latch.countDown();
|
||||
|
@ -219,7 +219,7 @@ public class PeerServiceTest {
|
|||
Thread.sleep(500);
|
||||
|
||||
seedNode2 = new SeedNode("test_dummy_dir");
|
||||
seedNode2.createAndStartP2PService(nodeAddress2, useLocalhost, 2, true, seedNodeAddresses, new P2PServiceListener() {
|
||||
seedNode2.createAndStartP2PService(nodeAddress2, MAX_CONNECTIONS, useLocalhost, 2, true, seedNodeAddresses, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
latch.countDown();
|
||||
|
@ -456,7 +456,7 @@ public class PeerServiceTest {
|
|||
SeedNode seedNode = new SeedNode("test_dummy_dir");
|
||||
|
||||
latch = new CountDownLatch(1);
|
||||
seedNode.createAndStartP2PService(new NodeAddress("localhost", port), useLocalhost, 2, true, seedNodeAddresses, new P2PServiceListener() {
|
||||
seedNode.createAndStartP2PService(new NodeAddress("localhost", port), MAX_CONNECTIONS, useLocalhost, 2, true, seedNodeAddresses, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
latch.countDown();
|
||||
|
|
|
@ -82,7 +82,7 @@ public class TestUtils {
|
|||
}
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
seedNode.createAndStartP2PService(new NodeAddress("localhost", port), useLocalhost, 2, true,
|
||||
seedNode.createAndStartP2PService(new NodeAddress("localhost", port), SeedNode.MAX_CONNECTIONS_DEFAULT, useLocalhost, 2, true,
|
||||
seedNodes, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.concurrent.CountDownLatch;
|
|||
@Ignore
|
||||
public class PeerManagerTest {
|
||||
private static final Logger log = LoggerFactory.getLogger(PeerManagerTest.class);
|
||||
private static final int MAX_CONNECTIONS = 100;
|
||||
|
||||
final boolean useLocalhost = true;
|
||||
private CountDownLatch latch;
|
||||
|
@ -37,7 +38,6 @@ public class PeerManagerTest {
|
|||
public void setup() throws InterruptedException {
|
||||
LocalhostNetworkNode.setSimulateTorDelayTorNode(50);
|
||||
LocalhostNetworkNode.setSimulateTorDelayHiddenService(8);
|
||||
PeerManager.setMaxConnections(100);
|
||||
|
||||
seedNodes = new HashSet<>();
|
||||
if (useLocalhost) {
|
||||
|
@ -84,7 +84,7 @@ public class PeerManagerTest {
|
|||
seedNodes.add(nodeAddress);
|
||||
seedNode1 = new SeedNode("test_dummy_dir");
|
||||
latch = new CountDownLatch(2);
|
||||
seedNode1.createAndStartP2PService(nodeAddress, useLocalhost, 2, true,
|
||||
seedNode1.createAndStartP2PService(nodeAddress, MAX_CONNECTIONS, useLocalhost, 2, true,
|
||||
seedNodes, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
|
@ -136,7 +136,7 @@ public class PeerManagerTest {
|
|||
latch = new CountDownLatch(6);
|
||||
|
||||
seedNode1 = new SeedNode("test_dummy_dir");
|
||||
seedNode1.createAndStartP2PService(nodeAddress1, useLocalhost, 2, true, seedNodes, new P2PServiceListener() {
|
||||
seedNode1.createAndStartP2PService(nodeAddress1, MAX_CONNECTIONS, useLocalhost, 2, true, seedNodes, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
latch.countDown();
|
||||
|
@ -174,7 +174,7 @@ public class PeerManagerTest {
|
|||
Thread.sleep(500);
|
||||
|
||||
seedNode2 = new SeedNode("test_dummy_dir");
|
||||
seedNode2.createAndStartP2PService(nodeAddress2, useLocalhost, 2, true, seedNodes, new P2PServiceListener() {
|
||||
seedNode2.createAndStartP2PService(nodeAddress2, MAX_CONNECTIONS, useLocalhost, 2, true, seedNodes, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
latch.countDown();
|
||||
|
@ -411,7 +411,7 @@ public class PeerManagerTest {
|
|||
SeedNode seedNode = new SeedNode("test_dummy_dir");
|
||||
|
||||
latch = new CountDownLatch(1);
|
||||
seedNode.createAndStartP2PService(new NodeAddress("localhost", port), useLocalhost, 2, true, seedNodes, new P2PServiceListener() {
|
||||
seedNode.createAndStartP2PService(new NodeAddress("localhost", port), MAX_CONNECTIONS, useLocalhost, 2, true, seedNodes, new P2PServiceListener() {
|
||||
@Override
|
||||
public void onRequestingDataCompleted() {
|
||||
latch.countDown();
|
||||
|
|
Loading…
Add table
Reference in a new issue