Getting Started with NATS CLI

Joshua StewardJoshua Steward
5 min read

What is NATS?

The technology landscape is full of message brokers and event/message buses: Kafka, Event Hub, Pulsar, SQS, Google Pub/Sub, and more in no particular order. In this crowded space, NATS stands out as a unique perspective of the connectivity problem space. Beyond simply passing messages around, NATS is oriented toward solving application connectivity from a first principles like foundation.

At first glance, NATS is a message bus, it facilitates location transparent Pub/Sub. But upon that, so much more can be built, and complex, nuanced patterns can be expressed. Basic Fan-Out/In Pub/Sub, Work Queue Distribution, Request/Reply semantics, Weighted & Mapped Routing, etc. Capabilities like this allow us a new way to approach the connectivity problem space. When we might traditionally reach for HTTP REST, or complex load balanced ingress, NATS provides an elegant alternative. And this is just with Core NATS before we dig into JetStream persistence, Key-Value Semantics, Object Storage, NEX Workloads, etc.

Where do we start?

In this introduction we’re going to accomplish three main objectives:

  1. Install our tooling and stand up a NATS server

  2. Pub/Sub messages using Subject based addressing

  3. Execute Request/Reply built on top of Pub/Sub


Tooling

NATS CLI

First, install the NATS CLI tool, this is the unified tool to interact with the NATS server. From the CLI we can Pub/Sub, Request/Reply, manage Streams, Benchmark, etc. The tool can be installed a variety of ways as documented in the GitHub README and the binaries are available in GitHub Releases. For instance, you can leverage go and install the latest with

go install github.com/nats-io/natscli/nats@latest

Ensure NATS has been added to your $PATH and with the following you should see the latest version you have

nats --version
0.2.2

Conveniently, in addition to the typical -h, --help the CLI gives a selection of “cheat sheets” via nats cheat {cheat}. Looking through these will really help understanding how to work with the tool and what can be done with it.

nats cheat
Available Cheats:
    account
    auth
    bench
    consumer
    contexts
    errors
    events
    kv
    latency
    obj
    pub
    reply
    schemas
    server
    stream
    sub

NATS Server

Next, you’ll need the nats-server, this is the core of it all and a single feature packed binary. The binary itself can be downloaded via NATS.io, alternatively nats-server can be easily spun up in Docker/Podman. Here, I’ll use Docker and we’re going to configure a couple of items.

  1. We’ll expose the default NATS port 4222 and the default monitoring port 8222

  2. Name the NATS server instance with -n nats1

  3. Enable NATS monitoring via -m 8222

docker run --rm --name my-nats -p "4222:4222" -p "8222:8222" nats -n nats1 -m 8222
[1] [INF] Starting nats-server
[1] [INF]   Version:  2.11.1
[1] [INF]   Git:      [d78523b]
[1] [INF]   Name:     nats1
[1] [INF]   ID:       ND6JF5FBLCHPSUBLSAJRLSHWANFQ2D6RJWSK3XJDFBIX5RTE3NQDH5ER
[1] [INF] Starting http monitor on *******:8222
[1] [INF] Listening for client connections on *******:4222
[1] [INF] Server is ready

Pub/Sub - NATS CLI

With our NATS server running, let’s begin with the simplest expression of NATS, Pub/Sub. Open three new terminals, two for subscription and one for publishing.

Next, separately begin two subscriptions with nats sub

nats sub some.subject

Executing this in both subscription terminals should yield some like this

Finally, let’s publish a message with nats pub and see it delivered to both subscribers.

From the NATS Pub terminal execute

nats pub some.subject "Hello World"

Altogether, we should see the message published and received by both subscribers

Adding Headers

Just for fun, let’s add a Header to our message, similar to HTTP Headers, these are Key/Value pairs that support multiple values. These can be used to pass metadata, or as we get more advanced can enable deduplication, optimistic concurrency, etc.

Execute the following nats pub command, passing a generic Content-Type header

nats pub some.subject --header "Content-Type:text/plain" "Hello World"

Altogether we should see the new output

Using Queue Groups

Previously, the published message was delivered to all subscribers, i.e. if we had 100 subscribers, every one would receive the message. However, sometimes we want to distribute messages to a group of subscribers. This is similar to the concept of a work queue, where each message is handled by one and only one subscriber.

To express this pattern in NATS we use a Queue Group. Defined on the subscription, all subscribers within the same group will share responsibility for a subject. NATS will deliver each message to one subscriber in via a nearly random selection that tends towards an even distribution.

Seeing it action, start two new subscriptions with the following command

nats sub some.subject --queue my_group

Then we can publish again

nats pub some.subject "Hello World"

And in result we should see that only one subscriber received the message

Note though, subscriptions outside the Queue Group and in other groups, are still delivered the message

Request/Reply - NATS CLI

Another common communication pattern is Request/Reply, where we expect a single reply for a given request. While this pattern is engrained within something like an HTTP call, NATS expresses this pattern from the basis of Pub/Sub. A Request is published while a temporary Inbox is formed and subscribed to by the “Requestor”, any subscriber can then Reply to the Request on the provided Inbox subject.

Let’s see it in action! First, open a new terminal and stand up a “Responder” to Requests

nats reply some.subject "Responded @ {{Time}}"

Then, from our NATS Pub terminal issue the Request

nats request some.subject "Hello World"

And we should see the Reply returned back to our requestor as expected

We’ll discuss this deeper when we code a Request/Reply pattern, but this illustrates the basic concept. Also note, that we published on the same Subject as before, our earlier Subscribers still received the new message, although they aren’t going to respond to our Request, still, interest in the Subject is respected and the message delivered.


Wrap Up

In this introduction we got familiar with standing up a NATS Server via Docker. Next, we got acquainted with the NATS CLI and its basic Pub/Sub, Request/Reply capabilities. With just a few commands, a single container, we’re already publishing and subscribing with location transparent and subject aware messaging. Our NATS Server, Publisher, and Subscribers can easily be globally remote from one another, and given access, could just as easily communicate. Clearly, we’re just beginning so stay tuned and we’ll keep exploring.

Have a specific question about NATS? Want a specific topic covered? Drop it in the comments!

0
Subscribe to my newsletter

Read articles from Joshua Steward directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Joshua Steward
Joshua Steward