mirror of
https://github.com/taigrr/nats.docs
synced 2025-01-18 04:03:23 -08:00
GitBook: [master] 326 pages and 16 assets modified
This commit is contained in:
committed by
gitbook-bot
parent
8b7ba5c3bb
commit
fb0d5c8355
14
developing-with-nats/developer.md
Normal file
14
developing-with-nats/developer.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Introduction
|
||||
|
||||
Developing with NATS is a combination of distributed application techniques, common NATS features and library specific syntax. As well as using this book for guidance, some of the libraries contain language-familiar formats of their API. For example, the Go library has godoc, and the Java library has javadoc.
|
||||
|
||||
| Library | Doc Link |
|
||||
| :--- | :--- |
|
||||
| [nats.go](https://github.com/nats-io/nats.go) | [godoc](http://godoc.org/github.com/nats-io/nats.go) |
|
||||
| [nats.java](https://github.com/nats-io/nats.java) | [javadoc](https://javadoc.io/doc/io.nats/jnats) |
|
||||
| [nats.net](https://github.com/nats-io/nats.net) | [doxygen](http://nats-io.github.io/nats.net/) |
|
||||
| [nats.rb](https://github.com/nats-io/nats.rb) | [yard](https://www.rubydoc.info/gems/nats) |
|
||||
| [nats.ts](https://github.com/nats-io/nats.ts) | [ts-doc](https://nats-io.github.io/nats.ts) |
|
||||
|
||||
Not all libraries contain this separate doc, depending on the language community, but be sure to check out the client libraries README for more information.
|
||||
|
||||
8
developing-with-nats/intro-1/README.md
Normal file
8
developing-with-nats/intro-1/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Automatic Reconnections
|
||||
|
||||
Most, if not all, of the client libraries will reconnect to the NATS system if they are disconnected for any reason. The reconnect logic can differ by library, so check your client library's documentation.
|
||||
|
||||
In general, the client will try to connect to all of the servers it knows about, either through the URLs provided in the `connect` call or the URLs provided by the NATS system itself. The NATS system will inform clients of new endpoints that can be used to reconnect. The library may have several options to help control reconnect behavior.
|
||||
|
||||
The list of servers used during reconnect is library dependent, but generally is constructed from connect function/options and the list of servers provided by the NATS system itself. This feature allows NATS applications and the NATS system itself to self heal and reconfigure itself with no additional configuration or intervention.
|
||||
|
||||
14
developing-with-nats/intro-1/buffer.md
Normal file
14
developing-with-nats/intro-1/buffer.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Buffering Messages During Reconnect Attempts
|
||||
|
||||
The NATS client libraries try as much as possible to be fire and forget. One of the features that may be included in the library you are using is the ability to buffer outgoing messages when the connection is down.
|
||||
|
||||
During a short reconnect, these client can allow applications to publish messages that, because the server is offline, will be cached in the client. The library will then send those messages on reconnect. When the maximum reconnect buffer is reached, messages will no longer be publishable by the client.
|
||||
|
||||
Be aware, while the message appears to be sent to the application it is possible that it is never sent because the connection is never remade. Your applications should use patterns like acknowledgements to ensure delivery.
|
||||
|
||||
For clients that support this feature, you are able to configure the size of this buffer with bytes, messages or both.
|
||||
|
||||
!INCLUDE "../../\_examples/reconnect\_5mb.html"
|
||||
|
||||
> _As mentioned throughout this document, each client library may behave slightly differently. Please check the documentation for the library you are using._
|
||||
|
||||
6
developing-with-nats/intro-1/disable.md
Normal file
6
developing-with-nats/intro-1/disable.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Disabling Reconnect
|
||||
|
||||
You can disable automatic reconnect with connection options:
|
||||
|
||||
!INCLUDE "../../\_examples/reconnect\_none.html"
|
||||
|
||||
6
developing-with-nats/intro-1/events.md
Normal file
6
developing-with-nats/intro-1/events.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Listening for Reconnect Events
|
||||
|
||||
Because reconnect is primarily under the covers many libraries provide an event listener you can use to be notified of reconnect events. This event can be especially important for applications sending a lot of messages.
|
||||
|
||||
!INCLUDE "../../\_examples/reconnect\_event.html"
|
||||
|
||||
6
developing-with-nats/intro-1/max.md
Normal file
6
developing-with-nats/intro-1/max.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Set the Number of Reconnect Attempts
|
||||
|
||||
Applications can set the maximum reconnect attempts. Generally, this will limit the actual number of attempts total, but check your library documentation. For example, in Java, if the client knows about 3 servers and the maximum reconnects is set to 2, it will not try all of the servers. On the other hand, if the maximum is set to 6 it will try all of the servers twice before considering the reconnect a failure and closing.
|
||||
|
||||
!INCLUDE "../../\_examples/reconnect\_10x.html"
|
||||
|
||||
8
developing-with-nats/intro-1/random.md
Normal file
8
developing-with-nats/intro-1/random.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Avoiding the Thundering Herd
|
||||
|
||||
When a server goes down, there is a possible anti-pattern called the _Thundering Herd_ where all of the clients try to reconnect immediately, thus creating a denial of service attack. In order to prevent this, most NATS client libraries randomize the servers they attempt to connect to. This setting has no effect if only a single server is used, but in the case of a cluster, randomization, or shuffling, will ensure that no one server bears the brunt of the client reconnect attempts.
|
||||
|
||||
However, if you want to disable the randomization process, so that servers are always checked in the same order, you can do that in most libraries with a connection options:
|
||||
|
||||
!INCLUDE "../../\_examples/reconnect\_no\_random.html"
|
||||
|
||||
6
developing-with-nats/intro-1/wait.md
Normal file
6
developing-with-nats/intro-1/wait.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Pausing Between Reconnect Attempts
|
||||
|
||||
It doesn’t make much sense to try to connect to the same server over and over. To prevent this sort of thrashing, and wasted reconnect attempts, libraries provide a wait setting. This setting will pause the reconnect logic if the same server is being tried multiple times **in a row**. In the previous example, if you have 3 servers and 6 attempts, the Java library would loop over the three servers. If none were connectable, it will then try all three again. However, the Java client doesn’t wait between each attempt, only when trying the same server again, so in that example the library may never wait. If on the other hand, you only provide a single server URL and 6 attempts, the library will wait between each attempt.
|
||||
|
||||
!INCLUDE "../../\_examples/reconnect\_10s.html"
|
||||
|
||||
6
developing-with-nats/intro-2/README.md
Normal file
6
developing-with-nats/intro-2/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Securing Connections
|
||||
|
||||
NATS provides several forms of security, authentication, authorization and isolation. You can turn on authentication which limits access to the NATS system. Accounts allow for isolation of a subject space and groups of applications. Authorization can be used to limit individual users access to specific subjects for publish and subscribe operations. TLS can be used to encrypt all traffic between clients and the NATS system. Finally, TLS can be used to verify client identities using client certificates. By combining all of these methods you can protect access to the system and to all message flows.
|
||||
|
||||
The client doesn't have control over access controls, but clients do provide the configurations required to authenticate with the system, bind to an account, and to require TLS.
|
||||
|
||||
24
developing-with-nats/intro-2/creds.md
Normal file
24
developing-with-nats/intro-2/creds.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Authenticating with a Credentials File
|
||||
|
||||
The 2.0 version of NATS server introduced the idea of JWT-based authentication. Clients interact with this new scheme using a user JWT and the private key from an NKey pair. To help make connecting with a JWT easier, the client libraries support the concept of a credentials file. This file contains both the private key and the JWT and can be generated with the `nsc` tool. The contents will look like the following and should be protected because it contains a private key. This creds file is unused and only for example purposes.
|
||||
|
||||
```text
|
||||
-----BEGIN NATS USER JWT-----
|
||||
eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJUVlNNTEtTWkJBN01VWDNYQUxNUVQzTjRISUw1UkZGQU9YNUtaUFhEU0oyWlAzNkVMNVJBIiwiaWF0IjoxNTU4MDQ1NTYyLCJpc3MiOiJBQlZTQk0zVTQ1REdZRVVFQ0tYUVM3QkVOSFdHN0tGUVVEUlRFSEFKQVNPUlBWV0JaNEhPSUtDSCIsIm5hbWUiOiJvbWVnYSIsInN1YiI6IlVEWEIyVk1MWFBBU0FKN1pEVEtZTlE3UU9DRldTR0I0Rk9NWVFRMjVIUVdTQUY3WlFKRUJTUVNXIiwidHlwZSI6InVzZXIiLCJuYXRzIjp7InB1YiI6e30sInN1YiI6e319fQ.6TQ2ilCDb6m2ZDiJuj_D_OePGXFyN3Ap2DEm3ipcU5AhrWrNvneJryWrpgi_yuVWKo1UoD5s8bxlmwypWVGFAA
|
||||
------END NATS USER JWT------
|
||||
|
||||
************************* IMPORTANT *************************
|
||||
NKEY Seed printed below can be used to sign and prove identity.
|
||||
NKEYs are sensitive and should be treated as secrets.
|
||||
|
||||
-----BEGIN USER NKEY SEED-----
|
||||
SUAOY5JZ2WJKVR4UO2KJ2P3SW6FZFNWEOIMAXF4WZEUNVQXXUOKGM55CYE
|
||||
------END USER NKEY SEED------
|
||||
|
||||
*************************************************************
|
||||
```
|
||||
|
||||
Given a creds file, a client can authenticate as a specific user belonging to a specific account:
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_creds.html"
|
||||
|
||||
8
developing-with-nats/intro-2/nkey.md
Normal file
8
developing-with-nats/intro-2/nkey.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Authenticating with an NKey
|
||||
|
||||
The 2.0 version of NATS server introduces a new challenge response authentication option. This challenge response is based on a wrapper we call NKeys which uses [Ed25519](https://ed25519.cr.yp.to/) signing. The server can use these keys in several ways for authentication. The simplest is for the server to be configured with a list of known public keys and for the clients to respond to the challenge by signing it with its private key. This challenge-response ensures security by ensuring that the client has the private key, but also protects the private key from the server which never has to actually see it.
|
||||
|
||||
Handling challenge response may require more than just a setting in the connection options, depending on the client library.
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_nkey.html"
|
||||
|
||||
24
developing-with-nats/intro-2/tls.md
Normal file
24
developing-with-nats/intro-2/tls.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Encrypting Connections with TLS
|
||||
|
||||
While authentication limits which clients can connect, TLS can be used to check the server’s identity and optionally the client’s identity and will encrypt all traffic between the two. The most secure version of TLS with NATS is to use verified client certificates. In this mode, the client can check that it trusts the certificate sent by NATS system but the individual server will also check that it trusts the certificate sent by the client. From an application's perspective connecting to a server that does not verify client certificates may appear identical. Under the covers, disabling TLS verification removes the server side check on the client’s certificate. When started in TLS mode, a `nats-server` will require all clients to connect with TLS. Moreover, if configured to connect with TLS, client libraries will fail to connect to a server without TLS.
|
||||
|
||||
The [Java examples repository](https://github.com/nats-io/java-nats-examples/tree/master/src/main/resources) contains certificates for starting the server in TLS mode.
|
||||
|
||||
```bash
|
||||
> nats-server -c /src/main/resources/tls.conf
|
||||
or
|
||||
> nats-server -c /src/main/resources/tls_verify.conf
|
||||
```
|
||||
|
||||
## Connecting with TLS
|
||||
|
||||
Connecting to a server with TLS is straightforward. Most clients will automatically use TLS when connected to a NATS system using TLS. Setting up a NATS system to use TLS is primarily an exercise in setting up the certificate and trust managers. Clients may also need additional information, for example:
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_tls.html"
|
||||
|
||||
## Connecting with the TLS Protocol
|
||||
|
||||
Some clients may support the `tls` protocol as well as a manual setting to turn on TLS. However, in that case there is likely some form of default or environmental settings to allow the TLS libraries to find certificate and trust stores.
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_tls\_url.html"
|
||||
|
||||
26
developing-with-nats/intro-2/token.md
Normal file
26
developing-with-nats/intro-2/token.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Authenticating with a Token
|
||||
|
||||
Tokens are basically random strings, much like a password, and can provide a simple authentication mechanism in some situations. However, tokens are only as safe as they are secret so other authentication schemes can provide more security in large installations.
|
||||
|
||||
For this example, start the server using:
|
||||
|
||||
```bash
|
||||
> nats-server --auth mytoken
|
||||
```
|
||||
|
||||
The code uses localhost:4222 so that you can start the server on your machine to try them out.
|
||||
|
||||
## Connecting with a Token
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_token.html"
|
||||
|
||||
## Connecting with a Token in the URL
|
||||
|
||||
Some client libraries will allow you to pass the token as part of the server URL using the form:
|
||||
|
||||
> nats://_token_@server:port
|
||||
|
||||
Again, once you construct this URL you can connect as if this was a normal URL.
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_token\_url.html"
|
||||
|
||||
36
developing-with-nats/intro-2/userpass.md
Normal file
36
developing-with-nats/intro-2/userpass.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Authenticating with a User and Password
|
||||
|
||||
For this example, start the server using:
|
||||
|
||||
```bash
|
||||
> nats-server --user myname --pass password
|
||||
```
|
||||
|
||||
You can encrypt passwords to pass to `nats-server` using a simple tool provided by the server:
|
||||
|
||||
```bash
|
||||
> go run mkpasswd.go -p
|
||||
> password: password
|
||||
> bcrypt hash: $2a$11$1oJy/wZYNTxr9jNwMNwS3eUGhBpHT3On8CL9o7ey89mpgo88VG6ba
|
||||
```
|
||||
|
||||
and use the hashed password in the server config. The client still uses the plain text version.
|
||||
|
||||
The code uses localhost:4222 so that you can start the server on your machine to try them out.
|
||||
|
||||
## Connecting with a User/Password
|
||||
|
||||
When logging in with a password `nats-server` will take either a plain text password or an encrypted password.
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_userpass.html"
|
||||
|
||||
## Connecting with a User/Password in the URL
|
||||
|
||||
Most clients make it easy to pass the user name and password by accepting them in the URL for the server. This standard format is:
|
||||
|
||||
> nats://_user_:_password_@server:port
|
||||
|
||||
Using this format, you can connect to a server using authentication as easily as you connected with a URL:
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_userpass\_url.html"
|
||||
|
||||
10
developing-with-nats/intro-3/README.md
Normal file
10
developing-with-nats/intro-3/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Receiving Messages
|
||||
|
||||
In general, applications can receive messages asynchronously or synchronously. Receiving messages with NATS can be library dependent.
|
||||
|
||||
Some languages, like Go or Java, provide synchronous and asynchronous APIs, while others may only support one type of subscription.
|
||||
|
||||
In all cases, the process of subscribing involves having the client library tell the NATS system that an application is interested in a particular subject.
|
||||
|
||||
Under the covers, the client library will assign a unique id to each subscription. This id is used as a closure when the server sends messages to a specific subscription. Each subscription gets a unique id, so if the same connection is used multiple times for the same subject, the server will send multiple copies of the same message. When an application is done with a subscription it unsubscribes which tells the server to stop sending messages.
|
||||
|
||||
8
developing-with-nats/intro-3/async.md
Normal file
8
developing-with-nats/intro-3/async.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Asynchronous Subscriptions
|
||||
|
||||
Asynchronous subscriptions use callbacks of some form to notify an application when a message arrives. These subscriptions are usually easier to work with, but do represent some form of internal work and resource usage, i.e. threads, by the library. Check your library's documentation for any resource usage associated with asynchronous subscriptions.
|
||||
|
||||
The following example subscribes to the subject `updates` and handles the incoming messages:
|
||||
|
||||
!INCLUDE "../../\_examples/subscribe\_async.html"
|
||||
|
||||
33
developing-with-nats/intro-3/drain.md
Normal file
33
developing-with-nats/intro-3/drain.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Draining Messages Before Disconnect
|
||||
|
||||
A feature recently added across the NATS client libraries is the ability to drain connections or subscriptions. Closing a connection, or unsubscribing from a subscription, are generally considered immediate requests. When you close or unsubscribe the library will halt messages in any pending queue or cache for subscribers. When you drain a subscription or connection, it will process any inflight and cached/pending messages before closing.
|
||||
|
||||
Drain provides clients that use queue subscriptions with a way to bring down applications without losing any messages. A client can bring up a new queue member, drain and shut down the old queue member, all without losing messages sent to the old client. Without drain, there is the possibility of lost messages due to delivery timing.
|
||||
|
||||
The libraries can provide drain on a connection or on a subscriber, or both.
|
||||
|
||||
For a connection the process is essentially:
|
||||
|
||||
1. Drain all subscriptions
|
||||
2. Stop new messages from being published
|
||||
3. Flush any remaining published messages
|
||||
4. Close
|
||||
|
||||
The API for drain can generally be used instead of close:
|
||||
|
||||
As an example of draining a connection:
|
||||
|
||||
!INCLUDE "../../\_examples/drain\_conn.html"
|
||||
|
||||
The mechanics of drain for a subscription are simpler:
|
||||
|
||||
1. Unsubscribe
|
||||
2. Process all cached or inflight messages
|
||||
3. Clean up
|
||||
|
||||
The API for drain can generally be used instead of unsubscribe:
|
||||
|
||||
!INCLUDE "../../\_examples/drain\_sub.html"
|
||||
|
||||
Because draining can involve messages flowing to the server, for a flush and asynchronous message processing, the timeout for drain should generally be higher than the timeout for a simple message request/reply or similar.
|
||||
|
||||
14
developing-with-nats/intro-3/queues.md
Normal file
14
developing-with-nats/intro-3/queues.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Queue Subscriptions
|
||||
|
||||
Subscribing to a queue group is only slightly different than subscribing to a subject alone. The application simply includes a queue name with the subscription. The effect of including the group is fairly major, since the server will now load balance messages between the members of the queue group, but the code differences are minimal.
|
||||
|
||||
Keep in mind that the queue groups in NATS are dynamic and do not require any server configuration. You can almost think of a regular subscription as a queue group of 1, but it is probably not worth thinking too much about that.
|
||||
|
||||

|
||||
|
||||
As an example, to subscribe to the queue `workers` with the subject `updates`:
|
||||
|
||||
!INCLUDE "../../\_examples/subscribe\_queue.html"
|
||||
|
||||
If you run this example with the publish examples that send to `updates`, you will see that one of the instances gets a message while the others you run won't. But the instance that receives the message will change.
|
||||
|
||||
8
developing-with-nats/intro-3/reply.md
Normal file
8
developing-with-nats/intro-3/reply.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Replying to a Message
|
||||
|
||||
Incoming messages have an optional reply-to field. If that field is set, it will contain a subject to which a reply is expected.
|
||||
|
||||
For example, the following code will listen for that request and respond with the time.
|
||||
|
||||
!INCLUDE "../../\_examples/subscribe\_w\_reply.html"
|
||||
|
||||
8
developing-with-nats/intro-3/structure.md
Normal file
8
developing-with-nats/intro-3/structure.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Structured Data
|
||||
|
||||
Client libraries may provide tools to help receive structured data, like JSON. The core traffic to the NATS server will always be opaque byte arrays. The server does not process message payloads in any form. For libraries that don't provide helpers, you can always encode and decode data before sending the associated bytes to the NATS client.
|
||||
|
||||
For example, to receive JSON you could do:
|
||||
|
||||
!INCLUDE "../../\_examples/subscribe\_json.html"
|
||||
|
||||
8
developing-with-nats/intro-3/sync.md
Normal file
8
developing-with-nats/intro-3/sync.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Synchronous Subscriptions
|
||||
|
||||
Synchronous subscriptions require the application to wait for messages. This type of subscription is easy to set-up and use, but requires the application to deal with looping if multiple messages are expected. For situations where a single message is expected, synchronous subscriptions are sometimes easier to manage, depending on the language.
|
||||
|
||||
For example, to subscribe to the subject `updates` and receive a single message you could do:
|
||||
|
||||
!INCLUDE "../../\_examples/subscribe\_sync.html"
|
||||
|
||||
16
developing-with-nats/intro-3/unsub_after.md
Normal file
16
developing-with-nats/intro-3/unsub_after.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Unsubscribing After N Messages
|
||||
|
||||
NATS provides a special form of unsubscribe that is configured with a message count and takes effect when that many messages are sent to a subscriber. This mechanism is very useful if only a single message is expected.
|
||||
|
||||
The message count you provide is the total message count for a subscriber. So if you unsubscribe with a count of 1, the server will stop sending messages to that subscription after it has received one message. If the subscriber has already received one or more messages, the unsubscribe will be immediate. This action based on history can be confusing if you try to auto unsubscribe on a long running subscription, but is logical for a new one.
|
||||
|
||||
> Auto unsubscribe is based on the total messages sent to a subscriber, not just the new ones.
|
||||
|
||||
Auto unsubscribe can also result in some tricky edge cases if a server cluster is used. The client will tell the server of the unsubscribe count when the application requests it. But if the client disconnects before the count is reached, it may have to tell another server of the remaining count. This dance between previous server notifications and new notifications on reconnect can result in unplanned behavior.
|
||||
|
||||
Finally, most of the client libraries also track the max message count after an auto unsubscribe request. Which means that the client will stop allowing messages to flow even if the server has miscounted due to reconnects or some other failure in the client library.
|
||||
|
||||
The following example shows unsubscribe after a single message:
|
||||
|
||||
!INCLUDE "../../\_examples/unsubscribe\_auto.html"
|
||||
|
||||
8
developing-with-nats/intro-3/unsubscribing.md
Normal file
8
developing-with-nats/intro-3/unsubscribing.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Unsubscribing
|
||||
|
||||
The client libraries provide a means to unsubscribe a previous subscription request.
|
||||
|
||||
This process requires an interaction with the server, so for an asynchronous subscription there may be a small window of time where a message comes through as the unsubscribe is processed by the library. Ignoring that slight edge case, the client library will clean up any outstanding messages and tell the server that the subscription is no longer used.
|
||||
|
||||
!INCLUDE "../../\_examples/unsubscribe.html"
|
||||
|
||||
18
developing-with-nats/intro-3/wildcards.md
Normal file
18
developing-with-nats/intro-3/wildcards.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Wildcard Subscriptions
|
||||
|
||||
There is no special code to subscribe with a wildcard subject. Wildcards are a normal part of the subject name.
|
||||
|
||||
However, there is a common technique that may come in to play when you use wildcards. This technique is to use the subject provided with the incoming message to determine what to do with the message.
|
||||
|
||||
For example, you can subscribe using `*` and then act based on the actual subject.
|
||||
|
||||
!INCLUDE "../../\_examples/subscribe\_star.html"
|
||||
|
||||
or do something similar with `>`:
|
||||
|
||||
!INCLUDE "../../\_examples/subscribe\_arrow.html"
|
||||
|
||||
The following example can be used to test these two subscribers. The `*` subscriber should receive at most 2 messages, while the `>` subscriber receives 4. More importantly the `time.*.east` subscriber won't receive on `time.us.east.atlanta` because that won't match.
|
||||
|
||||
!INCLUDE "../../\_examples/wildcard\_tester.html"
|
||||
|
||||
8
developing-with-nats/intro-4/README.md
Normal file
8
developing-with-nats/intro-4/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Sending Messages
|
||||
|
||||
NATS sends and receives messages using a protocol that includes a target subject, an optional reply subject and an array of bytes. Some libraries may provide helpers to convert other data formats to and from bytes, but the NATS server will treat all messages as opaque byte arrays.
|
||||
|
||||
All of the NATS clients are designed to make sending a message simple. For example, to send the string “All is Well” to the “updates” subject as a UTF-8 string of bytes you would do:
|
||||
|
||||
!INCLUDE "../../\_examples/publish\_bytes.html"
|
||||
|
||||
14
developing-with-nats/intro-4/caches.md
Normal file
14
developing-with-nats/intro-4/caches.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Caches, Flush and Ping
|
||||
|
||||
For performance reasons, most if not all, of the client libraries will cache outgoing data so that bigger chunks can be written to the network at one time. This may be as simple as a byte buffer that stores up a few messages before being pushed to the network.
|
||||
|
||||
These buffers do not hold messages forever, generally they are designed to hold messages in high throughput scenarios, while still providing good latency in low throughput situations.
|
||||
|
||||
It is the libraries job to make sure messages flow in a high performance manner. But there may be times when an application needs to know that a message has "hit the wire." In this case, applications can use a flush call to tell the library to move data through the system.
|
||||
|
||||
!INCLUDE "../../\_examples/flush.html"
|
||||
|
||||
## Flush and Ping/Pong
|
||||
|
||||
Many of the client libraries use the PING/PONG interaction built into the NATS protocol to insure that flush pushed all of the cached messages to the server. When an application calls flush most libraries will put a PING on the outgoing queue of messages, and wait for the server to send PONG before saying that the flush was successful.
|
||||
|
||||
6
developing-with-nats/intro-4/replyto.md
Normal file
6
developing-with-nats/intro-4/replyto.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Including a Reply Subject
|
||||
|
||||
The optional reply-to field when publishing a message can be used on the receiving side to respond. The reply-to subject is often called an _inbox_, and most libraries may provide a method for generating unique inbox subjects. Most libraries also provide for the request-reply pattern with a single call. For example to send a request to the subject `time`, with no content for the messages, you might:
|
||||
|
||||
!INCLUDE "../../\_examples/publish\_with\_reply.html"
|
||||
|
||||
95
developing-with-nats/intro-4/request_reply.md
Normal file
95
developing-with-nats/intro-4/request_reply.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Request-Reply Semantics
|
||||
|
||||
The pattern of sending a message and receiving a response is encapsulated in most client libraries into a request method. Under the covers this method will publish a message with a unique reply-to subject and wait for the response before returning.
|
||||
|
||||
In the older versions of some libraries a completely new reply-to subject is created each time. In newer versions, a subject hierarchy is used so that a single subscriber in the client library listens for a wildcard, and requests are sent with a unique child subject of a single subject.
|
||||
|
||||
The primary difference between the request method and publishing with a reply-to is that the library is only going to accept one response, and in most libraries the request will be treated as a synchronous action. The library may even provide a way to set the timeout.
|
||||
|
||||
For example, updating the previous publish example we may request `time` with a one second timeout:
|
||||
|
||||
!INCLUDE "../../\_examples/request\_reply.html"
|
||||
|
||||
You can think of request-reply in the library as a subscribe, get one message, unsubscribe pattern. In Go this might look something like:
|
||||
|
||||
```go
|
||||
sub, err := nc.SubscribeSync(replyTo)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
nc.Flush()
|
||||
|
||||
// Send the request
|
||||
nc.PublishRequest(subject, replyTo, []byte(input))
|
||||
|
||||
// Wait for a single response
|
||||
for {
|
||||
msg, err := sub.NextMsg(1 * time.Second)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
response = string(msg.Data)
|
||||
break
|
||||
}
|
||||
sub.Unsubscribe()
|
||||
```
|
||||
|
||||
## Scatter-Gather
|
||||
|
||||
You can expand the request-reply pattern into something often called scatter-gather. To receive multiple messages, with a timeout, you could do something like the following, where the loop getting messages is using time as the limitation, not the receipt of a single message:
|
||||
|
||||
```go
|
||||
sub, err := nc.SubscribeSync(replyTo)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
nc.Flush()
|
||||
|
||||
// Send the request
|
||||
nc.PublishRequest(subject, replyTo, []byte(input))
|
||||
|
||||
// Wait for a single response
|
||||
max := 100 * time.Millisecond
|
||||
start := time.Now()
|
||||
for time.Now().Sub(start) < max {
|
||||
msg, err := sub.NextMsg(1 * time.Second)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
responses = append(responses, string(msg.Data))
|
||||
}
|
||||
sub.Unsubscribe()
|
||||
```
|
||||
|
||||
Or, you can loop on a counter and a timeout to try to get _at least N_ responses:
|
||||
|
||||
```go
|
||||
sub, err := nc.SubscribeSync(replyTo)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
nc.Flush()
|
||||
|
||||
// Send the request
|
||||
nc.PublishRequest(subject, replyTo, []byte(input))
|
||||
|
||||
// Wait for a single response
|
||||
max := 500 * time.Millisecond
|
||||
start := time.Now()
|
||||
for time.Now().Sub(start) < max {
|
||||
msg, err := sub.NextMsg(1 * time.Second)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
responses = append(responses, string(msg.Data))
|
||||
|
||||
if len(responses) >= minResponses {
|
||||
break
|
||||
}
|
||||
}
|
||||
sub.Unsubscribe()
|
||||
```
|
||||
|
||||
8
developing-with-nats/intro-4/structure.md
Normal file
8
developing-with-nats/intro-4/structure.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Sending Structured Data
|
||||
|
||||
Some client libraries provide helpers to send structured data while others depend on the application to perform any encoding and decoding and just take byte arrays for sending. The following example shows how to send JSON but this could easily be altered to send a protocol buffer, YAML or some other format. JSON is a text format so we also have to encode the string in most languages to bytes. We are using UTF-8, the JSON standard encoding.
|
||||
|
||||
Take a simple _stock ticker_ that sends the symbol and price of each stock:
|
||||
|
||||
!INCLUDE "../../\_examples/publish\_json.html"
|
||||
|
||||
8
developing-with-nats/intro-5/README.md
Normal file
8
developing-with-nats/intro-5/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Monitoring the Connection
|
||||
|
||||
Managing the interaction with the server is primarily the job of the client library but most of the libraries also provide some insight into what is happening under the covers.
|
||||
|
||||
For example, the client library may provide a mechanism to get the connection's current status:
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_status.html"
|
||||
|
||||
22
developing-with-nats/intro-5/events.md
Normal file
22
developing-with-nats/intro-5/events.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Listen for Connection Events
|
||||
|
||||
While the connection status is interesting, it is perhaps more interesting to know when the status changes. Most, if not all, of the NATS client libraries provide a way to listen for events related to the connection and its status.
|
||||
|
||||
The actual API for these listeners is language dependent, but the following examples show a few of the more common use cases. See the API documentation for the client library you are using for more specific instructions.
|
||||
|
||||
Connection events may include the connection being closed, disconnected or reconnected. Reconnecting involves a disconnect and connect, but depending on the library implementation may also include multiple disconnects as the client tries to find a server, or the server is rebooted.
|
||||
|
||||
!INCLUDE "../../\_examples/connection\_listener.html"
|
||||
|
||||
## Listen for New Servers
|
||||
|
||||
When working with a cluster, servers may be added or changed. Some of the clients allow you to listen for this notification:
|
||||
|
||||
!INCLUDE "../../\_examples/servers\_added.html"
|
||||
|
||||
## Listen for Errors
|
||||
|
||||
The client library may separate server-to-client errors from events. Many server events are not handled by application code and result in the connection being closed. Listening for the errors can be very useful for debugging problems.
|
||||
|
||||
!INCLUDE "../../\_examples/error\_listener.html"
|
||||
|
||||
32
developing-with-nats/intro-5/slow.md
Normal file
32
developing-with-nats/intro-5/slow.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Slow Consumers
|
||||
|
||||
NATS is designed to move messages through the server quickly. As a result, NATS depends on the applications to consider and respond to changing message rates. The server will do a bit of impedance matching, but if a client is too slow the server will eventually cut them off. These cut off connections are called _slow consumers_.
|
||||
|
||||
One way some of the libraries deal with bursty message traffic is to cache incoming messages for a subscription. So if an application can handle 10 messages per second and sometimes receives 20 messages per second, the library may hold the extra 10 to give the application time to catch up. To the server, the application will appear to be handling the messages and consider the connection healthy. It is up to the client library to decide what to do when the cache is too big, but most client libraries will drop incoming messages.
|
||||
|
||||
Receiving and dropping messages from the server keeps the connection to the server healthy, but creates an application requirement. There are several common patterns:
|
||||
|
||||
* Use request/reply to throttle the sender and prevent overloading the subscriber
|
||||
* Use a queue with multiple subscribers splitting the work
|
||||
* Persist messages with something like NATS streaming
|
||||
|
||||
Libraries that cache incoming messages may provide two controls on the incoming queue, or pending messages. These are useful if the problem is bursty publishers and not a continuous performance mismatch. Disabling these limits can be dangerous in production and although setting these limits to 0 may help find problems, it is also a dangerous proposition in production.
|
||||
|
||||
> Check your libraries documentation for the default settings, and support for disabling these limits.
|
||||
|
||||
The incoming cache is usually per subscriber, but again, check the specific documentation for your client library.
|
||||
|
||||
## Limiting Incoming/Pending Messages by Count and Bytes
|
||||
|
||||
The first way that the incoming queue can be limited is by message count. The second way to limit the incoming queue is by total size. For example, to limit the incoming cache to 1,000 messages or 5mb whichever comes first:
|
||||
|
||||
!INCLUDE "../../\_examples/slow\_pending\_limits.html"
|
||||
|
||||
## Detect a Slow Consumer and Check for Dropped Messages
|
||||
|
||||
When a slow consumer is detected and messages are about to be dropped, the library may notify the application. This process may be similar to other errors or may involve a custom callback.
|
||||
|
||||
Some libraries, like Java, will not send this notification on every dropped message because that could be noisy. Rather the notification may be sent once per time the subscriber gets behind. Libraries may also provide a way to get a count of dropped messages so that applications can at least detect a problem is occurring.
|
||||
|
||||
!INCLUDE "../../\_examples/slow\_listener.html"
|
||||
|
||||
9
developing-with-nats/intro-6/README.md
Normal file
9
developing-with-nats/intro-6/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Tutorials
|
||||
|
||||
Tutorials are provided to give guidance on commonly used aspects of NATS.
|
||||
|
||||
* [Explore NATS Publish/Subscribe](pubsub.md)
|
||||
* [Explore NATS Request/Reply](reqreply.md)
|
||||
* [Explore NATS Queueing](queues.md)
|
||||
* [Advanced Connect and Custom Dialer in Go](custom_dialer.md)
|
||||
|
||||
128
developing-with-nats/intro-6/custom_dialer.md
Normal file
128
developing-with-nats/intro-6/custom_dialer.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Advanced Connect and Custom Dialer in Go
|
||||
|
||||
The Go NATS client features a [CustomDialer](https://godoc.org/github.com/nats-io/go-nats#CustomDialer) option which allows you to customize the connection logic against the NATS server without having to modify the internals of the client. For example, let's say that you want to make the client use the `context` package to use `DialContext` and be able to cancel connecting to NATS altogether with a deadline, you could then do define a Dialer implementation as follows:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
type customDialer struct {
|
||||
ctx context.Context
|
||||
nc *nats.Conn
|
||||
connectTimeout time.Duration
|
||||
connectTimeWait time.Duration
|
||||
}
|
||||
|
||||
func (cd *customDialer) Dial(network, address string) (net.Conn, error) {
|
||||
ctx, cancel := context.WithTimeout(cd.ctx, cd.connectTimeout)
|
||||
defer cancel()
|
||||
|
||||
for {
|
||||
log.Println("Attempting to connect to", address)
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
select {
|
||||
case <-cd.ctx.Done():
|
||||
return nil, cd.ctx.Err()
|
||||
default:
|
||||
d := &net.Dialer{}
|
||||
if conn, err := d.DialContext(ctx, network, address); err == nil {
|
||||
log.Println("Connected to NATS successfully")
|
||||
return conn, nil
|
||||
} else {
|
||||
time.Sleep(cd.connectTimeWait)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With the dialer implementation above, the NATS client will retry a number of times to connect to the NATS server until the context is no longer valid:
|
||||
|
||||
```go
|
||||
func main() {
|
||||
// Parent context cancels connecting/reconnecting altogether.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var err error
|
||||
var nc *nats.Conn
|
||||
cd := &customDialer{
|
||||
ctx: ctx,
|
||||
connectTimeout: 10 * time.Second,
|
||||
connectTimeWait: 1 * time.Second,
|
||||
}
|
||||
opts := []nats.Option{
|
||||
nats.SetCustomDialer(cd),
|
||||
nats.ReconnectWait(2 * time.Second),
|
||||
nats.ReconnectHandler(func(c *nats.Conn) {
|
||||
log.Println("Reconnected to", c.ConnectedUrl())
|
||||
}),
|
||||
nats.DisconnectHandler(func(c *nats.Conn) {
|
||||
log.Println("Disconnected from NATS")
|
||||
}),
|
||||
nats.ClosedHandler(func(c *nats.Conn) {
|
||||
log.Println("NATS connection is closed.")
|
||||
}),
|
||||
nats.NoReconnect(),
|
||||
}
|
||||
go func() {
|
||||
nc, err = nats.Connect("127.0.0.1:4222", opts...)
|
||||
}()
|
||||
|
||||
WaitForEstablishedConnection:
|
||||
for {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Wait for context to be canceled either by timeout
|
||||
// or because of establishing a connection...
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
break WaitForEstablishedConnection
|
||||
default:
|
||||
}
|
||||
|
||||
if nc == nil || !nc.IsConnected() {
|
||||
log.Println("Connection not ready")
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
break WaitForEstablishedConnection
|
||||
}
|
||||
if ctx.Err() != nil {
|
||||
log.Fatal(ctx.Err())
|
||||
}
|
||||
|
||||
for {
|
||||
if nc.IsClosed() {
|
||||
break
|
||||
}
|
||||
if err := nc.Publish("hello", []byte("world")); err != nil {
|
||||
log.Println(err)
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
log.Println("Published message")
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
// Disconnect and flush pending messages
|
||||
if err := nc.Drain(); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
log.Println("Disconnected")
|
||||
}
|
||||
```
|
||||
|
||||
154
developing-with-nats/intro-6/pubsub.md
Normal file
154
developing-with-nats/intro-6/pubsub.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Explore NATS Pub/Sub
|
||||
|
||||
NATS is a publish subscribe messaging system. Subscribers listening on a subject receive messages on that subject. If the subscriber is not actively listening on the subject, the message is not received. Subscribers can use the wildcard tokens such as `*` and `>` to match a single token or to match the tail of a subject.
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
|
||||
Go and the NATS server should be installed. Optionally you can use the demo server located at `nats://demo.nats.io`
|
||||
|
||||
### 1. Start the NATS server
|
||||
|
||||
```bash
|
||||
% nats-server
|
||||
```
|
||||
|
||||
When the server starts successfully, you will see the following messages:
|
||||
|
||||
```bash
|
||||
[1] 2019/31/05 15:18:22.301550 [INF] Starting nats-server version 2.0.0
|
||||
[1] 2019/31/05 15:18:22.301762 [INF] Listening for client connections on 0.0.0.0:4222
|
||||
[1] 2019/31/05 15:18:22.301769 [INF] nats-server is ready
|
||||
```
|
||||
|
||||
The NATS server listens for client connections on TCP Port 4222.
|
||||
|
||||
### 2. Start a shell or command prompt session
|
||||
|
||||
You will use this session to run an example NATS client subscriber program.
|
||||
|
||||
### 3. CD to the Go client examples directory
|
||||
|
||||
```bash
|
||||
% cd $GOPATH/src/github.com/nats-io/nats.go/examples
|
||||
```
|
||||
|
||||
### 4. Run the client subscriber program
|
||||
|
||||
```bash
|
||||
% go run nats-sub/main.go <subject>
|
||||
```
|
||||
|
||||
Where `<subject>` is a subject to listen on. A valid subject is a string that is unique in the system.
|
||||
|
||||
For example:
|
||||
|
||||
```bash
|
||||
% go run nats-sub/main.go msg.test
|
||||
```
|
||||
|
||||
You should see the message: _Listening on \[msg.test\]_
|
||||
|
||||
### 5. Start another shell or command prompt session
|
||||
|
||||
You will use this session to run a NATS publisher client.
|
||||
|
||||
## 6. CD to the examples directory
|
||||
|
||||
```bash
|
||||
% cd $GOPATH/src/github.com/nats-io/nats.go/examples
|
||||
```
|
||||
|
||||
### 7. Publish a NATS message
|
||||
|
||||
```bash
|
||||
% go run nats-pub/main.go <subject> <message>
|
||||
```
|
||||
|
||||
Where `<subject>` is the subject name and `<message>` is the text to publish.
|
||||
|
||||
For example:
|
||||
|
||||
```bash
|
||||
% go run nats-pub/main.go msg.test hello
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
% go run nats-pub/main.go msg.test "NATS MESSAGE"
|
||||
```
|
||||
|
||||
### 8. Verify message publication and receipt
|
||||
|
||||
You should see that the publisher sends the message: _Published \[msg.test\] : 'NATS MESSAGE'_
|
||||
|
||||
And that the subscriber receives the message: _\[\#1\] Received on \[msg.test\]: 'NATS MESSAGE'_
|
||||
|
||||
Note that if the receiver does not get the message, check that you are using the same subject name for the publisher and the subscriber.
|
||||
|
||||
### 9. Publish another message
|
||||
|
||||
```bash
|
||||
% go run nats-pub/main.go msg.test "NATS MESSAGE 2"
|
||||
```
|
||||
|
||||
You should see that the subscriber receive message 2. Note that the message count is incremented each time your subscribing client receives a message on that subject:
|
||||
|
||||
### 10. Start another shell or command prompt session
|
||||
|
||||
You will use this session to run a second NATS subscriber.
|
||||
|
||||
### 11. CD to the examples directory
|
||||
|
||||
```bash
|
||||
% cd $GOPATH/src/github.com/nats-io/nats.go/examples
|
||||
```
|
||||
|
||||
### 12. Subscribe to the message
|
||||
|
||||
```bash
|
||||
% go run nats-sub/main.go msg.test
|
||||
```
|
||||
|
||||
### 13. Publish another message using the publisher client
|
||||
|
||||
```bash
|
||||
% go run nats-pub/main.go msg.test "NATS MESSAGE 3"
|
||||
```
|
||||
|
||||
Verify that both subscribing clients receive the message.
|
||||
|
||||
### 14. Start another shell or command prompt session
|
||||
|
||||
You will use this session to run a third NATS subscriber.
|
||||
|
||||
### 15. CD to the examples directory
|
||||
|
||||
```bash
|
||||
% cd $GOPATH/src/github.com/nats-io/nats.go/examples
|
||||
```
|
||||
|
||||
### 16. Subscribe to a different message
|
||||
|
||||
```bash
|
||||
% go run nats-sub/main.go msg.test.new
|
||||
```
|
||||
|
||||
All the but last subscriber receives the message. Why? Because that subscriber is not listening on the message subject used by the publisher.
|
||||
|
||||
### 17. Update the last subscriber to use a wildcard
|
||||
|
||||
NATS supports the use of wildcard characters for message subscribers. You cannot publish a message using a wildcard subject.
|
||||
|
||||
Change the last subscriber the listen on msg.\* and run it:
|
||||
|
||||
```bash
|
||||
% go run nats-sub/main.go msg.*
|
||||
```
|
||||
|
||||
### 18. Publish another message
|
||||
|
||||
This time, all three subscribing clients should receive the message.
|
||||
|
||||
72
developing-with-nats/intro-6/queues.md
Normal file
72
developing-with-nats/intro-6/queues.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Explore NATS Queueing
|
||||
|
||||
NATS supports a form of load balancing using queue groups. Subscribers register a queue group name. A single subscriber in the group is randomly selected to receive the message.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Go and the NATS server should be installed.
|
||||
|
||||
### 1. Start the NATS server
|
||||
|
||||
```bash
|
||||
nats-server
|
||||
```
|
||||
|
||||
### 2. Clone the repositories for each client examples
|
||||
|
||||
```bash
|
||||
go get github.com/nats-io/nats.go
|
||||
git clone https://github.com/nats-io/nats.js.git
|
||||
git clone https://github.com/nats-io/nats.rb.git
|
||||
```
|
||||
|
||||
### 3. Run the Go client subscriber with queue group name
|
||||
|
||||
```bash
|
||||
cd $GOPATH/src/github.com/nats-io/nats.go/examples
|
||||
go run nats-qsub/main.go foo my-queue
|
||||
```
|
||||
|
||||
### 4. Install and run the Node client subscriber with queue group name
|
||||
|
||||
```bash
|
||||
npm install nats
|
||||
cd nats.js/examples
|
||||
node node-sub --queue=my-queue foo
|
||||
```
|
||||
|
||||
### 5. Install and run the Ruby client subscriber with queue group name
|
||||
|
||||
```bash
|
||||
gem install nats
|
||||
nats-queue foo my-queue &
|
||||
```
|
||||
|
||||
### 6. Run another Go client subscriber _without_ the queue group.
|
||||
|
||||
```bash
|
||||
cd $GOPATH/src/github.com/nats-io/nats.go/examples
|
||||
go run nats-sub/main.go foo
|
||||
```
|
||||
|
||||
### 7. Publish a NATS message using the Go client
|
||||
|
||||
```bash
|
||||
cd $GOPATH/src/github.com/nats-io/nats.go/examples
|
||||
go run nats-pub/main.go foo "Hello NATS!"
|
||||
```
|
||||
|
||||
### 8. Verify message publication and receipt
|
||||
|
||||
You should see that the publisher sends the message: _Published \[foo\] : 'Hello NATS!'_
|
||||
|
||||
You should see that only one of the my-queue group subscribers receives the message. In addition, the Go client subscriber not in the my-queue group should also receive the message.
|
||||
|
||||
### 9. Publish another message
|
||||
|
||||
```bash
|
||||
go run nats-pub/main.go foo "Hello NATS Again!"
|
||||
```
|
||||
|
||||
You should see that a different queue group subscriber receives the message this time, chosen at random among the 3 queue group members.
|
||||
|
||||
42
developing-with-nats/intro-6/reqreply.md
Normal file
42
developing-with-nats/intro-6/reqreply.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Explore NATS Request/Reply
|
||||
|
||||
NATS supports request/reply messaging. In this tutorial you explore how to exchange point-to-point messages using NATS.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Go and the NATS server should be installed.
|
||||
|
||||
### 1. Start the NATS server
|
||||
|
||||
```bash
|
||||
% nats-server
|
||||
```
|
||||
|
||||
### 2. Start two terminal sessions
|
||||
|
||||
You will use these sessions to run the NATS request and reply clients.
|
||||
|
||||
### 3. Change to the examples directory
|
||||
|
||||
```bash
|
||||
% cd $GOPATH/src/github.com/nats-io/nats.go/examples
|
||||
```
|
||||
|
||||
### 4. In one terminal, run the reply client listener
|
||||
|
||||
```bash
|
||||
% go run nats-rply/main.go foo "this is my response"
|
||||
```
|
||||
|
||||
You should see the message `Receiver is listening`, and that the NATS receiver client is listening on the "help.please" subject. The reply client acts as a receiver, listening for message requests. In NATS, the receiver is a subscriber.
|
||||
|
||||
### 5. In the other terminal, run the request client
|
||||
|
||||
```bash
|
||||
% go run nats-req/main.go foo "request payload"
|
||||
```
|
||||
|
||||
The NATS requestor client makes a request by sending the message "some message" on the “help.please” subject.
|
||||
|
||||
The NATS receiver client receives the message, formulates the reply \("OK, I CAN HELP!!!\), and sends it to the inbox of the requester.
|
||||
|
||||
8
developing-with-nats/intro/README.md
Normal file
8
developing-with-nats/intro/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Connecting
|
||||
|
||||
A NATS system is usually identified by a standard URL with the `nats` or `tls` protocol, e.g. nats://demo.nats.io. A NATS system can be a single server, a small cluster or a global super cluster. Throughout these examples we will rely on a single test server, provided by [nats.io](https://nats.io), at `nats://demo.nats.io`, where `4222` is the default port for NATS.
|
||||
|
||||
NATS also supports secure connectivity using TLS via the `tls` protocol. Most clients support auto-detection of a secure connection using the URL protocol `tls`. There is also a demo server running TLS at `tls://demo.nats.io:4443`. The protocol requirement is being made optional for many client libraries, so that you can use `demo.nats.io:4222` as the URL and let the client and server resolve whether or not TLS is required.
|
||||
|
||||
There are numerous options for a NATS connection ranging from timeouts to reconnect settings.
|
||||
|
||||
114
developing-with-nats/intro/cluster.md
Normal file
114
developing-with-nats/intro/cluster.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# Connecting to a Cluster
|
||||
|
||||
When connecting to a cluster, there are a few things to think about.
|
||||
|
||||
* Passing a URL for each cluster member \(semi-optional\)
|
||||
* The connection algorithm
|
||||
* The reconnect algorithm \(discussed later\)
|
||||
* Server provided URLs
|
||||
|
||||
When a client library first tries to connect it will use the list of URLs provided to the connection options or function. These URLs are checked, usually in order, and the first successful connection is used.
|
||||
|
||||
After a client connects to the server, the server may provide a list of URLs for additional known servers. This allows a client to connect to one server and still have other servers available during reconnect.
|
||||
|
||||
To insure the initial connection, your code should include a list of reasonable _front line_ servers. Those servers may know about other members of the cluster, and may tell the client about those members. But you don't have to configure the client to pass every valid member of the cluster in the connect method.
|
||||
|
||||
By providing the ability to pass multiple connect options NATS can handle the possibility of a machine going down or being unavailable to a client. By adding the ability of the server to feed clients a list of known servers as part of the client-server protocol the mesh created by a cluster can grow and change organically while the clients are running.
|
||||
|
||||
_Note, failure behavior is library dependent, please check the documentation for your client library on information about what happens if the connect fails._
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
servers := []string{"nats://127.0.0.1:1222", "nats://127.0.0.1:1223", "nats://127.0.0.1:1224"}
|
||||
|
||||
nc, err := nats.Connect(strings.Join(servers, ","))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Options options = new Options.Builder().
|
||||
server("nats://localhost:1222").
|
||||
server("nats://localhost:1223").
|
||||
server("nats://localhost:1224").
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect({
|
||||
servers: [
|
||||
"nats://demo.nats.io:4222",
|
||||
"nats://localhost:4222"
|
||||
]}
|
||||
);
|
||||
nc.on('connect', (c) => {
|
||||
// Do something with the connection
|
||||
doSomething();
|
||||
// When done close it
|
||||
nc.close();
|
||||
});
|
||||
nc.on('error', (err) => {
|
||||
failed(err);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
await nc.connect(servers=[
|
||||
"nats://127.0.0.1:1222",
|
||||
"nats://127.0.0.1:1223",
|
||||
"nats://127.0.0.1:1224"
|
||||
])
|
||||
|
||||
# Do something with the connection
|
||||
|
||||
await nc.close()
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
require 'nats/client'
|
||||
|
||||
NATS.start(servers: ["nats://127.0.0.1:1222", "nats://127.0.0.1:1223", "nats://127.0.0.1:1224"]) do |nc|
|
||||
# Do something with the connection
|
||||
|
||||
# Close the connection
|
||||
nc.close
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// will throw an exception if connection fails
|
||||
let nc = await connect({
|
||||
servers: [
|
||||
"nats://demo.nats.io:4222",
|
||||
"nats://localhost:4222"
|
||||
]
|
||||
});
|
||||
// Do something with the connection
|
||||
|
||||
// When done close it
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
73
developing-with-nats/intro/connect_timeout.md
Normal file
73
developing-with-nats/intro/connect_timeout.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Setting a Connect Timeout
|
||||
|
||||
Each library has its own, language preferred way, to pass connection options. One of the most common options is a connection timeout. To set the maximum time to connect to a server to 10 seconds:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
nc, err := nats.Connect("demo.nats.io", nats.Name("API Options Example"), nats.Timeout(10*time.Second))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Options options = new Options.Builder().
|
||||
server("nats://demo.nats.io:4222").
|
||||
connectionTimeout(Duration.ofSeconds(10)). // Set timeout
|
||||
build();
|
||||
Connection nc = Nats.connect(options);
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
await nc.connect(connect_timeout=2)
|
||||
|
||||
# Do something with the connection
|
||||
|
||||
await nc.close()
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
# There is currently no connect timeout as part of the Ruby NATS client API, but you can use a timer to mimic it.
|
||||
require 'nats/client'
|
||||
|
||||
timer = EM.add_timer(5) do
|
||||
NATS.connect do |nc|
|
||||
# Do something with the connection
|
||||
|
||||
# Close the connection
|
||||
nc.close
|
||||
end
|
||||
end
|
||||
EM.cancel_timer(timer)
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
let nc = await connect({
|
||||
url: "nats://demo.nats.io:4222",
|
||||
timeout: 1000
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
89
developing-with-nats/intro/default_server.md
Normal file
89
developing-with-nats/intro/default_server.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Connecting to the Default Server
|
||||
|
||||
Some libraries also provide a special way to connect to a _default_ url, which is generally `nats://localhost:4222`:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```go
|
||||
nc, err := nats.Connect(nats.DefaultURL)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connection
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```java
|
||||
Connection nc = Nats.connect();
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect();
|
||||
nc.on('connect', (c) => {
|
||||
// Do something with the connection
|
||||
doSomething();
|
||||
// When done close it
|
||||
nc.close();
|
||||
});
|
||||
nc.on('error', (err) => {
|
||||
failed(err);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
await nc.connect()
|
||||
|
||||
# Do something with the connection
|
||||
|
||||
await nc.close()
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
require 'nats/client'
|
||||
|
||||
NATS.start do |nc|
|
||||
# Do something with the connection
|
||||
|
||||
# Close the connection
|
||||
nc.close
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// will throw an exception if connection fails
|
||||
let nc = await connect();
|
||||
// Do something with the connection
|
||||
|
||||
// When done close it
|
||||
nc.close();
|
||||
|
||||
|
||||
// alternatively, you can use the Promise pattern
|
||||
let nc1: Client;
|
||||
connect()
|
||||
.then((c) => {
|
||||
nc1 = c;
|
||||
// Do something with the connection
|
||||
nc1.close();
|
||||
});
|
||||
// add a .catch/.finally
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
12
developing-with-nats/intro/noecho.md
Normal file
12
developing-with-nats/intro/noecho.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Turning Off Echo'd Messages
|
||||
|
||||
By default a NATS connection will echo messages if the connection also has interest in the published subject. This means that if a publisher on a connection sends a message to a subject any subscribers on that same connection will receive the message. Clients can opt to turn off this behavior, such that regardless of interest the message will not be delivered to subscribers on the same connection.
|
||||
|
||||
The NoEcho option can be useful in BUS patterns where all applications subscribe and publish to the same subject. Usually a publish represents a state change that the application already knows about, so in the case where the application publishes an update it does not need to process the update itself.
|
||||
|
||||

|
||||
|
||||
Keep in mind that each connection will have to turn off echo, and that it is per connection, not per application. Also, turning echo on and off can result in a major change to your applications communications protocol since messages will flow or stop flowing based on this setting and the subscribing code won't have any indication as to why.
|
||||
|
||||
!INCLUDE "../../\_examples/no\_echo.html"
|
||||
|
||||
20
developing-with-nats/intro/pingpong.md
Normal file
20
developing-with-nats/intro/pingpong.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Ping/Pong Protocol
|
||||
|
||||
The client and server use a simple PING/PONG protocol to check that they are both still connected. The client will ping the server on a regular, configured interval so that the server usually doesn't have to initiate the PING/PONG interaction.
|
||||
|
||||

|
||||
|
||||
## Set the Ping Interval
|
||||
|
||||
If you have a connection that is going to be open a long time with few messages traveling on it, setting this PING interval can control how quickly the client will be notified of a problem. However on connections with a lot of traffic, the client will often figure out there is a problem between PINGS, and as a result the default PING interval is often on the order of minutes. To set the interval to 20s:
|
||||
|
||||
!INCLUDE "../../\_examples/ping\_20s.html"
|
||||
|
||||
## Limit Outgoing Pings
|
||||
|
||||
The PING/PONG interaction is also used by most of the clients as a way to flush the connection to the server. Clients that cache outgoing messages provide a flush call that will run a PING/PONG. The flush will wait for the PONG to return, telling it that all cached messages have been processed, including the PING. The number of cached PING requests can be limited in most clients to insure that traffic problems are identified early. This configuration for _max outgoing pings_ or similar will usually default to a small number and should only be increased if you are worried about fast flush traffic, perhaps in multiple threads.
|
||||
|
||||
For example, to set the maximum number of outgoing pings to 5:
|
||||
|
||||
!INCLUDE "../../\_examples/ping\_5.html"
|
||||
|
||||
30
developing-with-nats/intro/protocol.md
Normal file
30
developing-with-nats/intro/protocol.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Controlling the Client/Server Protocol
|
||||
|
||||
The protocol between the client and the server is fairly simple and relies on a control line and sometimes a body. The control line contains the operations being sent, like PING or PONG, followed by a carriage return and line feed, CRLF or "\r\n". The server has a setting that can limit the maximum size of a control line. For PING and PONG this doesn't come into play, but for messages that contain subject names, the control line length can be important. The server is also configured with a maximum payload size, which limits the size of a message body. The server sends the maximum payload size to the client at connect time but doesn't currently tell the client the maximum control line size.
|
||||
|
||||
## Set the Maximum Control Line Size
|
||||
|
||||
Some clients will try to limit the control line size internally to prevent an error from the server. These clients may or may not allow you to set the size being used, but if they do, the size should be set to match the server configuration.
|
||||
|
||||
For example, to set the maximum control line size to 2k:
|
||||
|
||||
!INCLUDE "../../\_examples/control\_2k.html"
|
||||
|
||||
## Get the Maximum Payload Size
|
||||
|
||||
While the client can't control the maximum payload size, clients may provide a way for applications to get the size after the connection is made. This will allow the application to chunk or limit data as needed to pass through the server.
|
||||
|
||||
!INCLUDE "../../\_examples/max\_payload.html"
|
||||
|
||||
## Turn On Pedantic Mode
|
||||
|
||||
The NATS server provides a _pedantic_ mode that does extra checks on the protocol. By default, this setting is off but you can turn it on:
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_pedantic.html"
|
||||
|
||||
## Turn On/Off Verbose Mode
|
||||
|
||||
The NATS server also provide a _verbose_ mode. By default, verbose mode is enabled and the server will reply to every message from the client with either a +OK or a -ERR. Most clients turn off verbose mode, which disables all of the +OK traffic. Errors are rarely subject to verbose mode and client libraries handle them as documented. To turn on verbose mode, likely for testing:
|
||||
|
||||
!INCLUDE "../../\_examples/connect\_verbose.html"
|
||||
|
||||
86
developing-with-nats/intro/specific_server.md
Normal file
86
developing-with-nats/intro/specific_server.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Connecting to a Specific Server
|
||||
|
||||
The NATS client libraries can take a full URL, `nats://demo.nats.io:4222`, to specify a specific server host and port to connect to.
|
||||
|
||||
Libraries are removing the requirement for an explicit protocol and may allow `nats://demo.nats.io:4222` or just `demo.nats.io:4222`. Check with your specific client library's documentation to see what URL formats are supported.
|
||||
|
||||
For example, to connect to the demo server with a URL you can use:
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="Go" %}
|
||||
```java
|
||||
// If connecting to the default port, the URL can be simplified
|
||||
// to just the hostname/IP.
|
||||
// That is, the connect below is equivalent to:
|
||||
// nats.Connect("nats://demo.nats.io:4222")
|
||||
nc, err := nats.Connect("demo.nats.io")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer nc.Close()
|
||||
|
||||
// Do something with the connectioConnection nc = Nats.connect("nats://demo.nats.io:4222");
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Java" %}
|
||||
```text
|
||||
Connection nc = Nats.connect("nats://demo.nats.io:4222");
|
||||
|
||||
// Do something with the connection
|
||||
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="JavaScript" %}
|
||||
```javascript
|
||||
let nc = NATS.connect("nats://demo.nats.io:4222");
|
||||
nc.on('connect', (c) => {
|
||||
// Do something with the connection
|
||||
doSomething();
|
||||
// When done close it
|
||||
nc.close();
|
||||
});
|
||||
nc.on('error', (err) => {
|
||||
failed(err);
|
||||
});
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Python" %}
|
||||
```python
|
||||
nc = NATS()
|
||||
await nc.connect(servers=["nats://demo.nats.io:4222"])
|
||||
|
||||
# Do something with the connection
|
||||
|
||||
await nc.close()
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="Ruby" %}
|
||||
```ruby
|
||||
require 'nats/client'
|
||||
|
||||
NATS.start(servers: ["nats://demo.nats.io:4222"]) do |nc|
|
||||
# Do something with the connection
|
||||
|
||||
# Close the connection
|
||||
nc.close
|
||||
end
|
||||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="TypeScript" %}
|
||||
```typescript
|
||||
// will throw an exception if connection fails
|
||||
let nc = await connect("nats://demo.nats.io:4222");
|
||||
// Do something with the connection
|
||||
|
||||
// Close the connection
|
||||
nc.close();
|
||||
```
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
Reference in New Issue
Block a user