Request-Reply in Messaging
Code
package main
import (
"fmt"
"os"
"time"
"github.com/nats-io/nats.go"
)
func main() {
Use the env varibale if running in the container, otherwise use the default.
url := os.Getenv("NATS_URL")
if url == "" {
url = nats.DefaultURL
}
Create an unauthenticated connection to NATS.
nc, _ := nats.Connect(url)
defer nc.Drain()
In addition to vanilla publish-request, NATS supports request-reply interactions as well. Under the covers, this is just an optimized pair of publish-subscribe operations. The request handler is just a subscription that responds to a message sent to it. This kind of subscription is called a service. For this example, we can use the built-in asynchronous subscription in the Go SDK.
sub, _ := nc.Subscribe("greet.*", func(msg *nats.Msg) {
Parse out the second token in the subject (everything after greet.) and use it as part of the response message.
name := msg.Subject[6:]
msg.Respond([]byte("hello, " + name))
})
Now we can use the built-in Request
method to do the service request.
We simply pass a nil body since that is being used right now. In addition,
we need to specify a timeout since with a request we are waiting for the
reply and we likely don’t want to wait forever.
rep, _ := nc.Request("greet.joe", nil, time.Second)
fmt.Println(string(rep.Data))
rep, _ = nc.Request("greet.sue", nil, time.Second)
fmt.Println(string(rep.Data))
rep, _ = nc.Request("greet.bob", nil, time.Second)
fmt.Println(string(rep.Data))
What happens if the service is unavailable? We can simulate this by unsubscribing our handler from above. Now if we make a request, we will expect an error.
sub.Unsubscribe()
_, err := nc.Request("greet.joe", nil, time.Second)
fmt.Println(err)
}
Output
Network f540e0ef_default Creating Network f540e0ef_default Created Container f540e0ef-nats-1 Creating Container f540e0ef-nats-1 Created Container f540e0ef-nats-1 Starting Container f540e0ef-nats-1 Started hello, joe hello, sue hello, bob nats: no responders available for request