After I have complained countless times, NATS JetStream
has finally ended its beta phase and entered the RC phase. Finally, I’ve just gotten an official reply that the official version will be released after a few issues are addressed. So on the occasion of this important NATS-Server
feature release, let’s talk about the differences between the NATS product itself and the use of the new features, as well as more potential differences.
Conceptual distinction: NATS-Server / NATS Streaming Server / NATS JetStream
NATS-Server
NATS-Server
(or nats
) is an open source, cloud-native, high-performance messaging system that is the most basic product of NATS. At its core, it is a publish/subscribe (Pub/Sub) system that allows clients to communicate across services in different clusters nats
without having to pay attention to which service a specific message is on. In other words, a client can publish a message on the server side of any cluster, while trying to read it on any cluster client. In the official feature comparison with other similar message queue products, we can also pipe in a list of features of the product. nats
supports multi-stream multi-service for pub/sub
, load balancing, guaranteed message delivery at most/least once, multi-tenancy and user authentication, and other features. Although it seems to have a lot of advantages, the important reason why nats
is not a widely used message queue is that it lacks some of the most important product features for message queues, such as persistence support and guaranteed one-time delivery of messages. This means that after your message is sent, your message is potentially lost during processing and may even be undelivered.
NATS Streaming Server
The NATS Streaming Server
(or stan
) is used to try to solve the existing problems with nats
mentioned above. stan
adds persistence features and message delivery policy support. The nats
server comes with stan
, but nats
and stan
cannot be mixed during use. The relationship between stan
and nats
is described in the official documentation as follows
NATS clients and NATS Streaming Server clients cannot exchange data with each other. That is, if a NATS Streaming Server client publishes a message on foo, a NATS client subscribed on the same topic will not receive the message. NATS Streaming Server messages are NATS messages consisting of protobuf. NATS Streaming Server has to send ACKs to the producer and receive ACKs from the consumer. If messages are freely exchanged with NATS clients, this can cause problems.
The specific architecture of stan
is shown below.
However, although stan
provides persistence and messaging policy support, there were architectural design problems that led to a lot of problems left over from the initial design, such as when you determined that stan
clusters are fixed and cannot be expanded horizontally without limits (#999), like not supporting multi-tenancy (#1122), like clients not being able to actively pull messages and only being pushed etc.
NATS JetStream
NATS JetStream
(or JetStream
) is NATS’ latest architectural design based on the Raft
algorithm to try to solve the above problems. It is different from the original stan
functionality, and provides new persistence features and message delivery policies, as well as support for horizontal scaling. At the same time, the new JetStream
is also optimized for large messages, not as a client of nats
but embedded in NATS Server
as one of the features. In other words, when choosing between these technologies, JetStream
should be the most preferred option. More details can be found in the official guidance document.
NATS JetStream usage
Now that we’ve covered the theory, let’s talk about the actual usage. For now JetStream
is still in RC stage.
Compile and start the client
Download the nats-server
source code, unzip it and execute.
This will start a server that supports JetStream
functionality.
|
|
Writing JetStream DEMO
Next we look at how to use JetStream
for message publishing/subscription functionality.
|
|
In this example, there is a noteworthy feature that needs to be highlighted in addition to the subscribe
message, where we specifically declare the nats.DeliverNew()
option. If not declared, the default is: nats.DeliverAll()
. In addition to these two parameters, there is a nats.DeliverLast()
parameter, which corresponds to each of the 3 ways to start a subscription: the default way nats.DeliverAll()
is to read all messages within the valid lifetime, even those that have already been processed. nats.DeliverLast()
will include the last message in the message queue, even if it has been processed; nats.DeliverNew()
will only process new messages after the subscription.