0

This is a TCP server for receiving data from GPS server

const net = require('net');
const lora_packet = require('lora-packet');



const clients = [];


const server = net.createServer(function (socket) {
    socket.name = socket.remoteAddress + ":" + socket.remotePort;
    socket.device = new Device(socket);
    clients.push(socket);
    let bufferString = '';


    socket.on('data', function (data) {
        try {

            const packet = lora_packet.fromWire(data, 'hex');
            const str = packet._packet.PHYPayload.toString('hex');
            let prev = 0, next;
            while ((next = str.indexOf('0d0a', prev)) > -1) {
                bufferString += str.substring(prev, next + 4);
                console.log('got whole message: ' + bufferString);
                //Use the parts variable for futher communication
                socket.device.emit('data',bufferString);
                bufferString = '';
                prev = next + 4;
            }
            bufferString += str.substring(prev);

        } catch (err) {
            console.log("DATA RECEIVING PRODUCED AN ERROR" + err);
        }

    });
    socket.on('end', function () {
        clients.splice(clients.indexOf(socket), 1);
    });





})
// .listen(8080);


process.on('uncaughtException', function (err) {
    console.log('something terrible happened..')
    console.log(err);
})

module.exports = server;

I am using a TCP server to communicate to GPS devices and establish a live-connection with them.

I have a query that how would I load balance a TCP server to avoid a single point of failure? The problem is that when a TCP connection is formed, the data packets aren't delimited automatically and so I parse the whole stream to check "0d0a" delimiter.

const str = packet._packet.PHYPayload.toString('hex');
                let prev = 0, next;
                while ((next = str.indexOf('0d0a', prev)) > -1) {
                    bufferString += str.substring(prev, next + 4);
                    console.log('got whole message: ' + bufferString);
                    //Use the parts variable for futher communication
                    socket.device.emit('data',bufferString);
                    bufferString = '';
                    prev = next + 4;
                }

Shouldn't I make this connection sticky to a particular server instance if I load balance my TCP server because I also store client connections in a local instance?

const clients = [];

Also, as node.js is an application server and not a web server, it's usually recommended that a web server should be used for reverse-proxying but how can I implement Apache or Nginx or HAproxy for that matter to suffice my use case?

If I don't use any front-end web-server, are there any consequences that have to be faced?

  • You only need stickiness if the client disconnects and then reconnects AND there's a reason that the client needs to come back to the same server. There is no ability for a device to change servers within an existing TCP connection so you don't have to worry about data packets on the same TCP connection being sent to different servers. – jfriend00 Feb 04 '18 at 18:15
  • I guess there was a flaw in my understanding, I thought a load balancer might send some packets from a device to one server and other packets to a different server! – Abhishek Yadav Feb 04 '18 at 18:19
  • Also HAproxy might change the IP address of source for the device, can that be handled? – Abhishek Yadav Feb 04 '18 at 18:20
  • A load balancer only balances incoming connections, not packets on an existing connection. One a TCP socket is established, all packets go to the server that it picked for that TCP socket. – jfriend00 Feb 04 '18 at 18:20
  • If the proxy server changes the Source Ip for my server, there might be a problem that I won't get the IP of the device and won't be able to communicate back to the device! – Abhishek Yadav Feb 04 '18 at 18:24
  • Proxies don't change the actual IP of your server. They just route traffic to your server(s). If they ever changed the routing of an existing TCP socket in the middle of its lifetime, nothing on that socket would work any more. That's just not something they do because it breaks everything. – jfriend00 Feb 04 '18 at 18:49
  • Not changing the IP of the server, changing the IP of the device that sends data to the server through the load balancer! And the server sends data back to device directly to device without any load balancer – Abhishek Yadav Feb 04 '18 at 19:00
  • So the server would see the Ip address of the load balancer and not the device! – Abhishek Yadav Feb 04 '18 at 19:02
  • So how can I respond to the device if I don't know the IP of the device? – Abhishek Yadav Feb 04 '18 at 19:02
  • The device connects to your server with a TCP connection, right? You can send data to it on that TCP connection. The load balancer takes care of delivering packets on that TCP connection back to the device. The whole point of the load balancer is that neither end of the TCP connection needs to be aware of it. Both device and server can just behave like they have a direct TCP connection between them. Remember, in the real world, there are often dozens of network devices that your packets go through on the way from device to server or vice versa. That's all transparent to you. – jfriend00 Feb 04 '18 at 19:09
  • That was pretty informative but are we talking about HAProxy or any load balancer in general? Because I guess Nginx and HAproxy might differ in functionality when I use them in TCP mode. – Abhishek Yadav Feb 04 '18 at 19:57
  • I'm not sure what your last comment means. No load balancer sends different packets on the same TCP connection to different hosts. It balances the TCP connection to a particular host and then ALL packets on that TCP connection go to the same host from then on. "Stickiness" is a feature that the "next" TCP connection from the same source will be load balanced to the same destination as the prior TCP connection. Stickiness doesn't have anything to do with packets on an existing TCP connection. This aspect does not matter what load balancer you are using. – jfriend00 Feb 04 '18 at 21:00
  • And HAProxy in TCP mode just means that there's no evaluation of HTTP request path or headers to decide where to load balance it. – jfriend00 Feb 04 '18 at 21:01
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/72701/discussion-between-abhishek-yadav-and-jfriend00). – Abhishek Yadav Feb 05 '18 at 08:55

1 Answers1

0

Use haproxy with mode tcp

It looks like you could balance this traffic. I don't see a reason for stickiness.

kubanczyk
  • 13,502
  • 5
  • 40
  • 55
  • The GPS device sends the data to the server intermittently and also it's a streamlined data, i.e, it does not send all of the information once! That's why I maintain the bufferString variable and keep listening to the data till I encounter a delimiter for a packet! Wouldn't that be affected if the same device is load balanced to the other server? – Abhishek Yadav Feb 04 '18 at 16:18