86
1.1 Simple and Scalable Microservices NATS and the Docker tooling + Waldemar Quevedo / @wallyqs Docker SF Meetup, Oct 2016

NATS + Docker meetup talk Oct - 2016

  • Upload
    wallyqs

  • View
    448

  • Download
    5

Embed Size (px)

Citation preview

Page 1: NATS + Docker meetup talk Oct - 2016

1 . 1

Simple and ScalableMicroservices

NATS and the Docker tooling

+

Waldemar Quevedo / @wallyqs

Docker SF Meetup, Oct 2016

Page 2: NATS + Docker meetup talk Oct - 2016

1 . 1

2 . 1

ABOUTWaldemar Quevedo / So�ware Developer at in SF

Development of the Apcera PlatformPast: PaaS DevOps at Rakuten in TokyoNATS client maintainer (Ruby, Python)

@wallyqsApcera

Page 3: NATS + Docker meetup talk Oct - 2016

3 . 1

ABOUT THIS TALKWhat is NATSFeatures from NATSNATS + Docker �

Page 4: NATS + Docker meetup talk Oct - 2016

4 . 1

What is NATS?

Page 5: NATS + Docker meetup talk Oct - 2016

4 . 2

Page 6: NATS + Docker meetup talk Oct - 2016

4 . 3

NATSHigh Performance Messaging SystemCreated by First written in in 2010

Originally built for Cloud FoundryRewritten in in 2012

Better performanceOpen Source, MIT License

Used by Apcera, Ericsson, HTC, GE, Baidu

Derek CollisonRuby

Go

https://github.com/nats-io

Page 7: NATS + Docker meetup talk Oct - 2016

4 . 4

NATSDesign constrained to keep it as operationally simple andreliable as possible while still being both performant andscalable.

Page 8: NATS + Docker meetup talk Oct - 2016

4 . 5

Acts as an always available dial-tone

Page 9: NATS + Docker meetup talk Oct - 2016

4 . 6

It's Fast

Page 10: NATS + Docker meetup talk Oct - 2016

4 . 7

single byte message

Around 10M messages/second

Page 11: NATS + Docker meetup talk Oct - 2016

4 . 7

4 . 8

and Simple

Page 12: NATS + Docker meetup talk Oct - 2016

4 . 9

DESIGNConcise feature set (pure PubSub!)No built-in persistence of messagesNo exactly-once-delivery promises eitherThose concerns are simplified away from NATS

→ NATS Streaming

Page 13: NATS + Docker meetup talk Oct - 2016

4 . 10

DESIGNTCP/IP basedPlain text protocolfire and forgetat most once

Page 14: NATS + Docker meetup talk Oct - 2016

4 . 11

Very simple protocol

telnet demo.nats.io 4222

sub hello 1+OKpub hello 5world+OKMSG hello 1 5worldpingPONG

nats.io/documentation/nats-protocol

Page 15: NATS + Docker meetup talk Oct - 2016

4 . 12

Demo

Page 16: NATS + Docker meetup talk Oct - 2016

4 . 13

Clients

Page 17: NATS + Docker meetup talk Oct - 2016

4 . 14

GOnc, err := nats.Connect()// ...nc.Subscribe("hello", func(m *nats.Msg){ fmt.Printf("[Received] %s", m.Data)})nc.Publish("hello", []byte("world"))

Page 18: NATS + Docker meetup talk Oct - 2016

4 . 15

RUBYrequire 'nats/client'

NATS.start do |nc| nc.subscribe("hello") do |msg| puts "[Received] #{msg}" end

nc.publish("hello", "world")end

Page 19: NATS + Docker meetup talk Oct - 2016

4 . 16

PYTHON (ASYNCIO)yield from nc.connect()

@asyncio.coroutinedef handler(msg): print("[Received] {data}".format( data=msg.data.decode()))

# Coroutine based subscriberyield from nc.subscribe("foo", cb=handler)yield from nc.publish("foo", "bar")

Page 20: NATS + Docker meetup talk Oct - 2016

4 . 17

NODE.JSvar nats = require('nats').connect();

// Simple Publishernats.publish('foo', 'Hello World!');

// Simple Subscribernats.subscribe('foo', function(msg) { console.log('[Received] ' + msg);});

Page 21: NATS + Docker meetup talk Oct - 2016

4 . 18

CnatsConnection_Publish(nc,"foo",data,5);natsConnection_Subscribe(&sub,nc,"foo",onMsg, NULL);

voidonMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure){ printf("[Received] %.*s\n", natsMsg_GetData(msg)); // ...}

Page 22: NATS + Docker meetup talk Oct - 2016

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); } }

Page 23: NATS + Docker meetup talk Oct - 2016

4 . 20

JAVA// Simple Publishernc.publish("foo", "Hello World".getBytes());

// Simple Async Subscribernc.subscribe("foo", m -> { System.out.println("[Received] %s\n", new String(m.getData()));});

Page 24: NATS + Docker meetup talk Oct - 2016

4 . 21

Many more available!

C C# Java

Python NGINX Go

Node.js Elixir Ruby

PHP Erlang Rust

Haskell Scala Perl

( italics → community contributed)

Page 25: NATS + Docker meetup talk Oct - 2016

4 . 21

4 . 22

Great community!

Page 26: NATS + Docker meetup talk Oct - 2016

4 . 23

Growing ecosystem

nats.io/community

Page 27: NATS + Docker meetup talk Oct - 2016

4 . 23

4 . 24

Connectors

Page 28: NATS + Docker meetup talk Oct - 2016

4 . 24

4 . 25

Community contributed dashboards

github.com/cmfatih/natsboard

Page 29: NATS + Docker meetup talk Oct - 2016

4 . 25

4 . 26

Docker Hub activity from NATS users

Page 30: NATS + Docker meetup talk Oct - 2016

4 . 26

4 . 27

Docker Hub activity from NATS users

Page 31: NATS + Docker meetup talk Oct - 2016

4 . 27

4 . 28

Docker Store (Beta)

Page 32: NATS + Docker meetup talk Oct - 2016

4 . 28

5 . 1

NATS Features

Page 33: NATS + Docker meetup talk Oct - 2016

5 . 2

FEATURESPure PubSub based Request/ReplySubject routing with wildcards

AuthorizationDistribution queue groups for balancingCluster mode for HA

Auto discovery of topology/varz style monitoringSecure TLS connections with certificates

Page 34: NATS + Docker meetup talk Oct - 2016

5 . 3

REQUEST/REPLYIt is pure PubSub based using and bysignaling in the subject:

NATS unique identifierslimited interest

SUB _INBOX.y1JxglDi76shQQIhPbTDme 2UNSUB 2 1PUB help _INBOX.y1JxglDi76shQQIhPbTDme 6please

tells the server to unsubscribe from subscription with sid=2a�er getting 1 message before sending a request on thehelp subject.

Page 35: NATS + Docker meetup talk Oct - 2016

5 . 4

REQUEST/REPLYIf another subscriber is connected and interested in thehelp subject, it will then receive a message with that inbox.

SUB help 90

# Message received from serverMSG help 90 _INBOX.y1JxglDi76shQQIhPbTDme 6please

# Use the inbox to reply backPUB _INBOX.y1JxglDi76shQQIhPbTDme 11I can help!

Page 36: NATS + Docker meetup talk Oct - 2016

5 . 5

REQUEST/REPLYFinally, 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!

Page 37: NATS + Docker meetup talk Oct - 2016

5 . 6

REQUEST/REPLYNATS clients libraries have helpers for generating the uniqueinboxes 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 responsemsg, err := nc.Request("help", []byte("please"), t)if err == nil { fmt.Println(string(msg.Data)) // => I can help!}

Page 38: NATS + Docker meetup talk Oct - 2016

REQUEST/REPLY → LOWEST LATENCYResult of publishing a request to all nodes with limitedinterest means we are getting the fastest reply back:

Page 39: NATS + Docker meetup talk Oct - 2016

5 . 7

REQUEST/REPLY → LOWEST LATENCYResult of publishing a request to all nodes with limitedinterest means we are getting the fastest reply back:

Page 40: NATS + Docker meetup talk Oct - 2016

5 . 85 . 9

SUBJECTS ROUTINGWildcards: *

SUB foo.*.bar 90 PUB foo.hello.bar 2hiMSG foo.hello.bar 90 2hi

e.g. subscribe to all requests being made on the demo site:

telnet demo.nats.io 4222INFO {"auth_required":false,"version":"0.9.4",...}

SUB _INBOX.* 99MSG _INBOX.y1JxglDi76shQQIhPbTDme 99 11I can help!

Page 41: NATS + Docker meetup talk Oct - 2016

5 . 10

SUBJECTS ROUTINGFull wildcard: >

SUB hello.> 90PUB hello.world.again 2hiMSG hello.world.again 90 2hi

e.g. subscribe to all subjects and see whole traffic goingthrough the server:

telnet demo.nats.io 4222INFO {"auth_required":false,"version":"0.9.4",...}

sub > 1+OK

Page 42: NATS + Docker meetup talk Oct - 2016

5 . 11

DISTRIBUTION QUEUESBalance work among nodes randomly

Page 43: NATS + Docker meetup talk Oct - 2016

5 . 12

DISTRIBUTION QUEUESBalance work among nodes randomly

Page 44: NATS + Docker meetup talk Oct - 2016

5 . 13

DISTRIBUTION QUEUESBalance work among nodes randomly

Page 45: NATS + Docker meetup talk Oct - 2016

5 . 14

DISTRIBUTION QUEUESService A workers subscribe to service.A and createworkers distribution queue group for balancing the work.

nc, _ := nats.Connect(nats.DefaultURL)// SUB service.A workers 1\r\nnc.QueueSubscribe("service.A", "workers", func(m *nats.Msg) { nc.Publish(m.Reply, []byte("hi!")) })

Page 46: NATS + Docker meetup talk Oct - 2016

5 . 15

DISTRIBUTION QUEUESNote: NATS does not assume the audience!

Page 47: NATS + Docker meetup talk Oct - 2016

5 . 16

DISTRIBUTION QUEUESAll interested subscribers receive the message!

Page 48: NATS + Docker meetup talk Oct - 2016

5 . 17

CLUSTERINGAvoid SPOF on NATS by assembling a full mesh cluster

Page 49: NATS + Docker meetup talk Oct - 2016

5 . 18

CLUSTERINGClients reconnect logic is triggered

Page 50: NATS + Docker meetup talk Oct - 2016

5 . 19

CLUSTERINGConnecting 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 hasreceived from a client to all connected servers thatexpressed interest in the message's published subject.A message received from a route will only be distributedto local clients.

Page 51: NATS + Docker meetup talk Oct - 2016

5 . 20

CLUSTERINGReconnect and disconnect handlers can be useful to traceconnection 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: %q\n", nc.LastError()) }),)

Page 52: NATS + Docker meetup talk Oct - 2016

5 . 21

CLUSTER AUTO DISCOVERYSince release, topology can be discovered

dynamically by clients!v0.9.2

Page 53: NATS + Docker meetup talk Oct - 2016

5 . 22

We can start with a single node…

Page 54: NATS + Docker meetup talk Oct - 2016

5 . 22

5 . 23

Then have new nodes join the cluster…

Page 55: NATS + Docker meetup talk Oct - 2016

5 . 23

5 . 24

As new nodes join, server announces INFO to clients.

Page 56: NATS + Docker meetup talk Oct - 2016

5 . 24

5 . 25

Clients auto reconfigure to be aware of new nodes.

Page 57: NATS + Docker meetup talk Oct - 2016

5 . 25

5 . 26

Clients auto reconfigure to be aware of new nodes.

Page 58: NATS + Docker meetup talk Oct - 2016

5 . 26

5 . 27

Now fully connected!

Page 59: NATS + Docker meetup talk Oct - 2016

5 . 27

5 . 28

On failure, clients reconnect to an available node.

Page 60: NATS + Docker meetup talk Oct - 2016

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

Page 61: NATS + Docker meetup talk Oct - 2016

5 . 30

MONITORING: EXAMPLESGathering connections metrics from demo:

curl demo.nats.io:8222/varz | grep connections

Result:

"max_connections": 65536, "connections": 25, "total_connections": 12429,

Page 62: NATS + Docker meetup talk Oct - 2016

5 . 31

MONITORING: EXAMPLESGathering metrics regarding languages used whenconnecting 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",

Page 63: NATS + Docker meetup talk Oct - 2016

5 . 32

MONITORING polls from these endpoints providing a terminal UInats-top

Page 64: NATS + Docker meetup talk Oct - 2016

5 . 33

TLSSupported for client and route connections, and formonitoring.

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}

Page 65: NATS + Docker meetup talk Oct - 2016

5 . 34

CLUSTER TLSSecuring 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" }}

Page 66: NATS + Docker meetup talk Oct - 2016

5 . 35

SUBJECTS AUTHORIZATIONPubSub on certain subjects can be disallowed in the server'sconfiguration:

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} ]}

Page 67: NATS + Docker meetup talk Oct - 2016

5 . 36

SUBJECTS AUTHORIZATIONClients are not allowed to publish on _SYS (reserved):

PUB _SYS.foo 2hi-ERR 'Permissions Violation for Publish to "_SYS.foo"'

Page 68: NATS + Docker meetup talk Oct - 2016

6 . 1

NATS and the Docker tooling

Page 69: NATS + Docker meetup talk Oct - 2016

6 . 2

THE NATS DOCKER IMAGESmall binary → Lightweight Docker image

No deployment dependencies

Page 70: NATS + Docker meetup talk Oct - 2016

6 . 3

2-STEP BUILD PROCESS

Page 71: NATS + Docker meetup talk Oct - 2016

6 . 4

FIRST STEP: COMPILE

github.com/nats-io/gnatsd/Dockerfile

FROM golang:1.6.3

MAINTAINER Derek Collison <[email protected]

COPY . /go/src/github.com/nats-io/gnatsdWORKDIR /go/src/github.com/nats-io/gnatsd

RUN CGO_ENABLED=0 go install ...(elided)

EXPOSE 4222 8222ENTRYPOINT ["gnatsd"]CMD ["--help"]

Page 72: NATS + Docker meetup talk Oct - 2016

6 . 5

SECOND STEP: FROM SCRATCH

github.com/nats-io/nats-docker/Dockerfile

FROM scratch

COPY gnatsd /gnatsdCOPY gnatsd.conf /gnatsd.conf

EXPOSE 4222 6222 8222

ENTRYPOINT ["/gnatsd", "-c", "/gnatsd.conf"]CMD []

Page 73: NATS + Docker meetup talk Oct - 2016

6 . 6

THE NATS DOCKER IMAGEBy default it is exposing these ports:

# Clients, Cluster and Monitoring portsEXPOSE 4222 6222 8222

- Clients will be connecting against this port4222

- Port used for the cluster routes6222

- HTTP Monitoring endpoint8222

Page 74: NATS + Docker meetup talk Oct - 2016

6 . 7

USING NATS + DOCKER

Page 75: NATS + Docker meetup talk Oct - 2016

6 . 8

All examples can be found at

github.com/wallyqs/nats-docker-examples

Page 76: NATS + Docker meetup talk Oct - 2016

6 . 8

EXAMPLE: SINGLE NODE

API Server which receives HTTP requests and communicatesinternally through NATS to a pool of workers.

Page 77: NATS + Docker meetup talk Oct - 2016

6 . 96 . 10

EXAMPLE: CLUSTERED SETUP

API Server which receives HTTP requests and communicatesinternally through NATS to a pool of workers.

Page 78: NATS + Docker meetup talk Oct - 2016

6 . 11

LOCAL NATS CLUSTER VIA DOCKER COMPOSE

Docker Compose tooling comes in handy here for doingdevelopment as it helps us in assembling NATS clusterslocally.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"

Page 79: NATS + Docker meetup talk Oct - 2016

6 . 12

NATS + Docker Compose Demo

Page 80: NATS + Docker meetup talk Oct - 2016

6 . 12

6 . 13

DOCKER SWARM BASED NATS CLUSTER

Auto discovery becomes helpful in this context, we canassemble 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

Page 81: NATS + Docker meetup talk Oct - 2016

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:6222done

Initial server becomes the seed server, ignoring route to self.

Page 82: NATS + Docker meetup talk Oct - 2016

6 . 15

NATS + Docker Swarm mode Demo

Page 83: NATS + Docker meetup talk Oct - 2016

6 . 15

7 . 1

Summary

Page 84: NATS + Docker meetup talk Oct - 2016

7 . 2

NATS is a simple, fast and reliable solution for the internalcommunication of a distributed system.

Docker flexible tooling is a good complement for buildingNATS based applications.

Page 85: NATS + Docker meetup talk Oct - 2016

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

Page 86: NATS + Docker meetup talk Oct - 2016

8 . 1

THANKS! / github.com/nats-io @nats_io

Play with the demo site!

telnet demo.nats.io 4222