diff --git a/SUMMARY.md b/SUMMARY.md index db15957..06309b4 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -54,6 +54,7 @@ ### NATS Containerization * [NATS.docker](nats_docker/README.md) * [Tutorial](nats_docker/tutorial.md) + * [Docker Swarm](nats_docker/docker_swarm.md) ## NATS Streaming Server * [Basics](nats_streaming/nats-streaming-intro.md) diff --git a/nats_docker/docker_swarm.md b/nats_docker/docker_swarm.md new file mode 100644 index 0000000..cceeff9 --- /dev/null +++ b/nats_docker/docker_swarm.md @@ -0,0 +1,94 @@ + +#### Step 1: +Create an overlay network for the cluster (in this example, `nats-cluster-example`), and instantiate an initial NATS server. + +First create an overlay network: + +```sh +% docker network create --driver overlay nats-cluster-example +``` + +Next instantiate an initial "seed" server for a NATS cluster listening for other servers to join route to it on port 6222: + +```sh +% docker service create --network nats-cluster-example --name nats-cluster-node-1 nats:1.0.0 -cluster nats://0.0.0.0:6222 -DV +``` + +#### Step 2: +The 2nd step is to create another service which connects to the NATS server within the overlay network. Note that we connect to to the server at `nats-cluster-node-1`: + +```sh +% docker service create --name ruby-nats --network nats-cluster-example wallyqs/ruby-nats:ruby-2.3.1-nats-v0.8.0 -e ' + NATS.on_error do |e| + puts "ERROR: #{e}" + end + NATS.start(:servers => ["nats://nats-cluster-node-1:4222"]) do |nc| + inbox = NATS.create_inbox + puts "[#{Time.now}] Connected to NATS at #{nc.connected_server}, inbox: #{inbox}" + + nc.subscribe(inbox) do |msg, reply| + puts "[#{Time.now}] Received reply - #{msg}" + end + + nc.subscribe("hello") do |msg, reply| + next if reply == inbox + puts "[#{Time.now}] Received greeting - #{msg} - #{reply}" + nc.publish(reply, "world") + end + + EM.add_periodic_timer(1) do + puts "[#{Time.now}] Saying hi (servers in pool: #{nc.server_pool}" + nc.publish("hello", "hi", inbox) + end + end' +``` + +#### Step 3: +Now you can add more nodes to the Swarm cluster via more docker services, referencing the seed server in the `-routes` parameter: + +```sh +% docker service create --network nats-cluster-example --name nats-cluster-node-2 nats:1.0.0 -cluster nats://0.0.0.0:6222 -routes nats://nats-cluster-node-1:6222 -DV +``` + +In this case, `nats-cluster-node-1` is seeding the rest of the cluster through the autodiscovery feature. Now NATS servers `nats-cluster-node-1` and `nats-cluster-node-2` are clustered together. + +Add in more replicas of the subscriber: + +```sh +% docker service scale ruby-nats=3 +``` + +Then confirm the distribution on the Docker Swarm cluster: + +```sh +% docker service ps ruby-nats +ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR +25skxso8honyhuznu15e4989m ruby-nats.1 wallyqs/ruby-nats:ruby-2.3.1-nats-v0.8.0 node-1 Running Running 2 minutes ago +0017lut0u3wj153yvp0uxr8yo ruby-nats.2 wallyqs/ruby-nats:ruby-2.3.1-nats-v0.8.0 node-1 Running Running 2 minutes ago +2sxl8rw6vm99x622efbdmkb96 ruby-nats.3 wallyqs/ruby-nats:ruby-2.3.1-nats-v0.8.0 node-2 Running Running 2 minutes ago +``` + +The sample output after adding more NATS server nodes to the cluster, is below - and notice that the client is *dynamically* aware of more nodes being part of the cluster via auto discovery! + +```sh +[2016-08-15 12:51:52 +0000] Saying hi (servers in pool: [{:uri=>#, :was_connected=>true, :reconnect_attempts=>0}] +[2016-08-15 12:51:53 +0000] Saying hi (servers in pool: [{:uri=>#, :was_connected=>true, :reconnect_attempts=>0}] +[2016-08-15 12:51:54 +0000] Saying hi (servers in pool: [{:uri=>#, :was_connected=>true, :reconnect_attempts=>0}] +[2016-08-15 12:51:55 +0000] Saying hi (servers in pool: [{:uri=>#, :was_connected=>true, :reconnect_attempts=>0}, {:uri=>#, :reconnect_attempts=>0}, {:uri=>#, :reconnect_attempts=>0}] +``` + +Sample output after adding more workers which can reply back (since ignoring own responses): + +```sh +[2016-08-15 16:06:26 +0000] Received reply - world +[2016-08-15 16:06:26 +0000] Received reply - world +[2016-08-15 16:06:27 +0000] Received greeting - hi - _INBOX.b8d8c01753d78e562e4dc561f1 +[2016-08-15 16:06:27 +0000] Received greeting - hi - _INBOX.4c35d18701979f8c8ed7e5f6ea +``` + +### And so forth... +From here you can experiment adding to the NATS cluster by simply adding servers with new service names, that route to the seed server `nats-cluster-node-1`. As you've seen above, clients will automatically be updated to know that new servers are available in the cluster. + +```sh +% docker service create --network nats-cluster-example --name nats-cluster-node-3 nats:1.0.0 -cluster nats://0.0.0.0:6222 -routes nats://nats-cluster-node-1:6222 -DV +``` \ No newline at end of file