uNetworking / uWebSockets

Simple, secure & standards compliant web server for the most demanding of applications
Apache License 2.0
17.24k stars 1.75k forks source link

Is it Hardcoded to have maximum around 1K connections #1198

Closed be-thomas closed 3 years ago

be-thomas commented 3 years ago

I have stress tested it and Results are somewhat good. It is definitely faster than nodeJS (connected in 0-1ms where node taked 2-3 ms). Apart from that NodeJS WS library is able to sustain 20K connections easily. Where uWS is only able to keep 1014 connections open. It seems like some hard-coded limit.

Screenshot_2021-02-17_12-18-03

Also when I press Ctrl+C on Nodejs terminal to stop the client, the uWS server suddenly connects to about 500 more. However, one thing to note is that these same numbers can be seen every time. Its not like in 2nd or third test i get different numbers!, Its always same around 1K connections and then the server stalls FOREVER and then suddenly jumps to 1500 when I stop the nodejs client(1K and 500, every single time).

Screenshot_2021-02-17_12-22-57

This behaviour can be reproduced -

uWS server code -

/* We simply call the root header file "App.h", giving you uWS::App and uWS::SSLApp */
#include "App.h"
#include <iostream>

using namespace std;

/* This is a simple WebSocket echo server example.
 * You may compile it with "WITH_OPENSSL=1 make" or with "make" */

int main() {
    /* ws->getUserData returns one of these */
    struct PerSocketData {
        /* Fill with user data */
        int id;
    };

    int conns = 0;

    /* Keep in mind that uWS::SSLApp({options}) is the same as uWS::App() when compiled without SSL support.
     * You may swap to using uWS:App() if you don't need SSL */
    uWS::App().ws<PerSocketData>("/*", {
        /* Settings */
        .compression = uWS::SHARED_COMPRESSOR,
        .maxPayloadLength = 16 * 1024,
        .idleTimeout = 16,
        .maxBackpressure = 1 * 1024 * 1024,
        .closeOnBackpressureLimit = false,
        .resetIdleTimeoutOnSend = false,
        .sendPingsAutomatically = true,
        /* Handlers */
        .upgrade = nullptr,
        .open = [&conns](auto *ws) {
            /* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
            struct PerSocketData *data = (struct PerSocketData*) ws->getUserData();
            data->id = ++conns;
            cout << "Connected #" << (data->id) << endl;
            /* For Ending Connection - ws->end(); */
        },
        .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
            ws->send(message, opCode, true);
        },
        .drain = [](auto */*ws*/) {
            /* Check ws->getBufferedAmount() here */
        },
        .ping = [](auto */*ws*/) {
            /* Not implemented yet */
        },
        .pong = [](auto */*ws*/) {
            /* Not implemented yet */
        },
        .close = [](auto */*ws*/, int /*code*/, std::string_view /*message*/) {
            /* You may access ws->getUserData() here */
        }
    }).listen(9001, [](auto *listen_socket) {
        if (listen_socket) {
            std::cout << "Listening on port " << 9001 << std::endl;
        }
    }).run();
}

WS client code -

const WebSocket = require('ws');

const host = "127.0.0.1";
const port = 9001;
const count = 20000;
var i=0;

let interval = setInterval(() => {
    if(i == count) {
        clearInterval(interval);
        return;
    }
    const ws = new WebSocket('ws://' + host + ":" + port);
    console.log("Connecting #" + (i+1));
    ws.id = i+1
    ws.start = (new Date()).getTime();

    ws.on('open', function open() {
        ws.end = (new Date()).getTime();
        var diff = ws.end - ws.start
        console.log("Time taken for #" + ws.id + " - " + diff + " ms");
    });

    ws.on('message', function incoming(data) {
        console.log(data);
    });
    ws.on('error', () => {
        console.log("Hung Up - #" + ws.id);
        i--;
    });
    ws.on('close', () => {
        console.log("Closed #" + ws.id);
    })
    i++;
}, 5);

How can I have 20K concurrent connections (which is supported by default on node WS, that too single-threaded).

ghost commented 3 years ago

https://github.com/uNetworking/uWebSockets.js/issues/457