Getting Started with NATS CLI


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:
Install our tooling and stand up a NATS server
Pub/Sub messages using Subject based addressing
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.
We’ll expose the default NATS port 4222 and the default monitoring port 8222
Name the NATS server instance with
-n nats1
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!
Subscribe to my newsletter
Read articles from Joshua Steward directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
