Host NATS for message bus
# What is NATS (opens new window) ?
NATS messaging enables the exchange of data that is segmented into messages among computer applications and services. These messages are addressed by subjects and do not depend on network location. This provides an abstraction layer between the application or service and the underlying physical network. Data is encoded and framed as a message and sent by a publisher. The message is received, decoded, and processed by one or more subscribers.
NATS is a lightweight application wrote in golang, it is supposed to be easy to host as well. I've personally used RabbitMQ (opens new window) at work, an alternative of queue systems, however, the maintainability drive me away from it. I've also considered Kafka (opens new window) which is a wide solution with an industrial standard, even it has full support with event store architecture, it is costly somehow, in terms of hosting, understood the architecture and maintain it. To start it simple, I'd like to give NATS a shot.
You might found the intro on how NATS works in its official documentation (opens new window). The first few pages about the concept, publisher and subscriber is super easy to understood for about 3 mins read.
Only one thing to be reminded, NATS follows fire and forgot principle, it doesn't requires a storage for it is messages. If you looking for a message system with persistence messages, NATS may not be a good fit here.
Hence, I'm not going to touch in this article. In the follow parts, I will mainly talk about how to setup NATS and hence how to have it's account management config for production usage.
# How to setup NATS
NATS system composite three components:
Client
- Which the Publisher/Consumer communicating to
Cluster/Server
- By routing other clusters to a main cluster. The message published to client can be consumed by other client instances
Monitor
- A GUI panel with limited view for inspect the activities happen in NATS
- more details (opens new window)
Here is more details about the NATS architecture (opens new window), you may found how NATS stream works as well (this is out of topic for now).
# NATS with docker-compose
You may found instruction here (opens new window), it only allows you to have NATS operating to one machine, but it is a good start for boilerplate NATS
# NATS with K8s
A simple version of NATS running on K8s can be found here (opens new window), it is really just a minimal setup. It is gonna to be a nightmare to maintain vanilla K8s yaml files
# NATS with Helm
A most recommended way
- Helm community (opens new window)
- Good:
- easy to setup
- easy to config
- Missing:
- not able to do accounts management/access control in configmap
- accounts password stay in configmap, which is not able to get encrypted
- Good:
- Official from NATS (opens new window)
- Good:
- accounts management/access control in a secret
- supporting multiple accounts
- Missing:
- no longer actively developing
- not able to work with Helm 3.0
- complex CRD control (probably legacy issue for helm 2.0)
- Good:
# Use NATS
Publisher:
package main
import (
"fmt"
"time"
nats "github.com/nats-io/go-nats"
)
func main() {
// Connect to a server
nc, _ := nats.Connect(nats.DefaultURL)
for {
time.Sleep(3 * time.Second)
msg := fmt.Sprintf("sending the msg out %v", time.Now().Unix())
fmt.Println(msg)
// Simple Publisher
nc.Publish("foo", []byte(msg))
}
// Drain connection (Preferred for responders)
// Close() not needed if this is called.
nc.Drain()
// Close connection
nc.Close()
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Consumer:
package main
import (
"fmt"
nats "github.com/nats-io/go-nats"
)
func main() {
// Connect to a server
nc, _ := nats.Connect(nats.DefaultURL)
// Channel Subscriber
ch := make(chan *nats.Msg, 64)
sub, err := nc.ChanSubscribe("foo", ch)
if err != nil {
fmt.Println(err)
}
for a := range ch {
fmt.Println("------------------")
fmt.Println("a", a)
}
// Drain
sub.Drain()
// Drain connection (Preferred for responders)
// Close() not needed if this is called.
nc.Drain()
// Close connection
nc.Close()
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Conclusion
NATS is really easy to setup and handy to use, as long as it fit in use case, it worth the time to play around with it. Let me try to get some production experience on it first, will get back from it sometime soon.
Worth a look in the future:
- Accounts management (ACL) on with NATS during setup, especially with existing helm charts
- Persistent message queue with NATS Streaming