What do you use NATS for?
You can use NATS to exchange information with and make requests to other applications. You can also use NATS to make your application into a distributed peer-to-peer application.
At a high level your application can use NATS to:
Send (Publish) information to other applications or instances of your application.
Receive (Subscribe) information (in real-time or whenever your application runs) from other applications or instances of your application.
Make a request to a server or the service provided by another application.
Store shared (consistent) state/data between other applications or instances of your application.
Be informed in real-time about any new data being sent, or any changes to the shared state/data.
Using NATS means that, as an application developer you never have to worry about:
Who sends the information that you want to receive.
Who is interested in the information you are sending to others, or how many are interested or where they are.
Where the service you are sending a request to is located, or how many currently active instances of that service there are.
How many partitions or servers there are in the cluster.
Security (just identify yourself).
Whether your application is up and running at the time the information is sent or not (using JetStream).
Flow control (using JetStream)
Higher qualities of services such as exactly-once (using JetStream)
Fault-tolerance, and which servers are up or down at any given time.
The topology of the NATS server infrastructure or how it is architected.
Anatomy of a NATS Client Application
A NATS Client Application will use the NATS Client Library in the following way:
At initialization time it will first connect (securely if needed) to a NATS Service Infrastructure (i.e. one of the NATS servers).
Once successfully connected the application will:
Create messages and publish them to subjects or streams.
Subscribe to subject(s) or stream consumers to receive messages from other processes.
Publish request messages to a service and receive a reply message.
Receive request messages and send back replies or acknowledgements.
Associate and retrieve messages associated with keys in KV buckets.
Store and retrieve arbitrary large blobs with keys in the object store.
Finally, when the application terminates it should disconnect from the NATS Service Infrastructure.
See the following sections to learn more about those activities.
Connecting and disconnecting
The first thing any application needs to do is connect to NATS. Depending on the way the NATS Service Infrastructure being used is configured the connection may need to be secured, and therefore the application also needs to be able to specify security credentials at connection time. An application can create as many NATS connections as needed (each connection being completely independent, it could for example connect twice as two different users), although typically most applications only make a single NATS connection.
Once you have obtained a valid connection, you can use that connection in your application to use all of the Core NATS functionalities such as subscribing to subjects, publishing messages, making requests (and getting a JetStream context).
Finally, the application will need to disconnect safely from NATS.
Monitoring the NATS connection
Disconnecting safely from NATS
Working with messages
Messages store the data that applications exchange with each other. A message has a subject, a data payload (byte array), and may also have a reply-to and header fields.
You get messages returned or passed to your callbacks from subscribing, or making requests. The publish (and request) operations typically just take a subject and a byte array data payload and create the message for you, but you can also create a message yourself (if you want to set some headers).
Some messages can be 'acknowledged' (for example message received from JetStream pull consumers), and there are multiple forms of acknowledgements (including negative acknowledgements, and acknowledgements indicating that your application has properly received the message but needs more time to process it).
Structured data
Using Core NATS
Once your application has successfully connected to the NATS Server infrastructure, you can then start using the returned connection object to interact with NATS.
Core NATS Publishing
Flush and Ping/Pong
Core NATS Subscribing
The process of subscribing involves having the client library tell the NATS that an application is interested in a particular subject. When an application is done with a subscription it unsubscribes telling the server to stop sending messages.
A client will receive a message for each matching subscription, so if a connection has multiple subscriptions using identical or overlapping subjects (say foo
and >
) the same message will be sent to the client multiple times.
Subscribe as part of a queue group
On a given subject there can be more than one queue group created by subscribing applications, each queue group being an independent queue and distributing its own copy of the messages between the queue group members.
Slow consumers
Unsubscribing
Making requests to services
Servicing and replying to requests
Streaming with JetStream
Streaming functionalities
Temporal decoupling: the ability for a subscribing application to get on demand a replay of the messages stored in the stream due to past (and possibly future) publications.
Queuing: the ability for instances of the subscribing application to get, and safely process and remove (i.e. consume) from the stream individual or batches of messages, effectively using a stream as a distributed work queue.
Defining streams
Before you can use a stream to replay or consume messages published on a subject, it must be defined. The stream definition attributes specify
what is being stored (i.e. which subject(s) the stream monitors)
how it is being stored (e.g. file or memory storage, number of replicas)
how long the messages are stored (e.g. depending on limits, or on interest, or as a work queue): the retention policy
Publishing to streams
Stream consumers
Stream consumers are how application get messages from stream. To make another analogy to database concepts a consumers can be seen as a kind of 'views' (on a stream):
Consumers can have a subject filter to select messages from the stream according to their subject names.
Consumers have an ack policy which defines whether application must acknowledge the reception and processing of the messages being sent to them by the consumers (note that explicit acknowledgements are required for some types of streams and consumer to work properly). As well as how long to wait for acknowledgements for and how many times the consumer should try to re-deliver un-acknowledged messages for.
Consumers have a replay policy to specify the speed at which messages are being replayed at by the consumer.
Consumers also have a small amount of state on the NATS Server to store some message sequence numbers 'cursors'. You can have as many consumers as you need per stream.
Client applications either create ephemeral consumers, or define/find durable consumers. Applications either subscribe to 'push' consumers (consumers defined with a delivery subject and optionally a queue group name for that delivery subject), or fetch on demand (including an optional prefetch) from 'pull' consumers (consumers defined without a delivery subject or queue group name as they don't need any while providing the same functionality).
Ephemeral consumers
Applications typically use ephemeral ordered push consumers to get they own copy of the messages stored in a stream whenever they want.
Durable consumers
Durable consumers are, as the name suggest, meant to be 'always on', and used (shared) by multiple instances of the client application or by applications that get stopped and restarted multiple times and need to maintain state from one run of the application to another.
Durable consumers can be managed administratively using the NATS CLI Tool, or programmatically by the application itself. A consumer is created as a durable consumer simply by specifying a durable name at creation time.
Applications typically use durable pull consumers to distribute and scale horizontally the processing (or consumption) of the messages in a stream.
Consumer acknowledgements
ack()
to positively acknowledge the reception and processing of the messageterm()
to indicate that the message could not be and will never be able to be processed and should not be sent again later. Use term when the request is invalid.nack()
to negatively acknowledge the processing of the message, indicating that the message should be sent again. Use nack when the request is valid but you are unable to process it. If this inability to process happens because of a temporary condition, you should also close your subscription temporarily until you are able to process again.inProgress()
to indicate that the processing of the message is still on-going and more time is needed (before the message is considered for being sent again)
Higher Qualities of Service
Key Value Store
Object Store
NOTICE: Technology Preview
The Object Store is similar to the Key Value Store but meant to be used where the values can be of any arbitrary large size, as opposed to limited to the maximum size of a NATS message, as it the case with the Key Value Store.
Last updated
Was this helpful?