6.3 KiB
Load Balancer Testing Guide
This guide describes how to test the IPFS service discovery and load balancing system implemented in the DeBros Relay.
Prerequisites
- Node.js and pnpm installed
- DeBros Relay codebase
- Multiple terminal windows
Setting Up the Test Environment
1. Install Dependencies
First, make sure all required dependencies are installed:
pnpm install
2. Start Multiple Nodes
To test load balancing, you need to start multiple relay nodes with different configurations. Open separate terminal windows for each node.
Node 1 (Primary):
FINGERPRINT=node-1 PORT=7777 pnpm run dev
Node 2:
FINGERPRINT=node-2 PORT=6002 pnpm run dev
Node 3:
FINGERPRINT=node-3 PORT=6003 pnpm run dev
3. Verify Node Discovery
After starting the nodes, they should automatically discover each other via IPFS pubsub. Check the logs to verify that the nodes are discovering each other:
[SERVICE-DISCOVERY] New peer discovered: k51qzi5uqu5dl... (node-2)
[IPFS] Connected to peer: k51qzi5uqu5dl...
You should see periodic status reports showing connected peers:
==== DeBros RELAY STATUS REPORT ====
📊 Fingerprint: node-1
📊 Active connections: 3
📊 Current load: 1%
📊 Connected P2P peers: 2
==================================
CONNECTED PEERS:
1. k51qzi5uqu5dl... - Load: 5%
2. k51qzi5uqu5aa... - Load: 15%
==================================
Testing Load Balancing
1. Using HTTP Requests
You can use the provided load-balancer.http
file with tools like Visual Studio Code's REST Client extension or curl to test the API endpoints.
Check Node Info:
GET http://localhost:7777/api/discovery/node-info
Get Optimal Peer:
GET http://localhost:7777/api/discovery/optimal-peer
Get All Peers:
GET http://localhost:7777/api/discovery/peers
Health Check:
GET http://localhost:7777/health
2. Testing Different Load Balancing Strategies
You can test different load balancing strategies by changing the environment variable:
LOAD_BALANCING_STRATEGY=round-robin FINGERPRINT=node-1 PORT=7777 pnpm run dev
Available strategies:
least-loaded
(default): Chooses the node with the lowest loadround-robin
: Cycles through all available nodesrandom
: Randomly selects a node
3. Simulating Load
To properly test load balancing, you need to simulate different loads on the nodes. You can do this by establishing WebSocket connections to different nodes:
Simple WebSocket test script:
// save as test-connections.js
const { io } = require('socket.io-client');
const NUM_CONNECTIONS = 50; // Number of connections to create
const TARGET_PORT = 7777; // Port of the node to connect to
const connections = [];
function connect() {
for (let i = 0; i < NUM_CONNECTIONS; i++) {
const socket = io(`http://localhost:${TARGET_PORT}`, {
auth: {
walletAddress: `0x${i.toString(16).padStart(40, '0')}`,
signature: 'dummy-signature-for-testing',
},
});
socket.on('connect', () => {
console.log(`Connection ${i} established`);
});
connections.push(socket);
}
}
connect();
// Keep the script running
process.stdin.resume();
// Clean up on exit
process.on('SIGINT', () => {
console.log('Closing all connections...');
connections.forEach((socket) => socket.disconnect());
process.exit();
});
Run this script to create connections to one of your nodes:
node test-connections.js
You can modify the script to target different nodes and create varying levels of load.
4. Monitoring Results
As you create connections, each node should update its load metrics and broadcast this information to other nodes via pubsub. You should see log messages indicating updates to the load:
[LOAD-BALANCER] Current load: 30% (300 connections)
Then, when querying the optimal peer endpoint, you should see responses directing clients to the node with the lowest load:
{
"useThisNode": false,
"optimalPeer": {
"peerId": "k51qzi5uqu5dllthquketj8ds6vf0s5kkm7p3ybmzz32vr46tgqcm2sic0pxwk",
"load": 10
},
"message": "Found optimal peer"
}
Integrating with Client Applications
To integrate load balancing with client applications, the client should:
- Initially connect to any known relay node
- Query the
/api/discovery/optimal-peer
endpoint - If
useThisNode
isfalse
, disconnect and connect to the optimal peer - Periodically check for better nodes (every few minutes)
Example Client Integration:
async function connectToOptimalRelay() {
// Start with a known relay
const initialRelay = 'http://localhost:7777';
try {
// Query for optimal peer
const response = await fetch(`${initialRelay}/api/discovery/optimal-peer`);
const data = await response.json();
if (data.useThisNode) {
console.log(`Using initial relay: ${initialRelay}`);
return initialRelay;
} else {
// Convert peer ID to a URL (implementation depends on your setup)
const optimalRelayUrl = peerIdToUrl(data.optimalPeer.peerId);
console.log(`Switching to optimal relay: ${optimalRelayUrl}`);
return optimalRelayUrl;
}
} catch (error) {
console.error('Error finding optimal relay:', error);
return initialRelay; // Fall back to initial relay
}
}
// Connect to the best relay
const relayUrl = await connectToOptimalRelay();
const socket = io(relayUrl, {
auth: {
walletAddress: userWalletAddress,
signature: signature,
},
});
Troubleshooting
Nodes Not Discovering Each Other
- Check that the PubSub service is properly initialized
- Verify that all nodes are using the same service discovery topic
- Check if there are any network restrictions preventing P2P communication
- Try setting explicit bootstrap nodes in the configuration
High CPU/Memory Usage
- Adjust the heartbeat interval to a higher value
- Reduce the verbosity of logging in a production environment
- Consider optimizing the peer discovery mechanism for larger deployments
Load Balancing Not Working as Expected
- Check the logs to see if load metrics are being calculated and broadcasted correctly
- Ensure that the stale peer timeout is set appropriately
- Try different load balancing strategies to see which works best for your use case