Thursday 16 March 2017

Apache Reverse Proxy with Node JS and Socket IO spawning lots of httpd_prefork processes

I'm attempting to setup a reverse proxy using Apache for my Node JS app, which uses Socket IO (and is written in Koa v1.x).

This works great if I don't use Socket IO, but when I attempt to add this I am running into big issues with Apache spawning lots of http_prefork processes - to such an extent, that it maxes them out (my config is 150), and Apache just hangs.

My hunch is that Socket IO is keeping the connections open, so when my app gets more than 150 connections, it just breaks - which leaves me to believe I am doing something wrong!

Has anyone else experienced the same issue as me, and if so - is it resolvable, or do I simply up the maximum number of prefork processes indefinitely (feels wrong).

I'd normally use Ngnix for reverse proxy - it seems to play nicer in my experience (and I haven't ran into this issue) - but unfortunately, installing it on the server my app is running on is out of the question.

Here's a part of my apache config:

ProxyRequests        off
ProxyPreserveHost    on
RewriteEngine        on

RewriteCond         %{QUERY_STRING}     transport=polling           [NC]
RewriteRule         /(.*)               http://localhost:5000/$1    [P]
RewriteCond         %{HTTP:Upgrade}     websocket                   [NC]
RewriteRule         /(.*)               ws://localhost:5000/$1      [P]
ProxyPass           /sfd/               http://localhost:5000/
ProxyPassReverse    /sfd/               http://localhost:7540/

# Redirect to fully-qualified domain name for HTTPS
Redirect permanent  /sfd                https://[fqdn]/my-app/

Here's a couple of snippets of my Koa app too and how I use Socket IO.

I've removed some parts to avoid over complicating, but can include more if required.

app.js

'use strict';
const app    = koa();
const server = http.createServer(app.callback()).listen(process.env.PORT || 5000, => {
    console.log('HTTP Server started...');
    const io = require('./io')(server);
});

io.js

module.exports = (server) => {
    const io = require("socket.io")(server);

    // Catch errors
    io.on("error", (err) => {
        console.error(err);
    });

    // On connection
    io.on("connection", (socket) => {

        console.log("[SOCKET IO]: A user has connected with ID:", socket.id);

        // Join a room event with callback emit of 'room-joined'
        socket.on('join-room', (roomName) => {
            console.log(`A user is joining a room with the name ${roomName}`);
            socket.join(roomName);
            socket.emit('room-joined', roomName);
        });

    });



via doublesidedstickytape

No comments:

Post a Comment