views:

172

answers:

2

Let me first give an example. Imagine you have a single server running a JVM application. This server keeps a collection of N equations, once for each client:

Client #1: 2x 
Client #2: 1 + y 
Client #3: z/4

This server includes an HTTP interface so that random visitors can type https://www.acme.com/client/3 int their browsers and see the latest evaluated result of z/4.

The tricky part is that either the client or the server may change the variable value at any time, informing the other party immediately.

More specifically, Client #3 - a C app - can initially tell the server that z = 20. An hour later that same client informs the server that z = 23. Likewise the server can later inform the client that z = 28.

As caf pointed out in the comments, there can be a race condition when values are changed by the client and server simultaneously. The solution would be for both client and server to send the operation performed in their message, which would need to be executed by the other party. To keep things simple, let's limit the operations to (commutative) addition, allowing us to disregard message ordering. For example, the client seeds the server with z = 20:

server:z=20, client:z=20
  server sends {+3} message (so z=23 locally) & 
  client sends {-2} message (so z=18 locally) at the exact same time
server receives {-2} message at some point, adds to his local copy so z=21
client receives {+3} message at some point, adds to his local copy so z=21

As long as all messages are eventually evaluated by both parties, the correct answer will eventually be given to the users of the client and server since we limited ourselves to commutative operations (addition of 3 and -2). This does mean that both client and server can be returning incorrect answers in the time it takes for messages to be exchanged and processed. While undesirable, I believe this is unavoidable.

Some possible implementations of this idea include:

  • Open an encrypted, always on TCP socket connection for communication
    • Pros: no additional infrastructure needed, client and server know immediately if there is a problem (disconnect) with the other party, fairly straightforward (except the the encryption), native support from both JVM and C platforms
    • Cons: pretty low-level so you end up writing a lot yourself (protocol, delivery verification, retry-on-failure logic), probably have a lot of firewall headaches during client app installation
  • Asynchronous messaging (ex: ActiveMQ)
    • Pros: transactional, both C & Java integration, free up the client and server apps from needing retry logic or delivery verification, pretty straightforward encryption, easy extensibility via message filters/routers/etc
    • Cons: need additional infrastructure (message server) which must never fail,
  • Database or file system as asynchronous integration point
    • Same pros/cons as above but messier
  • RESTful Web Service
    • Pros: simple, possible reuse of the server's existing REST API, SSL figures out the encryption problem for you (maybe use RSA key a la GitHub for authentication?)
    • Cons: Client now needs to run a C HTTP REST server w/SSL, client and server need retry logic. Axis2 has both a Java and C version, but you may be limited to SOAP.

What other techniques should I be evaluating? What real world experiences have you had with these mechanisms? Which do you recommend for this problem and why?

A: 

I would go with the Asynchronous Messaging. TCP socket connections don't work in an enterprise environment, using a database for asynchronous communication is an awful idea and with the RESTful Web Service you will need to implement an awful lot of things yourself.

Perhaps you could use a JEE server that offers messaging capabilities (like Glassfish or JBoss) and implement your Java application there. Chances of the message server failing are likely far less than the chances of your own applications failing (provided that are installed in the same or similar machines).

kgiannakakis
A: 

Rather than each end of the link performing the compute and then sending the instructions to the other end, why not have them both only consume changes from the message source (TCP, ActiveMQ, DB, Whatever).

This simplifies the code of each as changes are always processed the same way - no difference between a local change or remote.

All changes are posted to the queue and all consumers update their local state.

Robert Christie