gokubernetesnats.iokubernetes-custom-resourcesnats-streaming-server

Testing NATS-streaming in Kubernetes with minimal effort


I wanted to test a very basic application for NATS-streaming on Kubernetes. To do so, I followed the commands from the official NATS-docs.

It basically comes down to running

kubectl apply -f https://raw.githubusercontent.com/nats-io/k8s/master/nats-server/single-server-nats.yml
kubectl apply -f https://raw.githubusercontent.com/nats-io/k8s/master/nats-streaming-server/single-server-stan.yml

in a terminal with access to the cluster (it's a kind-cluster in my case).

I used stan.go as the NATS-streaming-client. Here is the code I tried to connect to the NATS-streaming-server:

package main

import stan "github.com/nats-io/stan.go"

func main() {
    sc, err := stan.Connect("stan", "test-client")

    if err != nil {
        panic(err)
    }
    if err := sc.Publish("test-subject", []byte("This is a test-message!")); err != nil {
        panic(err)
    }
}

and this is the error I'm getting:

panic: nats: no servers available for connection

goroutine 1 [running]:
main.main()
    /Users/thilt/tmp/main.go:9 +0x15d
exit status 2

so I think another name was used for the cluster or something. If I use the provided example with nats-box from the docs.nats-link above, it also doesn't work! Where did I go wrong here?

I will happily provide more information, if needed.


Solution

  • There is a great example in stan.go docs:

    // Connect to NATS
    nc, err := nats.Connect(URL, opts...)
    if err != nil {
        log.Fatal(err)
    }
    defer nc.Close()
    
    sc, err := stan.Connect(clusterID, clientID, stan.NatsConn(nc))
    if err != nil {
        log.Fatalf("Can't connect: %v.\nMake sure a NATS Streaming Server is running at: %s", err, URL)
    }
    defer sc.Close()
    

    Your error happens because by default stan connects to localhost address (source code):

    // DefaultNatsURL is the default URL the client connects to
    DefaultNatsURL = "nats://127.0.0.1:4222"
    

    Notice that povided above example overwrite this default connection.

    Stan source code is short and easy to analyze. I really recommend you to try to analyze it and figure out what it does.


    Now let's put it all together; here is a working example:

    package main
    
    import (
        nats "github.com/nats-io/nats.go"
        stan "github.com/nats-io/stan.go"
    )
    
    func main() {
        // Create a NATS connection 
        nc, err := nats.Connect("nats://nats:4222")
        if err != nil {
            panic(err)
        }
    
        // Then pass it to the stan.Connect() call.
        sc, err := stan.Connect("stan", "me", stan.NatsConn(nc))
        if err != nil {
            panic(err)
        }
        if err := sc.Publish("test-subject", []byte("This is a test-message!")); err != nil {
            panic(err)
        }
    }