NetTalk Central

Author Topic: 2,000 Simple-Client - conceptual question  (Read 4645 times)

Wolfgang Orth

  • Sr. Member
  • ****
  • Posts: 251
    • View Profile
    • oData Wolfgang Orth
2,000 Simple-Client - conceptual question
« on: December 29, 2013, 02:27:36 PM »
Hello Bruce and all...

The NetSimple-project I am working on runs well. It is a SimpleServer with quite some SimpleClients, which stay connected permanently.

To keep that connection alive, I set ThisClient.InActiveTimeout = 900,000  (! 900 seconds = 15 minutes) and send a HeartBeat every 5 Minutes.

On the serverside I maintain an InMemory-table with all connented clients, holding IP-Address, SockID, Socket, time of last connect / Heartbeat etc.

Once in a while, the server will send out a message to all connected clients, forcing them to open a window.

I learned now, that this project will have to address 2,000 clients now.

A Windows Server OS should be capable for that amount of parallel connenctions. My concern is the timing of the Heartbeats.

With 2,000 clients sending a Heartbeat every 5 minutes, the server will get an average of 6 requests per second.

That will mean, that in a phase of sending a message to all stations, the IMDD-table will get LOOPed through, SET() NEXT() sending a message, but every 1/6th second the record-buffer will be touched from the incoming Heartbeat. I expect the LOOP to stumble then and not work properly, sending that message to each connected client, because this happens all on the same THREAD.

Making the client to send just a .PING() will not neccessarily keep the connection open, right.It simply says, that the machine that gets sent a PING responding, therefore it is reachable, but it says nothing about any connection.

So...... I thought of changing places.... Not the clients will send heartbeats, but once the server has noted the connection, it will be the server that sends a HeartBeat to all 2,000 stations.

If a proper resonse returns, the clients record in the IMDD-table can be updated.
ELSE
If no response comes back, the client can be purged from the list or maybe gets set to "not connected" inside .ErrorTrap().

That means, I have no permanent chatter on the line, it is reduced to the absolute necessary.

If the client itself does feel disconnected, it will auto-reconnect and listed again.

If clients get (re-)connected during that LOOP of Heartbeat or LOOP of Message, it is a rare occurance and I can maintain a temporary Queue, that can be parsed and integrated into the IMDD-table soon after such a LOOP has been finished.

Does that sound reasonable?

Thanks for any advice,
Wolfgang

Bruce

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 11250
    • View Profile
Re: 2,000 Simple-Client - conceptual question
« Reply #1 on: December 29, 2013, 10:08:22 PM »
Hi Wolfgang,

>> HeartBeat every 5 Minutes.

One obvious optimization here is to do one every 13 minutes or so. That would reduce the load on your server somewhat. You could make this a configurable setting, and experiment a bit to determine how big you can make this.

>> some SimpleClients, which stay connected permanently. ..... I learned now, that this project will have to address 2,000 clients now.

All architectures which _rely_ on a permanent connection are going to suffer some scalability issues. what happens when you discover that 2000 is not the upper-bound? What happens when it becomes 10000 or 100000 or so on? Frankly you can probably cope with 2000, and you don't need to implement scalability until it's necessary, but you should at least have some plan in mind.

>> With 2,000 clients sending a Heartbeat every 5 minutes, the server will get an average of 6 requests per second.

I'm assuming the heartbeat takes minimal effort to process, and reply. So, this number is probably well within what the machine can do. I'm having no trouble here serving 200 requests per second.

>>  I expect the LOOP to stumble then and not work properly, sending that message to each connected client, because this happens all on the same THREAD.

I think you have an inaccurate notion of how a single thread runs. Assuming you are doing a tight-loop through the memory file, sending the command, the loop will not be interrupted by the incoming heart-beats. Code in a single thread runs, as all code runs, from one line to the next. It is not "interrupted".

In other words, incoming heart-beats will accumulate as events in the ACCEPT command. Once your loop has completed, and your app continues to process events, then it will receive, in turn, the waiting heart-beat packets.

Of course it might be better to code the out-going instructions not in a tight loop, but as an event of it's own. In other words when it gets some timer event it sends the next client an instruction. It does one per event, and so the outgoing instructions will be mixed in nicely with the incoming heartbeats. This will scale up much better.

>> Not the clients will send heartbeats, but once the server has noted the connection, it will be the server that sends a HeartBeat to all 2,000 stations.

this is another approach that would probably work well. You are already working though the list sending an instruction - you could send a heartbeat in place of an instruction as you work through the list. the only differene is that if the _client_ sends the heartbeat, it will discover it is offline and recreate the connection. If the server sends the hearbeat it will discover the client is offline, but the client won't know to re-initiate the connection.

Frankly I'd probably leave it all alone at the moment. I think you will find your concern over the number of clients is unwarranted. It will continue to "just work".


Cheers
Bruce