NATS中文开发文档:发送消息

NATS使用包含目标主题、可选回复主题和字节数组的协议发送和接收消息。有些库可以提供帮助程序来将其他数据格式转换为字节或从字节转换为字节,但是NATS服务器将把所有消息视为不透明的字节数组。
所有的NATS客户机都是为了简化消息的发送。例如,要将字符串“All is Well”作为UTF-8字节字符串发送到“updates”主题,您需要执行以下操作:

nc, err := nats.Connect("demo.nats.io", nats.Name("API PublishBytes Example"))
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

if err := nc.Publish("updates", []byte("All is Well")); err != nil {
    log.Fatal(err)
}

包含一个回复主题

发布消息时的可选回复字段可用于接收端进行响应。对主题的回复通常称为收件箱,大多数库可能提供生成唯一收件箱主题的方法。大多数库还提供了带有单个调用的请求-应答模式。例如,若要向主题时间发送请求,而消息没有内容,则可以:

nc, err := nats.Connect("demo.nats.io")
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Create a unique subject name for replies.
uniqueReplyTo := nats.NewInbox()

// Listen for a single response
sub, err := nc.SubscribeSync(uniqueReplyTo)
if err != nil {
    log.Fatal(err)
}

// Send the request.
// If processing is synchronous, use Request() which returns the response message.
if err := nc.PublishRequest("time", uniqueReplyTo, nil); err != nil {
    log.Fatal(err)
}

// Read the reply
msg, err := sub.NextMsg(time.Second)
if err != nil {
    log.Fatal(err)
}

// Use the response
log.Printf("Reply: %s", msg.Data)

请求-应答语义

在大多数客户端库中,发送消息和接收响应的模式被封装到请求方法中。在此方法封装下,将发布对主题具有唯一答复的消息,并在返回之前等待答复。
在某些库的旧版本中,每次都会创建一个全新的主题回复。在较新的版本中,使用主题层次结构,以便客户端库中的单个订阅服务器侦听通配符,并使用单个主题的唯一子主题发送请求。
请求方法和带应答的发布之间的主要区别在于,库只接受一个响应,在大多数库中,请求将被视为一个同步操作。库甚至可以提供设置超时的方法。
例如,更新上一个发布示例时,我们可能会请求一秒超时的时间:

nc, err := nats.Connect("demo.nats.io")
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Send the request
msg, err := nc.Request("time", nil, time.Second)
if err != nil {
    log.Fatal(err)
}

// Use the response
log.Printf("Reply: %s", msg.Data)

// Close the connection
nc.Close()

您可以将库中的请求-答复看作订阅、获取一条消息、取消订阅模式。在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

您可以将请求-应答模式扩展为通常称为分散聚集的模式。要接收多条消息,在超时的情况下,可以执行以下操作,其中获取消息的循环使用时间作为限制,而不是接收单个消息:

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()

或者,可以在计数器上循环并超时以尝试获取至少N个响应:

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()

Caches, Flush and Ping

出于性能方面的原因,大多数(如果不是全部的话)客户机库将缓冲出的数据,以便更大的数据块可以一次写入网络。这可能像字节缓冲区一样简单,它在被推送到网络之前存储一些消息。
这些缓冲区不会永远保存消息,通常它们被设计为在高吞吐量情况下保存消息,而在低吞吐量情况下仍然提供良好的延迟。
确保消息以高性能的方式流动是库的工作。但有时应用程序需要知道消息已经“触网”,在这种情况下,应用程序可以使用flush调用告诉库在系统中移动数据。

nc, err := nats.Connect("demo.nats.io")
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

// Just to not collide using the demo server with other users.
subject := nats.NewInbox()

if err := nc.Publish(subject, []byte("All is Well")); err != nil {
    log.Fatal(err)
}
// Sends a PING and wait for a PONG from the server, up to the given timeout.
// This gives guarantee that the server has processed the above message.
if err := nc.FlushTimeout(time.Second); err != nil {
    log.Fatal(err)
}
Flush and Ping/Pong

许多客户机库使用NATS协议中内置的PING/PONG交互来确保flush将所有缓冲消息推送到服务器。当应用程序调用flush时,大多数库将在消息的传出队列上放置一个PING,并等待服务器使用PONG响应,然后再声明flush成功。
即使客户端可能使用PING/PONG进行刷新,但以这种方式发送的PING不计入最大传出PING。

发送结构化数据

一些客户端库提供帮助程序来发送结构化数据,而另一些客户端库则依赖于应用程序来执行任何编码和解码,并且只接受字节数组进行发送。下面的示例演示了如何发送JSON,但是可以很容易地将其更改为发送protobuffer、YAML或其他格式。JSON是一种文本格式,因此我们还必须将大多数语言中的字符串编码为字节。我们使用的是UTF-8,JSON标准编码。
用一个简单的股票行情器发送每只股票的符号和价格:

nc, err := nats.Connect("demo.nats.io")
if err != nil {
    log.Fatal(err)
}
defer nc.Close()

ec, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER)
if err != nil {
    log.Fatal(err)
}
defer ec.Close()

// Define the object
type stock struct {
    Symbol string
    Price  int
}

// Publish the message
if err := ec.Publish("updates", &stock{Symbol: "GOOG", Price: 1200}); err != nil {
    log.Fatal(err)
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页