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