node/docs/LOAD-BALANCER-TESTING.md
2025-04-06 20:20:28 +03:00

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 load
  • round-robin: Cycles through all available nodes
  • random: 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:

  1. Initially connect to any known relay node
  2. Query the /api/discovery/optimal-peer endpoint
  3. If useThisNode is false, disconnect and connect to the optimal peer
  4. 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

  1. Check that the PubSub service is properly initialized
  2. Verify that all nodes are using the same service discovery topic
  3. Check if there are any network restrictions preventing P2P communication
  4. Try setting explicit bootstrap nodes in the configuration

High CPU/Memory Usage

  1. Adjust the heartbeat interval to a higher value
  2. Reduce the verbosity of logging in a production environment
  3. Consider optimizing the peer discovery mechanism for larger deployments

Load Balancing Not Working as Expected

  1. Check the logs to see if load metrics are being calculated and broadcasted correctly
  2. Ensure that the stale peer timeout is set appropriately
  3. Try different load balancing strategies to see which works best for your use case