Simple and Scalable
Microservices
NATS and the Docker tooling
+
Waldemar Quevedo / @wallyqs
Docker SF Meetup, Oct 2016
1 . 1
2 . 1
ABOUT
Waldemar Quevedo /
So ware Developer at in SF
Development of the Apcera Platform
Past: PaaS DevOps at Rakuten in Tokyo
NATS client maintainer (Ruby, Python)
@wallyqs
Apcera
3 . 1
ABOUT THIS TALK
What is NATS
Features from NATS
NATS + Docker
4 . 1
What is NATS?
4 . 2
4 . 3
NATS
High Performance Messaging System
Created by
First written in in 2010
Originally built for Cloud Foundry
Rewritten in in 2012
Better performance
Open Source, MIT License
Used by Apcera, Ericsson, HTC, GE, Baidu
Derek Collison
Ruby
Go
https://github.com/nats-io
4 . 4
NATS
Design constrained to keep it as operationally simple and
reliable as possible while still being both performant and
scalable.
4 . 5
Acts as an always available dial-tone
4 . 6
It's Fast
single byte message
Around 10M messages/second
4 . 7
4 . 8
and Simple
4 . 9
DESIGN
Concise feature set (pure PubSub!)
No built-in persistence of messages
No exactly-once-delivery promises either
Those concerns are simplified away from NATS
→ NATS Streaming
4 . 10
DESIGN
TCP/IP based
Plain text protocol
fire and forget
at most once
4 . 11
Very simple protocol
telnet demo.nats.io 4222
sub hello 1
+OK
pub hello 5
world
+OK
MSG hello 1 5
world
ping
PONG
nats.io/documentation/nats-protocol
4 . 12
Demo
4 . 13
Clients
4 . 14
GO
nc, err := nats.Connect()
// ...
nc.Subscribe("hello", func(m *nats.Msg){
fmt.Printf("[Received] %s", m.Data)
})
nc.Publish("hello", []byte("world"))
4 . 15
RUBY
require 'nats/client'
NATS.start do |nc|
nc.subscribe("hello") do |msg|
puts "[Received] #{msg}"
end
nc.publish("hello", "world")
end
4 . 16
PYTHON (ASYNCIO)
yield from nc.connect()
@asyncio.coroutine
def handler(msg):
print("[Received] {data}".format(
data=msg.data.decode()))
# Coroutine based subscriber
yield from nc.subscribe("foo", cb=handler)
yield from nc.publish("foo", "bar")
4 . 17
NODE.JS
var nats = require('nats').connect();
// Simple Publisher
nats.publish('foo', 'Hello World!');
// Simple Subscriber
nats.subscribe('foo', function(msg) {
console.log('[Received] ' + msg);
});
4 . 18
C
natsConnection_Publish(nc,"foo",data,5);
natsConnection_Subscribe(&sub,nc,"foo",onMsg, NULL);
void
onMsg(natsConnection *nc, natsSubscription *sub,
natsMsg *msg, void *closure)
{
printf("[Received] %.*sn",
natsMsg_GetData(msg));
// ...
}
4 . 19
C#
using (ISyncSubscription s = c.SubscribeSync("foo"))
{
for (int i = 0; i < 10; i++)
{
Msg m = s.NextMessage();
System.Console.WriteLine("[Received] " + m);
}
}
4 . 20
JAVA
// Simple Publisher
nc.publish("foo", "Hello World".getBytes());
// Simple Async Subscriber
nc.subscribe("foo", m -> {
System.out.println("[Received] %sn",
new String(m.getData()));
});
Many more available!
C C# Java
Python NGINX Go
Node.js Elixir Ruby
PHP Erlang Rust
Haskell Scala Perl
( italics → community contributed)
4 . 21
4 . 22
Great community!
Growing ecosystem
nats.io/community
4 . 23
Connectors
4 . 24
Community contributed dashboards
github.com/cmfatih/natsboard
4 . 25
Docker Hub activity from NATS users
4 . 26
Docker Hub activity from NATS users
4 . 27
Docker Store (Beta)
4 . 28
5 . 1
NATS Features
5 . 2
FEATURES
Pure PubSub based Request/Reply
Subject routing with wildcards
Authorization
Distribution queue groups for balancing
Cluster mode for HA
Auto discovery of topology
/varzstyle monitoring
Secure TLS connections with certificates
5 . 3
REQUEST/REPLY
It is pure PubSub based using and by
signaling in the subject:
NATS unique identifiers
limited interest
SUB _INBOX.y1JxglDi76shQQIhPbTDme 2
UNSUB 2 1
PUB help _INBOX.y1JxglDi76shQQIhPbTDme 6
please
tells the server to unsubscribe from subscription with sid=2
a er getting 1 message before sending a request on the
helpsubject.
5 . 4
REQUEST/REPLY
If another subscriber is connected and interested in the
helpsubject, it will then receive a message with that inbox.
SUB help 90
# Message received from server
MSG help 90 _INBOX.y1JxglDi76shQQIhPbTDme 6
please
# Use the inbox to reply back
PUB _INBOX.y1JxglDi76shQQIhPbTDme 11
I can help!
5 . 5
REQUEST/REPLY
Finally, original requestor will be receiving the message:
SUB _INBOX.y1JxglDi76shQQIhPbTDme 2
UNSUB 2 1
PUB help _INBOX.y1JxglDi76shQQIhPbTDme 6
please
MSG _INBOX.y1JxglDi76shQQIhPbTDme 2 11
I can help!
5 . 6
REQUEST/REPLY
NATS clients libraries have helpers for generating the unique
inboxes which act as ephemeral subscriptions:
nats.NewInbox()
// _INBOX.y1JxglDi76shQQIhPbTDme
Used internally when making a Request:
nc, _ := nats.Connect(nats.DefaultURL)
t := 250*time.Millisecond
// Request sets to AutoUnsubscribe after 1 response
msg, err := nc.Request("help", []byte("please"), t)
if err == nil {
fmt.Println(string(msg.Data))
// => I can help!
}
REQUEST/REPLY → LOWEST LATENCY
Result of publishing a request to all nodes with limited
interest means we are getting the fastest reply back:
5 . 7
REQUEST/REPLY → LOWEST LATENCY
Result of publishing a request to all nodes with limited
interest means we are getting the fastest reply back:
5 . 85 . 9
SUBJECTS ROUTING
Wildcards: *
SUB foo.*.bar 90
PUB foo.hello.bar 2
hi
MSG foo.hello.bar 90 2
hi
e.g. subscribe to all requests being made on the demo site:
telnet demo.nats.io 4222
INFO {"auth_required":false,"version":"0.9.4",...}
SUB _INBOX.* 99
MSG _INBOX.y1JxglDi76shQQIhPbTDme 99 11
I can help!
5 . 10
SUBJECTS ROUTING
Full wildcard: >
SUB hello.> 90
PUB hello.world.again 2
hi
MSG hello.world.again 90 2
hi
e.g. subscribe to all subjects and see whole traffic going
through the server:
telnet demo.nats.io 4222
INFO {"auth_required":false,"version":"0.9.4",...}
sub > 1
+OK
5 . 11
DISTRIBUTION QUEUES
Balance work among nodes randomly
5 . 12
DISTRIBUTION QUEUES
Balance work among nodes randomly
5 . 13
DISTRIBUTION QUEUES
Balance work among nodes randomly
5 . 14
DISTRIBUTION QUEUES
Service A workers subscribe to service.Aand create
workersdistribution queue group for balancing the work.
nc, _ := nats.Connect(nats.DefaultURL)
// SUB service.A workers 1rn
nc.QueueSubscribe("service.A", "workers",
func(m *nats.Msg) {
nc.Publish(m.Reply, []byte("hi!"))
})
5 . 15
DISTRIBUTION QUEUES
Note: NATS does not assume the audience!
5 . 16
DISTRIBUTION QUEUES
All interested subscribers receive the message!
5 . 17
CLUSTERING
Avoid SPOF on NATS by assembling a full mesh cluster
5 . 18
CLUSTERING
Clients reconnect logic is triggered
5 . 19
CLUSTERING
Connecting to a NATS cluster of 2 nodes explicitly
srvs := "nats://10.240.0.1:4222,nats://10.240.0.2:4223"
nc, _ := nats.Connect(srvs)
NOTE: NATS servers have a forwarding limit of one hop.
Each server will only forward a message that it has
received from a client to all connected servers that
expressed interest in the message's published subject.
A message received from a route will only be distributed
to local clients.
5 . 20
CLUSTERING
Reconnect and disconnect handlers can be useful to trace
connection failures.
nc, err := nats.Connect(uri,
nats.DisconnectHandler(func(nc *nats.Conn) {
fmt.Printf("Got disconnected!n")
}),
nats.ReconnectHandler(func(nc *nats.Conn) {
fmt.Printf("Got reconnected to %v!n",
nc.ConnectedUrl())
}),
nats.ClosedHandler(func(nc *nats.Conn) {
fmt.Printf("Connection closed. Reason: %qn",
nc.LastError())
}),
)
5 . 21
CLUSTER AUTO DISCOVERY
Since release, topology can be discovered
dynamically by clients!
v0.9.2
We can start with a single node…
5 . 22
Then have new nodes join the cluster…
5 . 23
As new nodes join, server announces INFOto clients.
5 . 24
Clients auto reconfigure to be aware of new nodes.
5 . 25
Clients auto reconfigure to be aware of new nodes.
5 . 26
Now fully connected!
5 . 27
On failure, clients reconnect to an available node.
5 . 28
5 . 29
MONITORING
style monitoring endpoint available for inspecting the
internal state of the server.
/varz
Other available endpoints:
- Info of clients connected to this server/connz
- Subscriptions metrics/subsz
- Cluster routes/routez
5 . 30
MONITORING: EXAMPLES
Gathering connections metrics from demo:
curl demo.nats.io:8222/varz | grep connections
Result:
"max_connections": 65536,
"connections": 25,
"total_connections": 12429,
5 . 31
MONITORING: EXAMPLES
Gathering metrics regarding languages used when
connecting to demo
curl demo.nats.io:8222/connz?subsz=1 | grep lang | sort | uniq -c
Result:
10 "lang": "go",
7 "lang": "node",
8 "lang": "python2",
5 . 32
MONITORING
polls from these endpoints providing a terminal UInats-top
5 . 33
TLS
Supported for client and route connections, and for
monitoring.
https_port: 6443
tls {
cert_file: "./configs/certs/server-cert.pem"
key_file: "./configs/certs/server-key.pem"
ca_file: "./configs/certs/ca.pem"
# Require client certificates
verify: true
}
5 . 34
CLUSTER TLS
Securing route connections with TLS
cluster {
listen: 0.0.0.0:6222
tls {
# Route cert
cert_file: "./configs/certs/srva-cert.pem"
# Private key
key_file: "./configs/certs/srva-key.pem"
# Optional certificate authority verifying routes
# Required when we have self-signed CA, etc.
ca_file: "./configs/certs/ca.pem"
}
}
5 . 35
SUBJECTS AUTHORIZATION
PubSub on certain subjects can be disallowed in the server's
configuration:
authorization {
admin = { publish = ">", subscribe = ">" }
requestor = {
publish = ["req.foo", "req.bar"]
subscribe = "_INBOX.*"
}
users = [
{user: alice, password: foo, permissions: $admin}
{user: bob, password: bar, permissions: $requestor}
]
}
5 . 36
SUBJECTS AUTHORIZATION
Clients are not allowed to publish on _SYS(reserved):
PUB _SYS.foo 2
hi
-ERR 'Permissions Violation for Publish to "_SYS.foo"'
6 . 1
NATS and the Docker tooling
6 . 2
THE NATS DOCKER IMAGE
Small binary → Lightweight Docker image
No deployment dependencies
6 . 3
2-STEP BUILD PROCESS
6 . 4
FIRST STEP: COMPILE
github.com/nats-io/gnatsd/Dockerfile
FROM golang:1.6.3
MAINTAINER Derek Collison <derek@apcera.com>
COPY . /go/src/github.com/nats-io/gnatsd
WORKDIR /go/src/github.com/nats-io/gnatsd
RUN CGO_ENABLED=0 go install ...(elided)
EXPOSE 4222 8222
ENTRYPOINT ["gnatsd"]
CMD ["--help"]
6 . 5
SECOND STEP: FROM SCRATCH
github.com/nats-io/nats-docker/Dockerfile
FROM scratch
COPY gnatsd /gnatsd
COPY gnatsd.conf /gnatsd.conf
EXPOSE 4222 6222 8222
ENTRYPOINT ["/gnatsd", "-c", "/gnatsd.conf"]
CMD []
6 . 6
THE NATS DOCKER IMAGE
By default it is exposing these ports:
# Clients, Cluster and Monitoring ports
EXPOSE 4222 6222 8222
- Clients will be connecting against this port4222
- Port used for the cluster routes6222
- HTTP Monitoring endpoint8222
6 . 7
USING NATS + DOCKER
All examples can be found at
github.com/wallyqs/nats-docker-examples
6 . 8
EXAMPLE: SINGLE NODE
API Server which receives HTTP requests and communicates
internally through NATS to a pool of workers.
6 . 96 . 10
EXAMPLE: CLUSTERED SETUP
API Server which receives HTTP requests and communicates
internally through NATS to a pool of workers.
6 . 11
LOCAL NATS CLUSTER VIA DOCKER COMPOSE
Docker Compose tooling comes in handy here for doing
development as it helps us in assembling NATS clusters
locally.
version: "2"
networks:
nats-network: {}
services:
nats-server-A:
networks: ["nats-network"]
image: "nats:0.9.4"
entrypoint: "/gnatsd --routes nats://nats-server-B:6222,nats://nats-server-C:6222 --cluster nats://0.0.0.0:6222"
nats-server-B:
networks: ["nats-network"]
image: "nats:0.9.4"
entrypoint: "/gnatsd --routes nats://nats-server-A:6222,nats://nats-server-C:6222 --cluster nats://0.0.0.0:6222"
nats-server-C:
networks: ["nats-network"]
image: "nats:0.9.4"
entrypoint: "/gnatsd --routes nats://nats-server-A:6222,nats://nats-server-B:6222 --cluster nats://0.0.0.0:6222"
NATS + Docker Compose Demo
6 . 12
6 . 13
DOCKER SWARM BASED NATS CLUSTER
Auto discovery becomes helpful in this context, we can
assemble one with the following commands.
docker network create --driver overlay nats-cluster-example
docker service create --network nats-cluster-example --name nats-A 
nats:0.9.4 -cluster nats://0.0.0.0:6222
docker service create --network nats-cluster-example --name nats-B 
nats:0.9.4 -routes nats://nats-A:6222 
-cluster nats://0.0.0.0:6222
docker service create --network nats-cluster-example --name nats-C 
nats:0.9.4 -routes nats://nats-A:6222,nats://nats-B:6222 
-cluster nats://0.0.0.0:6222
6 . 14
DOCKER SWARM BASED NATS CLUSTER
Even easier: just use same configuration in all nodes.
for node in A B C; do
docker service create --network nats-cluster-example 
--name nats-$node nats:0.9.4 
-routes nats://nats-A:6222 
-cluster nats://0.0.0.0:6222
done
Initial server becomes the seed server, ignoring route to self.
NATS + Docker Swarm mode Demo
6 . 15
7 . 1
Summary
NATS is a simple, fast and reliable solution for the internal
communication of a distributed system.
Docker flexible tooling is a good complement for building
NATS based applications.
7 . 2
7 . 3
BONUS: NATS STREAMING
NATS Streaming recently became an official image too!
It is a layer on top of NATS totalling in ~10MB.
Further info: github.com/nats-io/nats-streaming-server
8 . 1
THANKS!
/github.com/nats-io @nats_io
Play with the demo site!
telnet demo.nats.io 4222

NATS + Docker meetup talk Oct - 2016

  • 1.
    Simple and Scalable Microservices NATSand the Docker tooling + Waldemar Quevedo / @wallyqs Docker SF Meetup, Oct 2016
  • 2.
    1 . 1 2. 1 ABOUT Waldemar Quevedo / So ware Developer at in SF Development of the Apcera Platform Past: PaaS DevOps at Rakuten in Tokyo NATS client maintainer (Ruby, Python) @wallyqs Apcera
  • 3.
    3 . 1 ABOUTTHIS TALK What is NATS Features from NATS NATS + Docker
  • 4.
    4 . 1 Whatis NATS?
  • 5.
  • 6.
    4 . 3 NATS HighPerformance Messaging System Created by First written in in 2010 Originally built for Cloud Foundry Rewritten in in 2012 Better performance Open Source, MIT License Used by Apcera, Ericsson, HTC, GE, Baidu Derek Collison Ruby Go https://github.com/nats-io
  • 7.
    4 . 4 NATS Designconstrained to keep it as operationally simple and reliable as possible while still being both performant and scalable.
  • 8.
    4 . 5 Actsas an always available dial-tone
  • 9.
  • 10.
    single byte message Around10M messages/second
  • 11.
    4 . 7 4. 8 and Simple
  • 12.
    4 . 9 DESIGN Concisefeature set (pure PubSub!) No built-in persistence of messages No exactly-once-delivery promises either Those concerns are simplified away from NATS → NATS Streaming
  • 13.
    4 . 10 DESIGN TCP/IPbased Plain text protocol fire and forget at most once
  • 14.
    4 . 11 Verysimple protocol telnet demo.nats.io 4222 sub hello 1 +OK pub hello 5 world +OK MSG hello 1 5 world ping PONG nats.io/documentation/nats-protocol
  • 15.
  • 16.
  • 17.
    4 . 14 GO nc,err := nats.Connect() // ... nc.Subscribe("hello", func(m *nats.Msg){ fmt.Printf("[Received] %s", m.Data) }) nc.Publish("hello", []byte("world"))
  • 18.
    4 . 15 RUBY require'nats/client' NATS.start do |nc| nc.subscribe("hello") do |msg| puts "[Received] #{msg}" end nc.publish("hello", "world") end
  • 19.
    4 . 16 PYTHON(ASYNCIO) yield from nc.connect() @asyncio.coroutine def handler(msg): print("[Received] {data}".format( data=msg.data.decode())) # Coroutine based subscriber yield from nc.subscribe("foo", cb=handler) yield from nc.publish("foo", "bar")
  • 20.
    4 . 17 NODE.JS varnats = require('nats').connect(); // Simple Publisher nats.publish('foo', 'Hello World!'); // Simple Subscriber nats.subscribe('foo', function(msg) { console.log('[Received] ' + msg); });
  • 21.
    4 . 18 C natsConnection_Publish(nc,"foo",data,5); natsConnection_Subscribe(&sub,nc,"foo",onMsg,NULL); void onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure) { printf("[Received] %.*sn", natsMsg_GetData(msg)); // ... }
  • 22.
    4 . 19 C# using(ISyncSubscription s = c.SubscribeSync("foo")) { for (int i = 0; i < 10; i++) { Msg m = s.NextMessage(); System.Console.WriteLine("[Received] " + m); } }
  • 23.
    4 . 20 JAVA //Simple Publisher nc.publish("foo", "Hello World".getBytes()); // Simple Async Subscriber nc.subscribe("foo", m -> { System.out.println("[Received] %sn", new String(m.getData())); });
  • 24.
    Many more available! CC# Java Python NGINX Go Node.js Elixir Ruby PHP Erlang Rust Haskell Scala Perl ( italics → community contributed)
  • 25.
    4 . 21 4. 22 Great community!
  • 26.
  • 27.
  • 28.
    4 . 24 Communitycontributed dashboards github.com/cmfatih/natsboard
  • 29.
    4 . 25 DockerHub activity from NATS users
  • 30.
    4 . 26 DockerHub activity from NATS users
  • 31.
    4 . 27 DockerStore (Beta)
  • 32.
    4 . 28 5. 1 NATS Features
  • 33.
    5 . 2 FEATURES PurePubSub based Request/Reply Subject routing with wildcards Authorization Distribution queue groups for balancing Cluster mode for HA Auto discovery of topology /varzstyle monitoring Secure TLS connections with certificates
  • 34.
    5 . 3 REQUEST/REPLY Itis pure PubSub based using and by signaling in the subject: NATS unique identifiers limited interest SUB _INBOX.y1JxglDi76shQQIhPbTDme 2 UNSUB 2 1 PUB help _INBOX.y1JxglDi76shQQIhPbTDme 6 please tells the server to unsubscribe from subscription with sid=2 a er getting 1 message before sending a request on the helpsubject.
  • 35.
    5 . 4 REQUEST/REPLY Ifanother subscriber is connected and interested in the helpsubject, it will then receive a message with that inbox. SUB help 90 # Message received from server MSG help 90 _INBOX.y1JxglDi76shQQIhPbTDme 6 please # Use the inbox to reply back PUB _INBOX.y1JxglDi76shQQIhPbTDme 11 I can help!
  • 36.
    5 . 5 REQUEST/REPLY Finally,original requestor will be receiving the message: SUB _INBOX.y1JxglDi76shQQIhPbTDme 2 UNSUB 2 1 PUB help _INBOX.y1JxglDi76shQQIhPbTDme 6 please MSG _INBOX.y1JxglDi76shQQIhPbTDme 2 11 I can help!
  • 37.
    5 . 6 REQUEST/REPLY NATSclients libraries have helpers for generating the unique inboxes which act as ephemeral subscriptions: nats.NewInbox() // _INBOX.y1JxglDi76shQQIhPbTDme Used internally when making a Request: nc, _ := nats.Connect(nats.DefaultURL) t := 250*time.Millisecond // Request sets to AutoUnsubscribe after 1 response msg, err := nc.Request("help", []byte("please"), t) if err == nil { fmt.Println(string(msg.Data)) // => I can help! }
  • 38.
    REQUEST/REPLY → LOWESTLATENCY Result of publishing a request to all nodes with limited interest means we are getting the fastest reply back:
  • 39.
    5 . 7 REQUEST/REPLY→ LOWEST LATENCY Result of publishing a request to all nodes with limited interest means we are getting the fastest reply back:
  • 40.
    5 . 85. 9 SUBJECTS ROUTING Wildcards: * SUB foo.*.bar 90 PUB foo.hello.bar 2 hi MSG foo.hello.bar 90 2 hi e.g. subscribe to all requests being made on the demo site: telnet demo.nats.io 4222 INFO {"auth_required":false,"version":"0.9.4",...} SUB _INBOX.* 99 MSG _INBOX.y1JxglDi76shQQIhPbTDme 99 11 I can help!
  • 41.
    5 . 10 SUBJECTSROUTING Full wildcard: > SUB hello.> 90 PUB hello.world.again 2 hi MSG hello.world.again 90 2 hi e.g. subscribe to all subjects and see whole traffic going through the server: telnet demo.nats.io 4222 INFO {"auth_required":false,"version":"0.9.4",...} sub > 1 +OK
  • 42.
    5 . 11 DISTRIBUTIONQUEUES Balance work among nodes randomly
  • 43.
    5 . 12 DISTRIBUTIONQUEUES Balance work among nodes randomly
  • 44.
    5 . 13 DISTRIBUTIONQUEUES Balance work among nodes randomly
  • 45.
    5 . 14 DISTRIBUTIONQUEUES Service A workers subscribe to service.Aand create workersdistribution queue group for balancing the work. nc, _ := nats.Connect(nats.DefaultURL) // SUB service.A workers 1rn nc.QueueSubscribe("service.A", "workers", func(m *nats.Msg) { nc.Publish(m.Reply, []byte("hi!")) })
  • 46.
    5 . 15 DISTRIBUTIONQUEUES Note: NATS does not assume the audience!
  • 47.
    5 . 16 DISTRIBUTIONQUEUES All interested subscribers receive the message!
  • 48.
    5 . 17 CLUSTERING AvoidSPOF on NATS by assembling a full mesh cluster
  • 49.
    5 . 18 CLUSTERING Clientsreconnect logic is triggered
  • 50.
    5 . 19 CLUSTERING Connectingto a NATS cluster of 2 nodes explicitly srvs := "nats://10.240.0.1:4222,nats://10.240.0.2:4223" nc, _ := nats.Connect(srvs) NOTE: NATS servers have a forwarding limit of one hop. Each server will only forward a message that it has received from a client to all connected servers that expressed interest in the message's published subject. A message received from a route will only be distributed to local clients.
  • 51.
    5 . 20 CLUSTERING Reconnectand disconnect handlers can be useful to trace connection failures. nc, err := nats.Connect(uri, nats.DisconnectHandler(func(nc *nats.Conn) { fmt.Printf("Got disconnected!n") }), nats.ReconnectHandler(func(nc *nats.Conn) { fmt.Printf("Got reconnected to %v!n", nc.ConnectedUrl()) }), nats.ClosedHandler(func(nc *nats.Conn) { fmt.Printf("Connection closed. Reason: %qn", nc.LastError()) }), )
  • 52.
    5 . 21 CLUSTERAUTO DISCOVERY Since release, topology can be discovered dynamically by clients! v0.9.2
  • 53.
    We can startwith a single node…
  • 54.
    5 . 22 Thenhave new nodes join the cluster…
  • 55.
    5 . 23 Asnew nodes join, server announces INFOto clients.
  • 56.
    5 . 24 Clientsauto reconfigure to be aware of new nodes.
  • 57.
    5 . 25 Clientsauto reconfigure to be aware of new nodes.
  • 58.
    5 . 26 Nowfully connected!
  • 59.
    5 . 27 Onfailure, clients reconnect to an available node.
  • 60.
    5 . 28 5. 29 MONITORING style monitoring endpoint available for inspecting the internal state of the server. /varz Other available endpoints: - Info of clients connected to this server/connz - Subscriptions metrics/subsz - Cluster routes/routez
  • 61.
    5 . 30 MONITORING:EXAMPLES Gathering connections metrics from demo: curl demo.nats.io:8222/varz | grep connections Result: "max_connections": 65536, "connections": 25, "total_connections": 12429,
  • 62.
    5 . 31 MONITORING:EXAMPLES Gathering metrics regarding languages used when connecting to demo curl demo.nats.io:8222/connz?subsz=1 | grep lang | sort | uniq -c Result: 10 "lang": "go", 7 "lang": "node", 8 "lang": "python2",
  • 63.
    5 . 32 MONITORING pollsfrom these endpoints providing a terminal UInats-top
  • 64.
    5 . 33 TLS Supportedfor client and route connections, and for monitoring. https_port: 6443 tls { cert_file: "./configs/certs/server-cert.pem" key_file: "./configs/certs/server-key.pem" ca_file: "./configs/certs/ca.pem" # Require client certificates verify: true }
  • 65.
    5 . 34 CLUSTERTLS Securing route connections with TLS cluster { listen: 0.0.0.0:6222 tls { # Route cert cert_file: "./configs/certs/srva-cert.pem" # Private key key_file: "./configs/certs/srva-key.pem" # Optional certificate authority verifying routes # Required when we have self-signed CA, etc. ca_file: "./configs/certs/ca.pem" } }
  • 66.
    5 . 35 SUBJECTSAUTHORIZATION PubSub on certain subjects can be disallowed in the server's configuration: authorization { admin = { publish = ">", subscribe = ">" } requestor = { publish = ["req.foo", "req.bar"] subscribe = "_INBOX.*" } users = [ {user: alice, password: foo, permissions: $admin} {user: bob, password: bar, permissions: $requestor} ] }
  • 67.
    5 . 36 SUBJECTSAUTHORIZATION Clients are not allowed to publish on _SYS(reserved): PUB _SYS.foo 2 hi -ERR 'Permissions Violation for Publish to "_SYS.foo"'
  • 68.
    6 . 1 NATSand the Docker tooling
  • 69.
    6 . 2 THENATS DOCKER IMAGE Small binary → Lightweight Docker image No deployment dependencies
  • 70.
    6 . 3 2-STEPBUILD PROCESS
  • 71.
    6 . 4 FIRSTSTEP: COMPILE github.com/nats-io/gnatsd/Dockerfile FROM golang:1.6.3 MAINTAINER Derek Collison <derek@apcera.com> COPY . /go/src/github.com/nats-io/gnatsd WORKDIR /go/src/github.com/nats-io/gnatsd RUN CGO_ENABLED=0 go install ...(elided) EXPOSE 4222 8222 ENTRYPOINT ["gnatsd"] CMD ["--help"]
  • 72.
    6 . 5 SECONDSTEP: FROM SCRATCH github.com/nats-io/nats-docker/Dockerfile FROM scratch COPY gnatsd /gnatsd COPY gnatsd.conf /gnatsd.conf EXPOSE 4222 6222 8222 ENTRYPOINT ["/gnatsd", "-c", "/gnatsd.conf"] CMD []
  • 73.
    6 . 6 THENATS DOCKER IMAGE By default it is exposing these ports: # Clients, Cluster and Monitoring ports EXPOSE 4222 6222 8222 - Clients will be connecting against this port4222 - Port used for the cluster routes6222 - HTTP Monitoring endpoint8222
  • 74.
    6 . 7 USINGNATS + DOCKER
  • 75.
    All examples canbe found at github.com/wallyqs/nats-docker-examples
  • 76.
    6 . 8 EXAMPLE:SINGLE NODE API Server which receives HTTP requests and communicates internally through NATS to a pool of workers.
  • 77.
    6 . 96. 10 EXAMPLE: CLUSTERED SETUP API Server which receives HTTP requests and communicates internally through NATS to a pool of workers.
  • 78.
    6 . 11 LOCALNATS CLUSTER VIA DOCKER COMPOSE Docker Compose tooling comes in handy here for doing development as it helps us in assembling NATS clusters locally. version: "2" networks: nats-network: {} services: nats-server-A: networks: ["nats-network"] image: "nats:0.9.4" entrypoint: "/gnatsd --routes nats://nats-server-B:6222,nats://nats-server-C:6222 --cluster nats://0.0.0.0:6222" nats-server-B: networks: ["nats-network"] image: "nats:0.9.4" entrypoint: "/gnatsd --routes nats://nats-server-A:6222,nats://nats-server-C:6222 --cluster nats://0.0.0.0:6222" nats-server-C: networks: ["nats-network"] image: "nats:0.9.4" entrypoint: "/gnatsd --routes nats://nats-server-A:6222,nats://nats-server-B:6222 --cluster nats://0.0.0.0:6222"
  • 79.
    NATS + DockerCompose Demo
  • 80.
    6 . 12 6. 13 DOCKER SWARM BASED NATS CLUSTER Auto discovery becomes helpful in this context, we can assemble one with the following commands. docker network create --driver overlay nats-cluster-example docker service create --network nats-cluster-example --name nats-A nats:0.9.4 -cluster nats://0.0.0.0:6222 docker service create --network nats-cluster-example --name nats-B nats:0.9.4 -routes nats://nats-A:6222 -cluster nats://0.0.0.0:6222 docker service create --network nats-cluster-example --name nats-C nats:0.9.4 -routes nats://nats-A:6222,nats://nats-B:6222 -cluster nats://0.0.0.0:6222
  • 81.
    6 . 14 DOCKERSWARM BASED NATS CLUSTER Even easier: just use same configuration in all nodes. for node in A B C; do docker service create --network nats-cluster-example --name nats-$node nats:0.9.4 -routes nats://nats-A:6222 -cluster nats://0.0.0.0:6222 done Initial server becomes the seed server, ignoring route to self.
  • 82.
    NATS + DockerSwarm mode Demo
  • 83.
    6 . 15 7. 1 Summary
  • 84.
    NATS is asimple, fast and reliable solution for the internal communication of a distributed system. Docker flexible tooling is a good complement for building NATS based applications.
  • 85.
    7 . 2 7. 3 BONUS: NATS STREAMING NATS Streaming recently became an official image too! It is a layer on top of NATS totalling in ~10MB. Further info: github.com/nats-io/nats-streaming-server
  • 86.
    8 . 1 THANKS! /github.com/nats-io@nats_io Play with the demo site! telnet demo.nats.io 4222