1
0
mirror of https://github.com/taigrr/nats.docs synced 2025-01-18 04:03:23 -08:00

fix folder structure from gitbook import

This commit is contained in:
ainsley
2019-10-07 14:20:40 -05:00
parent fb1b7b9a2b
commit 7681f14c27
44 changed files with 0 additions and 0 deletions

View 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.

View 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 %}

View 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 %}

View 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 %}

View File

@@ -0,0 +1,88 @@
# 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.
![](../../.gitbook/assets/noecho.svg)
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.
{% tabs %}
{% tab title="Go" %}
```go
// Turn off echo
nc, err := nats.Connect("demo.nats.io", nats.Name("API NoEcho Example"), nats.NoEcho())
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").
noEcho(). // Turn off echo
build();
Connection nc = Nats.connect(options);
// Do something with the connection
nc.close();
```
{% endtab %}
{% tab title="JavaScript" %}
```javascript
let nc = NATS.connect({
url: "nats://demo.nats.io:4222",
noEcho: true
});
```
{% endtab %}
{% tab title="Python" %}
```python
ncA = NATS()
ncB = NATS()
await ncA.connect(no_echo=True)
await ncB.connect()
async def handler(msg):
# Messages sent by `ncA' will not be received.
print("[Received] ", msg)
await ncA.subscribe("greetings", cb=handler)
await ncA.flush()
await ncA.publish("greetings", b'Hello World!')
await ncB.publish("greetings", b'Hello World!')
# Do something with the connection
await asyncio.sleep(1)
await ncA.drain()
await ncB.drain()
```
{% endtab %}
{% tab title="Ruby" %}
```ruby
NATS.start("nats://demo.nats.io:4222", no_echo: true) do |nc|
# ...
end
```
{% endtab %}
{% tab title="TypeScript" %}
```typescript
let nc = await connect({
url: "nats://demo.nats.io:4222", noEcho: true});
```
{% endtab %}
{% endtabs %}

View File

@@ -0,0 +1,181 @@
# 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.
![](../../.gitbook/assets/pingpong.svg)
## 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:
{% tabs %}
{% tab title="Go" %}
```go
// Set Ping Interval to 20 seconds
nc, err := nats.Connect("demo.nats.io", nats.Name("API Ping Example"), nats.PingInterval(20*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").
pingInterval(Duration.ofSeconds(20)). // Set Ping Interval
build();
Connection nc = Nats.connect(options);
// Do something with the connection
nc.close();
```
{% endtab %}
{% tab title="JavaScript" %}
```javascript
let nc = NATS.connect({
pingInterval: 20*1000, //20s
url: "nats://demo.nats.io:4222"
});
```
{% endtab %}
{% tab title="Python" %}
```python
nc = NATS()
await nc.connect(
servers=["nats://demo.nats.io:4222"],
# Set Ping Interval to 20 seconds
ping_interval=20,
)
# Do something with the connection.
```
{% endtab %}
{% tab title="Ruby" %}
```ruby
require 'nats/client'
NATS.start(ping_interval: 20) do |nc|
nc.on_reconnect do
puts "Got reconnected to #{nc.connected_server}"
end
nc.on_disconnect do |reason|
puts "Got disconnected! #{reason}"
end
# Do something with the connection
end
```
{% endtab %}
{% tab title="TypeScript" %}
```typescript
// will throw an exception if connection fails
let nc = await connect({
pingInterval: 20*1000, //20s
url: "nats://demo.nats.io:4222"
});
nc.close();
```
{% endtab %}
{% endtabs %}
## 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:
{% tabs %}
{% tab title="Go" %}
```go
// Set maximum number of PINGs out without getting a PONG back
// before the connection will be disconnected as a stale connection.
nc, err := nats.Connect("demo.nats.io", nats.Name("API MaxPing Example"), nats.MaxPingsOutstanding(5))
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").
maxPingsOut(5). // Set max pings in flight
build();
Connection nc = Nats.connect(options);
// Do something with the connection
nc.close();
```
{% endtab %}
{% tab title="JavaScript" %}
```javascript
let nc = NATS.connect({
maxPingOut: 5,
url: "nats://demo.nats.io:4222"
});
```
{% endtab %}
{% tab title="Python" %}
```python
nc = NATS()
await nc.connect(
servers=["nats://demo.nats.io:4222"],
# Set maximum number of PINGs out without getting a PONG back
# before the connection will be disconnected as a stale connection.
max_outstanding_pings=5,
ping_interval=1,
)
# Do something with the connection.
```
{% endtab %}
{% tab title="Ruby" %}
```ruby
require 'nats/client'
NATS.start(max_outstanding_pings: 5) do |nc|
nc.on_reconnect do
puts "Got reconnected to #{nc.connected_server}"
end
nc.on_disconnect do |reason|
puts "Got disconnected! #{reason}"
end
# Do something with the connection
end
```
{% endtab %}
{% tab title="TypeScript" %}
```typescript
// will throw an exception if connection fails
let nc = await connect({
maxPingOut: 5,
url: "nats://demo.nats.io:4222"
});
nc.close();
```
{% endtab %}
{% endtabs %}

View File

@@ -0,0 +1,319 @@
# 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:
{% tabs %}
{% tab title="Go" %}
```go
// This does not apply to the NATS Go Client
```
{% endtab %}
{% tab title="Java" %}
```java
Options options = new Options.Builder().
server("nats://demo.nats.io:4222").
maxControlLine(2 * 1024). // Set the max control line to 2k
build();
Connection nc = Nats.connect(options);
// Do something with the connection
nc.close();
```
{% endtab %}
{% tab title="JavaScript" %}
```javascript
// set this option before creating a connection
NATS.MAX_CONTROL_LINE_SIZE = 1024*2;
let nc = NATS.connect({
url: "nats://demo.nats.io:4222"
});
```
{% endtab %}
{% tab title="Python" %}
```python
# Asyncio NATS client does not allow custom control lines.
```
{% endtab %}
{% tab title="Ruby" %}
```ruby
# There is no need to customize this in the Ruby NATS client.
```
{% endtab %}
{% tab title="TypeScript" %}
```typescript
// control line size is not configurable on TypeScript NATS client.
```
{% endtab %}
{% endtabs %}
## 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.
{% tabs %}
{% tab title="Go" %}
```go
nc, err := nats.Connect("demo.nats.io")
if err != nil {
log.Fatal(err)
}
defer nc.Close()
mp := nc.MaxPayload()
log.Printf("Maximum payload is %v bytes", mp)
// Do something with the max payload
```
{% endtab %}
{% tab title="Java" %}
```java
Connection nc = Nats.connect("nats://demo.nats.io:4222");
long max = nc.getMaxPayload();
// Do something with the max payload
nc.close();
```
{% endtab %}
{% tab title="JavaScript" %}
```javascript
let nc = NATS.connect("nats://demo.nats.io:4222");
// on node you *must* register an error listener. If not registered
// the library emits an 'error' event, the node process will exit.
nc.on('error', (err) => {
t.log('client got an error:', err);
});
nc.on('connect', () => {
t.log(nc.info.max_payload);
});
```
{% endtab %}
{% tab title="Python" %}
```python
nc = NATS()
await nc.connect(servers=["nats://demo.nats.io:4222"])
print("Maximum payload is %d bytes" % nc.max_payload)
# Do something with the max payload.
```
{% endtab %}
{% tab title="Ruby" %}
```ruby
require 'nats/client'
NATS.start(max_outstanding_pings: 5) do |nc|
nc.on_reconnect do
puts "Got reconnected to #{nc.connected_server}"
end
nc.on_disconnect do |reason|
puts "Got disconnected! #{reason}"
end
# Do something with the max_payload
puts "Maximum Payload is #{nc.server_info[:max_payload]} bytes"
end
```
{% endtab %}
{% tab title="TypeScript" %}
```typescript
// connect will happen once - the first connect
nc.on('connect', (nc: Client, url: string, options: ServerInfo) => {
// nc is the connection that connected
t.log('client connected to', url);
t.log('max_payload', options.max_payload);
});
```
{% endtab %}
{% endtabs %}
## 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:
{% tabs %}
{% tab title="Go" %}
```go
opts := nats.GetDefaultOptions()
opts.Url = "demo.nats.io"
// Turn on Pedantic
opts.Pedantic = true
nc, err := opts.Connect()
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").
pedantic(). // Turn on pedantic
build();
Connection nc = Nats.connect(options);
// Do something with the connection
nc.close();
```
{% endtab %}
{% tab title="JavaScript" %}
```javascript
let nc = NATS.connect({
url: "nats://demo.nats.io:4222",
pedantic: true
});
```
{% endtab %}
{% tab title="Python" %}
```python
nc = NATS()
await nc.connect(servers=["nats://demo.nats.io:4222"], pedantic=True)
# Do something with the connection.
```
{% endtab %}
{% tab title="Ruby" %}
```ruby
require 'nats/client'
NATS.start(pedantic: true) do |nc|
nc.on_reconnect do
puts "Got reconnected to #{nc.connected_server}"
end
nc.on_disconnect do |reason|
puts "Got disconnected! #{reason}"
end
nc.close
end
```
{% endtab %}
{% tab title="TypeScript" %}
```typescript
// will throw an exception if connection fails
let nc = await connect({
url: "nats://demo.nats.io:4222",
pedantic: true
});
nc.close();
```
{% endtab %}
{% endtabs %}
## 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:
{% tabs %}
{% tab title="Go" %}
```go
opts := nats.GetDefaultOptions()
opts.Url = "demo.nats.io"
// Turn on Verbose
opts.Verbose = true
nc, err := opts.Connect()
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").
verbose(). // Turn on verbose
build();
Connection nc = Nats.connect(options);
// Do something with the connection
nc.close();
```
{% endtab %}
{% tab title="JavaScript" %}
```javascript
let nc = NATS.connect({
url: "nats://demo.nats.io:4222",
verbose: true
});
```
{% endtab %}
{% tab title="Python" %}
```python
nc = NATS()
await nc.connect(servers=["nats://demo.nats.io:4222"], verbose=True)
# Do something with the connection.
```
{% endtab %}
{% tab title="Ruby" %}
```ruby
require 'nats/client'
NATS.start(verbose: true) do |nc|
nc.on_reconnect do
puts "Got reconnected to #{nc.connected_server}"
end
nc.on_disconnect do |reason|
puts "Got disconnected! #{reason}"
end
nc.close
end
```
{% endtab %}
{% tab title="TypeScript" %}
```typescript
// will throw an exception if connection fails
let nc = await connect({
url: "nats://demo.nats.io:4222",
verbose: true
});
nc.close();
```
{% endtab %}
{% endtabs %}

View 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 %}