NATS Logo by Example

Simple Leafnode in Topologies

This example showcases the most minimal leafnode configuration and how clients interact.

CLI Go Python JavaScript Rust C# .NET V2 Java Ruby Elixir Crystal C
Jump to the output or the recording
$ nbe run topologies/simple-leafnode/cli
View the source code or learn how to run this example yourself

Code

#!/bin/sh


set -euo pipefail

For this example, we are going to have a service connected to the main server and then another client send a request via a connection to the leaf node.

NATS_MAIN_URL="nats://0.0.0.0:4222"
NATS_LEAF_URL="nats://0.0.0.0:4223"

The nats CLI provides a way to manage different contexts by name. We save two, one for the main server and one for the leaf node. In subsequent calls to nats, we can pass the --context option to refer to either server.

nats context save main \
  --server "$NATS_MAIN_URL" \


nats context save leaf \
  --server "$NATS_LEAF_URL"

Create the most basic server config which enables leaf node connections.

echo 'Creating the main server conf...'
cat <<- EOF > main.conf
port: 4222
leafnodes: {
  port: 7422
}
EOF

The second config is for the leaf node itself. This needs to define the leaf node remotes which is the main server it will be connecting to.

echo 'Creating the leaf node conf...'
cat <<- EOF > leaf.conf
port: 4223
leafnodes: {
  remotes: [
    {url: "nats-leaf://0.0.0.0:7422"}
  ]
}
EOF

Start the main server first.

nats-server -c main.conf 2> /dev/null &
MAIN_PID=$!


sleep 1

Now we can start the leaf node which uses the credentials for the remote connection.

nats-server -c leaf.conf 2> /dev/null &
LEAF_PID=$!


sleep 1

Here we create a simple service which is connected via the main server. We will put this in the background since this will block while serving.

nats --context main reply 'greet' 'hello from main' &
SERVICE_PID=$!

Tiny sleep to ensure the service is connected.

sleep 1

Let’s try out a request that is performed by a client connecting to the leaf node. As expected, this will get routed to the service connected to the main server.

nats --context leaf request 'greet' ''

Let’s start another service connected to the leaf node servicing the same subject.

nats --context leaf reply 'greet' 'hello from leaf' &
SERVICE2_PID=$!

NATS is smart enough to route messages to closest service relative to where the client request comes from.

nats --context leaf request 'greet' ''
nats --context leaf request 'greet' ''
nats --context leaf request 'greet' ''

If we remove the leaf-base service, it will fallback to the main service.

kill $SERVICE2_PID
nats --context leaf request 'greet' ''

Finally stop the service and servers.

kill $SERVICE_PID
kill $LEAF_PID
kill $MAIN_PID

Output

NATS Configuration Context "main"

      Server URLs: nats://0.0.0.0:4222
             Path: /root/.config/nats/context/main.json

NATS Configuration Context "leaf"

      Server URLs: nats://0.0.0.0:4223
             Path: /root/.config/nats/context/leaf.json

Creating the main server conf...
Creating the leaf node conf...
13:39:37 Listening on "greet" in group "NATS-RPLY-22"
13:39:38 Sending request on "greet"


13:39:38 [#0] Received on subject "greet":
hello from main

13:39:38 Received with rtt 310.147µs
13:39:38 Sending request on "greet"
13:39:38 Listening on "greet" in group "NATS-RPLY-22"
13:39:38 [#1] Received on subject "greet":


hello from main

13:39:38 Received with rtt 346.954µs
13:39:39 Sending request on "greet"
13:39:39 [#0] Received on subject "greet":


hello from leaf

13:39:39 Received with rtt 253.344µs
13:39:39 Sending request on "greet"


13:39:39 [#1] Received on subject "greet":
13:39:39 Received with rtt 208.806µs
hello from leaf

13:39:39 Sending request on "greet"
13:39:39 [#2] Received on subject "greet":


hello from main

13:39:39 Received with rtt 334.981µs

Recording

Note, playback is half speed to make it a bit easier to follow.