Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronise a variable between java instance across network

Tags:

I have this assignment in college where they ask us to run a Java app as a socket server with multiple clients. Client sends a string, server returns the string in upper case with a request counter. Quite simple.

Each request made by any given client is counted on the server side and stored in a static variable for each client connection thread. So that each client request increments the counter globally on the server. That's working well.

Now, they ask us to run "backup" instances of that server on different machines on the network so that if the primary stops responding, the client connects to one of the backups. That, I got working. But the counter is obviously reset since it's a different server.

The challenge is that the request counter be the same on the primary and the secondaries so that if the primary responds to 10 requests, goes down, client switch to a backup and makes a request, the backup server responds 11.

Here is what I considered:

  1. if on the same PC, I'd use threads but we're over the network so I believe this will not work.
  2. server sends that counter to the client with the response, which in turn returns it to the server at the next request and so forth. Not very "clean" imo but could work.
  3. Each server talks to each other to sync this counter. However, sockets don't seem to be very efficient to do this, if even possible. RMI seems to be an alternative here but I'd like confirmation before I start learning it.

Any leads or suggestions here? I'm not posting code because I don't need a solution here but if necessary, I can invite to the gihub repo.

EDIT: There is no latency, reliability or similar constraints for this project. There is X number of clients and Y number of servers (single master, multiple failovers). Additional third party infrastructure like a DB isn't an option really but third party Java librairies are welcome. Basically I just run in Eclipse on multiple PCs. This is an introduction assignment to distributed systems, expected done in 2 weeks so I believe "keep it simple" is the key here!

EDIT 2: The number and addresses of backup servers will be passed as arguments to the application so broadcast/discovery isn't necessary. We'll likely cover all those points in a later lab assignment in the semester :)

EDIT 3: From all your great suggestions, I'll try an implementation of some variation of #3 and let you know how it works. I think the issue I have here is to make sure all servers are aware of the others. But like I mentioned, they don't need to discover each other so I'll hard code it for now and revisit in the next assignment! Probably opt for some elected master... :)

like image 368
JulioQc Avatar asked May 15 '17 21:05

JulioQc


2 Answers

If option #2 is allowed, then it is the easiest, however I am not sure how it could work in the face of multiple clients (so it depends on the requirements here).

Is it possible to back the servers by a shared db running on another computer? Ideally perhaps one clustered across multiple machines? Or can you use an event bus or 3rd party libraries / code (shared cache, JMS, or even EJBs)?

If not, then having the servers talk to each other is your best bet. Sockets can work, as could UDP multicast (careful there though, no way to know if a message was missed which is why TCP / sockets are safer). If the nodes are going to talk to each other there are generally a few accepted ways to handle the setup:

  • Master / slaves: Current node is the master and all writes are to it. Slaves connect to the master and receive updates. When the master goes down a new master needs to be elected (see leader election). MongoDB works like this.
  • Everyone to everyone: Every node connects to every other known node. Can get complicated and might not scale well to lots of nodes.
  • Daisy chain: one node connects to the next node, which connects to the next, and so on. I don't believe this is widely used.
  • Ring network: Each node connects to two others in order to form a ring. This is generally superior to daisy chain, but a little bit more complicated to implement.

See here for more examples: https://en.wikipedia.org/wiki/Network_topology

If this was in the real world (i.e. not school), you would use either a shared cache (e.g. ehcache), local caches backed by an event bus (JMS of some sort), or a shared clustered db.


EDIT:

After re-reading your question, it seems you only have a single backup server to worry about, and my guess of the course requirements is that they simply want your backup server to connect to your primary server and also receive the variable count updates. This is completely fine to implement with sockets (it isn't inefficient for a single backup server), and is perhaps the solution they are expecting you to use.

E.g. Backup server connects to primary server and either polls for updates across the held connection or simply listens for updates issued from the primary server.

Key notes: - You might need keep alives to ensure the connection does not get killed. - Make sure to implement re-connection logic if the connection from backup to primary dies.

If this is for a networking course they may be expecting UDP multicast, but that may depend a little bit on the server / network environment.

like image 103
Trevor Freeman Avatar answered Sep 22 '22 10:09

Trevor Freeman


This is a classic distributed systems problem. The right solution is some variation of your option #3, where the different servers communicate with each other.

Where it gets complicated is when you start to introduce latency, downtime, and/or network partitioning between the various servers. Eventually you'll need to arrive at some kind of consensus algorithm. Paxos is a well-known approach to this problem, but there are others; Raft is popular these days as well.

like image 23
Daniel Pryden Avatar answered Sep 23 '22 10:09

Daniel Pryden