Skip to content

Commit

Permalink
Merge pull request #516 from nats-io/fix_515
Browse files Browse the repository at this point in the history
[ADDED] Doc: how to configure NATS options when embedding Streaming server
  • Loading branch information
kozlovic committed Mar 16, 2018
2 parents 0fe69da + 0d5832a commit 7889f37
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 9 deletions.
115 changes: 115 additions & 0 deletions README.md
Expand Up @@ -41,6 +41,7 @@ NATS Streaming provides the following high-level feature set.
- [Getting Started](#getting-started)
* [Building](#building)
* [Running](#running)
* [Embedding NATS Streaming](#embedding-nats-streaming)
- [Configuring](#configuring)
* [Command line arguments](#command-line-arguments)
* [Configuration file](#configuration-file)
Expand Down Expand Up @@ -1057,6 +1058,120 @@ The server will be started and listening for client connections on port 4222 (th

Note that you do not need to start the embedded NATS Server. It is started automatically when you run the NATS Streaming Server. See below for details on how you secure the embedded NATS Server.

## Embedding NATS Streaming

Embedding a NATS Streaming Server in your own code is easy. Simply import:

```
stand "github.com/nats-io/nats-streaming-server/server"
```

(Note: we chose `stand` here, but you don't have to use that name)

Then if you want to use default options, it is as simple as doing:

```
s, err := stand.RunsServer("mystreamingserver")
```

If you want a more advance configuration, then you need to pass options.
For instance, let's start the server with a file store instead of memory.

First import the stores package so we have access to the store type.

```
stores "github.com/nats-io/nats-streaming-server/stores"
```

Then get the default options and override some of them:

```
opts := stand.GetDefaultOptions()
opts.StoreType = stores.TypeFile
opts.FilestoreDir = "datastore"
s, err := stand.RunServerWithOpts(opts, nil)
```

However, since the NATS Streaming Server project vendors NATS Server (that it uses as the communication layer with its clients and other servers in the cluster), there are some limitations.

If you were to import `github.com/nats-io/gnatsd/server`, instantiate a NATS `Options` structure, configure it and pass it to the second argument of `RunServerWithOpts`, you would get a compiler error. For instance doing this does not work:

```
import (
natsd "github.com/nats-io/gnatsd/server"
stand "github.com/nats-io/nats-streaming-server/server"
stores "github.com/nats-io/nats-streaming-server/stores"
)
(...)
nopts := &natsd.Options{}
nopts.Port = 4223
s, err := stand.RunServerWithOpts(nil, nopts)
```

You would get:

```
./myapp.go:36:35: cannot use nopts (type *"myapp/vendor/github.com/nats-io/gnatsd/server".Options) as type *"myapp/vendor/github.com/nats-io/nats-streaming-server/vendor/github.com/nats-io/gnatsd/server".Options in argument to "myapp/vendor/github.com/nats-io/nats-streaming-server/server".RunServerWithOpts
```

To workaround this issue, the NATS Streaming Server package provides a function `NewNATSOptions()` that is suitable for this approach:

```
nopts := stand.NewNATSOptions()
nopts.Port = 4223
s, err := stand.RunServerWithOpts(nil, nopts)
```

That will work.

But, if you want to do advanced NATS configuration that requires types or interfaces that belong to the NATS Server package, then this approach won't work.
In this case you need to run the NATS Server indepently and have the NATS Streaming Server connects to it. Here is how:

```
// This configure the NATS Server using natsd package
nopts := &natsd.Options{}
nopts.HTTPPort = 8222
nopts.Port = 4223
// Setting a customer client authentication requires the NATS Server Authentication interface.
nopts.CustomClientAuthentication = &myCustomClientAuth{}
// Create the NATS Server
ns := natsd.New(nopts)
// Start it as a go routine
go ns.Start()
// Wait for it to be able to accept connections
if !ns.ReadyForConnections(10 * time.Second) {
panic("not able to start")
}
// Get NATS Streaming Server default options
opts := stand.GetDefaultOptions()
// Point to the NATS Server with host/port used above
opts.NATSServerURL = "nats://localhost:4223"
// Now we want to setup the monitoring port for NATS Streaming.
// We still need NATS Options to do so, so create NATS Options
// using the NewNATSOptions() from the streaming server package.
snopts := stand.NewNATSOptions()
snopts.HTTPPort = 8223
// Now run the server with the streaming and streaming/nats options.
s, err := stand.RunServerWithOpts(opts, snopts)
if err != nil {
panic(err)
}
```

The above seem involved, but it really only if you use very advanced NATS Server options.

# Configuring

## Command line arguments
Expand Down
19 changes: 10 additions & 9 deletions server/server.go
Expand Up @@ -32,7 +32,7 @@ import (
"github.com/nats-io/nats-streaming-server/util"
)

// A single STAN server
// A single NATS Streaming Server

// Server defaults.
const (
Expand Down Expand Up @@ -529,7 +529,7 @@ func (c *channel) getAckSubject() string {
return fmt.Sprintf("%s.%s", c.stan.info.AcksSubs, c.name)
}

// StanServer structure represents the STAN server
// StanServer structure represents the NATS Streaming Server
type StanServer struct {
// Keep all members for which we use atomic at the beginning of the
// struct and make sure they are all 64bits (or use padding if necessary).
Expand Down Expand Up @@ -644,7 +644,7 @@ type subStore struct {
qsubs map[string]*queueState // queue subscribers
durables map[string]*subState // durables lookup
acks map[string]*subState // ack inbox lookup
stan *StanServer // back link to Stan server
stan *StanServer // back link to the server
}

// Holds all queue subsribers for a subject/group and
Expand Down Expand Up @@ -1080,7 +1080,7 @@ func (ss *subStore) LookupByAckInbox(ackInbox string) *subState {
return sub
}

// Options for STAN Server
// Options for NATS Streaming Server
type Options struct {
ID string
DiscoverPrefix string
Expand Down Expand Up @@ -1119,7 +1119,7 @@ func (o *Options) Clone() *Options {
return &clone
}

// DefaultOptions are default options for the STAN server
// DefaultOptions are default options for the NATS Streaming Server
var defaultOptions = Options{
ID: DefaultClusterID,
DiscoverPrefix: DefaultDiscoverPrefix,
Expand All @@ -1133,7 +1133,7 @@ var defaultOptions = Options{
ClientHBFailCount: DefaultMaxFailedHeartBeats,
}

// GetDefaultOptions returns default options for the STAN server
// GetDefaultOptions returns default options for the NATS Streaming Server
func GetDefaultOptions() (o *Options) {
opts := defaultOptions
opts.StoreLimits = stores.DefaultStoreLimits
Expand Down Expand Up @@ -1311,15 +1311,16 @@ func NewNATSOptions() *server.Options {
return &opts
}

// RunServer will startup an embedded STAN server and a nats-server to support it.
// RunServer will startup an embedded NATS Streaming Server and a nats-server to support it.
func RunServer(ID string) (*StanServer, error) {
sOpts := GetDefaultOptions()
sOpts.ID = ID
nOpts := DefaultNatsServerOptions
return RunServerWithOpts(sOpts, &nOpts)
}

// RunServerWithOpts will startup an embedded STAN server and a nats-server to support it.
// RunServerWithOpts allows you to run a NATS Streaming Server with full control
// on the Streaming and NATS Server configuration.
func RunServerWithOpts(stanOpts *Options, natsOpts *server.Options) (newServer *StanServer, returnedError error) {
var sOpts *Options
var nOpts *server.Options
Expand Down Expand Up @@ -4656,7 +4657,7 @@ func (s *StanServer) startGoRoutine(f func()) {
s.mu.Unlock()
}

// ClusterID returns the STAN Server's ID.
// ClusterID returns the NATS Streaming Server's ID.
func (s *StanServer) ClusterID() string {
s.mu.RLock()
defer s.mu.RUnlock()
Expand Down

0 comments on commit 7889f37

Please sign in to comment.