github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/docs/v2/plugins/plugins-nats.md (about) 1 --- 2 title: NATS 3 keywords: plugins, nats 4 tags: [plugins, nats] 5 sidebar: home_sidebar 6 permalink: /plugins-nats 7 summary: 8 --- 9 10 This doc looks at micro on nats, an integration of the nats messaging system into the micro toolkit. 11 It includes discussion around service discovery, synchronous and asynchronous communication for microservices. 12 13 ### What is NATS? 14 15 [**NATS**](http://nats.io/) is an open source cloud native messaging system or more simply a message bus. NATS was created by Derek Collison, 16 the founder of [Apcera](https://www.apcera.com/). It originated within VMWare and began life as a ruby based system. 17 It's long since been rewritten in Go and is steadily gaining adoption amongst those looking for a highly scalable and 18 performant messaging system. 19 20 If you want to learn more about NATS itself, visit [nats.io](http://nats.io/) or join the community [here](http://nats.iohttps://slack.m3o.com). 21 22 ### Why NATS? 23 24 Why not NATS? Having worked with many message buses in the past, it was very quickly clear that NATS stood apart. Over the years messaging 25 has been hailed as the saviour of the enterprise, resulting in systems that attempted to be everything to everyone. It led to 26 a lot of false promises, significant feature bloat and high cost technologies that created more problems than they solved. 27 28 NATS, in contrast, takes the approach of being very focused, solving the problems of performance and availability while staying incredibly lean. 29 It speaks of being "always on and available", and using a "fire and forget" messaging pattern. It's simplicity, 30 focus and lightweight characteristics make it a prime candidate for the microservices ecosystem. We believe it will soon become the 31 primary candidate as a transport for communication between services where messaging is concerned. 32 33 What NATS provides: 34 35 - High performance and scalability 36 - High availability 37 - Extremely lightweight 38 - At most once delivery 39 40 What NATS does not provide: 41 42 - Persistence 43 - Transactions 44 - Enhanced delivery modes 45 - Enterprise queueing 46 47 That briefly covers the what's and why's of NATS. So how does it fit in with Micro? Let's discuss. 48 49 ### Micro on NATS 50 51 [**Micro**](https://github.com/tickoalcantara12/micro) is a microservice toolkit built with a pluggable architecture allowing the underlying dependencies to be swapped out with 52 minimal changes. Each interface of the [**Go-Micro**](https://github.com/micro/go-micro) framework provides a building block for microservices; 53 the [registry](https://pkg.go.dev/github.com/micro/go-micro/v2/registry#Registry) 54 for service discovery, [transport](https://pkg.go.dev/github.com/micro/go-micro/v2/transport#Transport) for synchronous communication, 55 [broker](https://pkg.go.dev/github.com/micro/go-micro/v2/broker#Broker) for asynchronous messaging, etc. 56 57 Creating a plugin for each component is as simple as implementing the interface. We'll spend more time detailing 58 how to write plugins in a future blog post. If you want to check out the plugins for NATS or any other systems 59 such as etcd discovery, kafka broker, rabbitmq transport, you can find them here 60 [github.com/micro/go-plugins](https://github.com/micro/go-plugins). 61 62 Micro on NATS is essentially a set of go-micro plugins that can be used to integrate with the NATS messaging system. 63 By providing plugins for the various interfaces of go-micro, we create a number of integration points which allow 64 a choice of architecture patterns. 65 66 In our experience one size does not fit all and the flexibility of Micro on NATS 67 allows you to define the model that works for you and your team. 68 69 Below we'll discuss implementations of the NATS plugins for the transport, broker and registry. 70 71 ### Transport 72 73 <img src="images/nats-req-rsp.png" /> 74 75 The transport is the go-micro interface for synchronous communication. It uses fairly common Socket semantics similar 76 to other Go code with `Listen`, `Dial` and `Accept`. These concepts and patterns are well understood 77 for synchronous communication using tcp, http, etc but it can be somewhat more difficult to adapt to 78 a message bus. A connection is established with the message bus rather than with a service itself. To get around 79 this we use the notion of a pseudo connection with topics and channels. 80 81 Here's how it works. 82 83 A service uses `transport.Listen` to listen for messages. This will create a connection 84 to NATS. When `transport.Accept` is called, a unique topic is created and subscribed to. This unique topic will be 85 used as the service address in the go-micro registry. Every message received will then be used as the basis for a 86 pseudo socket/connection. If an existing connection exists with the same reply address we'll simply put the message 87 in the backlog for that connection. 88 89 A client which wants to communicate with this service will use `transport.Dial` to create a connection to the service. 90 This will connect to NATS, create it's own unique topic and subscribe to it. The topic is used for responses from the 91 service. Anytime a message is sent by the client to the service, it will set the reply address to this topic. 92 93 When either side wants to close the connection, they simply call `transport.Close` which will terminate the 94 connection to NATS. 95 96 <img src="images/nats-transport.png" /> 97 98 <b>Using the transport plugin</b> 99 100 Import the transport plugin 101 102 ``` 103 import _ "github.com/micro/go-plugins/transport/nats" 104 ``` 105 106 Start with the transport flag 107 108 ``` 109 go run main.go --transport=nats --transport_address=127.0.0.1:4222 110 ``` 111 112 Alternatively use the transport directly 113 114 ``` 115 transport := nats.NewTransport() 116 ``` 117 118 <center>...</center> 119 The go-micro transport interface: 120 121 ```go 122 type Transport interface { 123 Dial(addr string, opts ...DialOption) (Client, error) 124 Listen(addr string, opts ...ListenOption) (Listener, error) 125 String() string 126 } 127 ``` 128 129 <a href="https://github.com/micro/go-plugins/tree/master/transport/nats"><i class="fa fa-github fa-2x"></i> Transport</a> 130 131 ### Broker 132 133 <img src="images/nats-pub-sub.png" /> 134 135 The broker is the go-micro interface for asynchronous messaging. It provides a high level generic implementation that applies 136 across most message brokers. NATS, by its very nature, is an asynchronous messaging system, it's made for use as a 137 message broker. There's only one caveat, NATS does not persist messages. While this may not be ideal for some, 138 we still believe NATS can and should be used as a broker with go-micro. Where persistence is not required, it allows 139 for a highly scalable pub sub architecture. 140 141 NATS provides a very straight forward Publish and Subscribe mechanism with the concepts of Topics, Channels, etc. There 142 was no real fancy work required here to make it work. Messages can be published in an asynchronous fire and forget 143 manner. Subscribers using the same channel name form a Queue Group in NATS which will then allow messages to 144 automatically be evenly distributed across the subscribers. 145 146 <img src="images/nats-broker.png" /> 147 148 <b>Using the broker plugin</b> 149 150 Import the broker plugin 151 152 ``` 153 import _ "github.com/micro/go-plugins/broker/nats" 154 ``` 155 156 Start with the broker flag 157 158 ``` 159 go run main.go --broker=nats --broker_address=127.0.0.1:4222 160 ``` 161 162 Alternatively use the broker directly 163 164 ``` 165 broker := nats.NewBroker() 166 ``` 167 168 <center>...</center> 169 The go-micro broker interface: 170 171 ```go 172 type Broker interface { 173 Options() Options 174 Address() string 175 Connect() error 176 Disconnect() error 177 Init(...Option) error 178 Publish(string, *Message, ...PublishOption) error 179 Subscribe(string, Handler, ...SubscribeOption) (Subscriber, error) 180 String() string 181 } 182 ``` 183 <a href="https://github.com/micro/go-plugins/tree/master/broker/nats"><i class="fa fa-github fa-2x"></i> Broker</a> 184 185 ### Registry 186 187 <img src="images/nats-service-discovery.png" /> 188 189 The registry is the go-micro interface for service discovery. You might be thinking. Service discovery using a message bus? 190 Does that even work? Indeed it does and rather well. 191 Many people using a message bus for their transport will avoid using any kind of separate discovery mechanism. 192 This is because the message bus itself can handle routing via topics and channels. Topics defined as 193 service names can be used as the routing key, automatically load balancing between instances of a 194 service that subscribe to the topic. 195 196 Go-micro treats the service discovery and transport mechanisms as two separate concerns. Anytime a client makes 197 a request to another service, beneath the covers, it looks up the service in the registry by name, picks the 198 address of a node and then communicates with it via the transport. 199 200 Usually the most common way of storing service discovery information is via 201 a distributed key-value store like zookeeper, etcd or something similar. As you may have realised, NATS 202 is not a distributed key-value store, so we're going to do something a little different... 203 204 <b>Broadcast queries!</b> 205 206 Broadcast queries are just as you may imagine. Services listen on a particular topic we deem for broadcasting 207 queries. Anyone who wants service discovery information will first create a reply topic which it subscribes to, 208 then make its query on the broadcast topic with their reply address. 209 210 Because we don't actually know how many instances of a service are running or how many 211 responses will be returned, we set an upper bound on the time we're willing to wait for a response. It's a crude 212 mechanism of scatter gather for discovery but because of the scalable and performant nature of NATs, it actually 213 works incredibly well. It also indirectly provides a very simple way of filtering services with higher response 214 times. In the future we'll look to improve the underlying implementation. 215 216 So to sum up how it works: 217 218 1. Create reply topic and subscribe 219 2. Send query on broadcast topic with reply address 220 3. Listen for responses and unsubscribe after a time limit 221 4. Aggregate response and return result 222 223 <img src="images/nats-registry.png" /> 224 225 226 <b>Using the registry plugin</b> 227 228 Import the registry plugin 229 230 ``` 231 import _ "github.com/micro/go-plugins/registry/nats" 232 ``` 233 234 Start with the registry flag 235 236 ``` 237 go run main.go --registry=nats --registry_address=127.0.0.1:4222 238 ``` 239 240 Alternatively use the registry directly 241 242 ``` 243 registry := nats.NewRegistry() 244 ``` 245 246 <center>...</center> 247 The go-micro registry interface: 248 249 ```go 250 type Registry interface { 251 Register(*Service, ...RegisterOption) error 252 Deregister(*Service) error 253 GetService(string) ([]*Service, error) 254 ListServices() ([]*Service, error) 255 Watch() (Watcher, error) 256 String() string 257 } 258 ``` 259 260 <a href="https://github.com/micro/go-plugins/tree/master/registry/nats"><i class="fa fa-github fa-2x"></i> Registry</a> 261 262 ### Scaling Micro on NATS 263 264 In the examples above we're only specifying a single NATS server on localhost but our recommended practice for real world use 265 is to setup a NATS cluster for highly availability and fault tolerance. To learn more about NATs clustering 266 checkout the NATS documentation [here](http://nats.io/documentation/server/gnatsd-cluster/). 267 268 Micro accepts a comma separated list of addresses as the flags mentioned above or optionally the use of environment variables. 269 If you're using the client libraries directly it also allows a variadic 270 set of hosts as an option for initialisation of the registry, transport and broker. 271 272 In terms of architecture in a cloud native world, our past experiences suggest that clusters per AZ or per region are ideal. 273 Most cloud providers have relatively low (3-5ms) latency between AZs which allows for regional clustering without issue. 274 When running a highly available configuration, it's important to ensure that you're system is capable of tolerating an AZ 275 failure and in more mature configurations an entire region failure. We do not recommend 276 clustering across regions. Ideally higher level tools should be used to manage multi-cluster and multi-region systems. 277 278 Micro is an incredibly flexible runtime agnostic microservices system. It's designed to run anywhere and in any configuration. 279 It's view of the world is guided by the service registry. Clusters of services can be localised and namespaced within 280 a pool of machines, AZs or regions based entirely on which registry you provide the service access to. In combination with 281 NATS clustering it allows you to build a highly available architecture to serve your needs. 282 283 <img src="images/region.png" /> 284 285 286 ### Summary 287 288 [**NATS**](http://nats.io/) is a scalable and performant messaging system which we believe fits nicely into 289 the microservice ecosystem. It plays extremely well with Micro and as we've 290 demonstrated can be used as a plugin for the [Registry](https://godoc.org/github.com/micro/go-plugins/registry/nats), 291 [Transport](https://godoc.org/github.com/micro/go-plugins/transport/nats) or [Broker](https://godoc.org/github.com/micro/go-plugins/broker/nats). 292 We've implemented all three to highlight just how flexible NATS can be. 293 294 Micro on NATS is an example of Micro's powerful pluggable architecture. Each of the go-micro packages can be implemented 295 and swapped out with minimal changes. In the future look to see more of examples of Micro on [X]. The next most likely 296 to be Micro on Kubernetes. 297 298 Hopefully this will inspire you to try out Micro on NATS or even write some plugins for other systems and contribute back 299 to the community. 300 301 Find the source for the NATS plugins at [github.com/micro/go-plugins](https://github.com/micro/go-plugins). 302