NATS WITH GOLANG USING DOCKER
Tags: nats, go, docker
Published: 2022-07-21 09:52:00

# NATS

NATs is an open source, lightweight and high performance native message system developed by go language. It provides an abstraction layer between an application or service and the underlying physical network. The data is encoded and sent as a message by the publisher. Messages are received, decoded, and processed by one or more subscribers.
NATs makes it easy for programs to communicate across different environments, languages, cloud providers, and internal systems

### Advantages

- Ease of use
- Highly performant
- Zero downtime scaling
- Supports edge, cloud or hybrid deployments

#### Install NATS in windows Locally

```
choco install nats-server
```

To start a simple demonstration server locally, simply run:

> nats-server

nats-server -m 8222 (if you want to enable the HTTP monitoring functionality)
You can also test the monitoring endpoint, viewing http://localhost:8222 with a browser.

Installing via Docker

> docker pull nats:latest

To run NATS on docker

> docker run -p 4222:4222 -ti nats:latest

NATS Server Containerization

> docker pull nats
> docker run nats

By default the NATS server exposes multiple ports:
4222 is for clients.
8222 is an HTTP management port for information reporting.
6222 is a routing port for clustering.
Use -p or -P to customize.

Or

> docker run -it nats:alpine sh
> docker run -itd nats:alpine

To run a server with the ports exposed on a docker network:

```
docker network create nats
```

```
docker run --name nats --network nats --rm -p 4222:4222 -p 8222:8222 nats --http_port 8222

or 

docker run --itd --restart always --name nats-alpine --network nats --rm -p 4222:4222 -p 8222:8222 nats:alpine --http_port 8222
```

### NATS CLI

Downloading Release Build

You can find the latest release of nats-server [https://github.com/nats-io/nats-server/releases](here).
You could manually download the zip file matching your systems architecture, and unzip it. You could also use curl to download a specific version

Download this build (https://github.com/nats-io/nats-server/releases) "nats-0.0.33-windows-amd64" from this URL and unzip in you machine and navigating into the given path and run the nats account info command which show the accout information. Run the below commands to perform publish or subscribe the given messages

> nats-server -js
> nats account info

Publish Message

> nats publish hello my-data

Subscribe

> nats subscribe hello

Request-Reply
> nats request hello

Reply
> nats reply hello data

Benchmark

> nats bench --msgs 1000 --pub 2 --sub 2 test

### Subject based Message

Basically, NATs is about publishing and listening to messages. Both depend heavily on the subject of the message. Simply put, subject is a string of characters that publishers and subscribers can use to find each other’s names.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/src9n2r8q6oqfbq11sn9.png)
 
### Publish Subscribe

NATS implements a publish-subscribe message distribution model for one-to-many communication. A publisher sends a message on a subject and any active subscriber listening on that subject receives the message. Subscribers can also register interest in wildcard subjects that work a bit like a regular expression (but only a bit). This one-to-many pattern is sometimes called a fan-out.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aiaw7j0kms3og2yks1de.png)
 
Example

Pub

```
nc, _ := nats.Connect(nats.DefaultURL)
defer nc.Close()

nc.Publish("foo", []byte("Hello World!"))
```

Sub

```
nc, _ := nats.Connect(nats.DefaultURL)
defer nc.Close()

nc.Subscribe("foo", func(m *nats.Msg) {
    fmt.Printf("Received a message: %s\n", string(m.Data))
})
```

### Request Reply

Request response is a common pattern in modern distributed system. When sending a request, the application either waits for a response with a specific timeout or receives the response asynchronously. With the increasing complexity requirements of modern systems, many technologies need additional components to complete the complete feature set.
NATs supports this pattern through its core communication mechanisms (publish and subscribe). The request is published together with the answer topic on a given topic, and the responder listens for the topic and sends the response to the answer topic. The reply topic is usually a topic called “inbox”, which will be dynamically directed back to the requester, regardless of the location of either party.
The ability of NATs even allows multiple responses, the first of which is utilized and the system effectively discards the additional responses. This allows a complex pattern to have multiple responders to reduce response latency and jitter.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5583usftbzrof7btyxy.png)
Go to the /nats-0.0.33-windows-amd64 path and run below commands
```
1.Start the first member of the queue group (In new window)
nats reply hello "service instance A Reply# {{Count}}"

2.Start the second member of the queue group [In new window]
> nats reply hello "service instance B Reply# {{Count}}"

3.Start the thrid member of the queue group [In new window]
> nats reply hello "service instance C Reply# {{Count}}"

4.Publish NATS Message [In new window]
> nats request foo "Simple request"
5.Publish another Message [In new window]
> nats pub foo "Another simple request"
```
You should see that only one of the hello group subscribers receives the message and replies it, and you can also see which one of the available hello subscribers processed the request from the reply message received (i.e. service instance A, B or C)

Example

```
nc, _ := nats.Connect(nats.DefaultURL)
defer nc.Close()

nc.Subscribe("foo", func(m *nats.Msg) {
    nc.Publish(m.Reply, []byte("I will help you"))
})

reply, _ := nc.Request("foo", []byte("help"), 50*time.Millisecond)

fmt.Println(string(reply.Data))
```

### Queue Group

NATs provides a built-in load balancing feature called distributed queues. Using queue subscribers balances messaging between a set of subscribers that can be used to provide application fault tolerance and large-scale workload processing.
To create a queue subscription, you only need the subscriber to register the queue name. All subscribers with the same queue name form a queue group. No configuration is required. When a message is published on a registered topic, a member of the group is randomly selected to receive the message. Although the queue group has multiple subscribers, each message is used by only one subscriber.
An important feature of NATs is that queue groups are defined by the application and its queue subscribers, not on the server configuration.
Queue subscribers are ideal for extended services. Scaling up is as simple as running another application, and scaling down is to terminate the application with a signal that exhausts the running request. This flexibility and lack of any configuration changes make NATs an excellent service communication technology that can work with all platform technologies
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ba0xojiunlg8l4yr6efi.png)
Example:
```
nc, _ := nats.Connect(nats.DefaultURL)
defer nc.Close()

received := 0

nc.QueueSubscribe("foo", "worker_group", func(_ *nats.Msg) {
    received++
})
``` 

### Acknowledgements

In systems with up to one semantics, messages are sometimes lost. If your application is performing a request answer, it should use a timeout to handle any network or application failures. It’s always a good idea to set a timeout on a request and use code that handles the timeout. When publishing an event or data flow, one way to ensure message delivery is to convert it to a request reply with an ACK concept. In NATs, an ACK can be an empty message, a message without a payload
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4j25ze29mfrpwu4vgasf.png)
 
Example:
```
nc, _ := nats.Connect(nats.DefaultURL)
defer nc.Close()
    
nc.Subscribe("foo", func(m *nats.Msg) {
    //nc.Publish(m.Reply, []byte("I will help you"))
    m.Respond([]byte(""))
})
    
reply, _ := nc.Request("foo", []byte("help"), 50*time.Millisecond)
    
fmt.Println("ack:", string(reply.Data))
```

### NATS-TOP

nats-top is a top-like tool for monitoring nats-server servers.
The nats-top tool provides a dynamic real-time view of a NATS server. nats-top can display a variety of system summary information about the NATS server, such as subscription, pending bytes, number of messages, and more, in real time

Installation in GO

```
go install github.com/nats-io/nats-top
```

If you want to start the nats server monitoring enabled we can use the below commands

```
nats-server -m 8222
```

Start Nats-top

```
nats-top
```
### References
- [Reference 1](http://thinkmicroservices.com/blog/2021/nats/nats.html)
- [Reference 2](https://docs.nats.io/)
- [Reference 3](https://developpaper.com/an-introduction-to-the-messaging-model-of-golang-nats/)