Slow RabbitMq Producer (load tests)

Stefanos Kouroupis - Dec 18 '19 - - Dev Community

This article, is nothing more, than a silly way of how to push random rabbitMq messages in a controlled (lol) way in an exchange. Really Useful to simulate a load test.

From this point I am going to refer to RabbitMq, as just rabbit 🐇 and I am going to use a large number of emoji....just because.

Step 1 import all the necessary libraries 📚, which are basically the following two-ish.

  • amqplib - rabbit library and client
  • fs - aka filesystem
import * as amqp from 'amqplib';
import * as fs from 'fs';
Enter fullscreen mode Exit fullscreen mode

Step 2 declare all our configurable values;

const DATA_LENGTH = 100;
const EXCHANGE = "MyExchange";
const ROUTING_KEY = "MyRoutingKey";
const MESSAGE_TYPE = "MyMessageType";
const RABBIT_USERNAME = "MyUsername";
const RABBIT_PASSWORD = "MyPassword";
const RABBIT_HOSTNAME = "localhost";
const RABBIT_PORT = "5672";
const RABBIT_VIRTUAL_HOST= "/";
const DELAY_BETWEEN_MESSAGES= "80";
Enter fullscreen mode Exit fullscreen mode

Step 3 define a model with some initial values (any other way, is way more complicated for such simple example)

class UserModel {
    userId: number = 1;
    fistName: string = "";
    lastName: string = "";
}
Enter fullscreen mode Exit fullscreen mode

Step 4 write a function that gives random values to our model


function generateRandomValue(value: any): any {
    if (typeof (value) == "string") {
        return Math.random().toString(36).substring(7);
    }
    if (typeof (value) == "number") {
        return Math.random();
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 5 (optional) log to a file 🗄️, if you really care about any errors. Logging to console would also work fine, except, sometimes on load tests, you could send million of messages, which could make logging to console a bit of a fuss, 🥁 soooooo I would say we need one.

function log2file(obj: any) {
    fs.appendFile(`./log.txt`, `${JSON.stringify(obj)} 
    `, (err) => {
        if (err) {
            console.log("undefined error");
        }
    });
}
Enter fullscreen mode Exit fullscreen mode

Step 6 send Random object(🥕) to rabbit

function send2Rabbit(channel: any) {
    // GENERATE RANDOM MESSAGE
    const user: any = new UserModel();
    for (var prop in user) {
        if (Object.prototype.hasOwnProperty.call(user, prop)) {
            user[prop] = generateRandomValue((user[prop]) as unknown as any);
        }
    }

    const content = new Buffer(JSON.stringify(user));

    if (channel) {
        try {
            channel.publish(EXCHANGE, ROUTING_KEY, content, {
                type: MESSAGE_TYPE
            });

        } catch (error) {
            log2file(error);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 7 push the power on 🔌 and see the world 🌍 crumble 💥 before your eyes 👀

// IIFE
(async () => {
    try {
        const rabbitConnection = await amqp.connect({
            protocol: 'amqp',
            hostname: RABBIT_HOSTNAME,
            port: RABBIT_PORT,
            username: RABBIT_USERNAME,
            password: RABBIT_PASSWORD,
            vhost: RABBIT_VIRTUAL_HOST,
        });
        const rabbitChannel = await rabbitConnection.createChannel();

        for (let index = 0; index < DATA_LENGTH; index++) {
            send2Rabbit(rabbitChannel)
            await threadSleep(DELAY_BETWEEN_MESSAGES);
        }

    } catch (error) {
        log2file(error);
    }
})();

Enter fullscreen mode Exit fullscreen mode

Step 8 bonus (sleep function 💤)

function threadSleep(ms: any) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . .