JSON-accessible store which receives updates via multicast broadcasts.
JavaScript
Switch branches/tags
Nothing to show
Latest commit dadbde7 Sep 8, 2013 @skx Mention firewalls.
Permalink
Failed to load latest commit information.
README.md
client.js
mstore.js
mstore.json.example

README.md

Multicast Store

There are many situations where you want to have a central source of server-names, etc, which can be queried from any host within a cluster.

The central source should be easy to query, and very reliable. It must also allow you to send updates to it, such that when a client queries updates are "instant".

mstore is a simple JSON HTTP-server which will export a collection of data to clients, and can be updated easily via UDP-multicast packets.

You can trivially run the daemon on many hosts, and updates will propagate to all running mstore instances within your VLAN.

Simple Use Case

Imagine you have a cluster which has four webservers and two memcached servers.

You could hard-wire the list of memcached servers on your web nodes, but what if you wanted to add a new one? Or if one failed? Instead you should prefer to find the names of your servers dynamically from a central service registry.

With a running mstore instance upon your VLAN you can poll it for the list of Database hosts, memcache hosts, and other configuration values.

Whenever you need to make changes you can do so by sending out the appropriate "update" messages.

Simple Recipe

You want to store the IP of your main database server.

On one host run:

 node mstore.js

You can then visit the following URL which will show only the single result _mtime, the time of the last modification of the hosted-data. (Or the server start time.)

 http://localhost:9615/

On the same host or a completely unrelated host within the same VLAN run:

 node client.js "set db:db1.example.com"

Now reload your URL and you'll see the JSON data has been updated to include the value you set:

 $ curl http://localhost:9615/
 {"db":"db1.example.com","_mtime":1378532324}}

The UDP-listener accepts several commands at the moment:

  • set key:val
    • Sets the value of the key named key to be value.
  • delete key
    • Deletes the specified key.
  • seta key:val1,val2,val3,...,valN
    • Set the value of the key named key to be the array val1, val2 .. valN.
  • aadd key:value
    • Add the value value to the array key, creating that array if necessary.
  • adel key:value
    • Remove the value value from the array key, if it exists.

Any succesful update/delete command will result in the _mtime member being updated automatically. The _mtime member is nothing more than the time of the last update, as measured by seconds since the epoch.

Note: Polling the HTTP interface should be fast partly because the code is small, but also because we support suitable caching headers and the standard E-Tag header.

Advanced/Redundant Usage

Configure all the nodes within your cluster to each run their own instance of mstore. This will allow your code to be consistent and always query the URL http://localhost:9615/.

Running multiple instances like this avoids the single point of failure which is possible if you talk to a single well-known server such as http://mstore.example.com/.

Even with many distinct mstore daemons running upon your VLAN you should expect any "update" messages you send to take effect globally, thanks to the magic of multicast.

Defaults

If the file mstore.json exists it will be read, and the values contained within it will be the defaults for the service - rather than starting with an empty state.

Security

NONE:

  • Any host within your LAN/VLAN can query the store.
    • You can avoid this via a suitable firewall.
  • Any host within your LAN/VLAN can send broadcast packets that result in the update/deletion of your stored data.
    • You can avoid this via a suitable firewall.
  • There is no access control list support, though that could be added if desired.
    • File an issue if you wish it to be added.
    • You can avoid this via a suitable firewall.

Future Plans?

  • More data-types might be useful, but I'd prefer to keep things simple, initially.
  • A sample non-node client might be useful.
  • We could gain consistency by storing all data in a redis database, instead of our internal JSON storage area.
    • This would allow new primitives such as atomic increments/decrements.
    • The downside would be another external dependency.

Alternatives

The most popular alternative to mstore is etcd, which is is a Go-powered server for configuration data. The biggest difference is that etcd uses HTTP-POSTS for updates rather than multicast broadcasts.

etcd also allows explicit server-to-server communication and clustering.

Another alternative system for auto-discover of hostnames/service-hosts is ZeroConf, which is a little more controversial and limited. You can read a little about that on the Debian Wiki.

Steve