GCP PubSub-如何排队异步消息?

时间:2019-03-28 18:34:45

标签: google-cloud-pubsub

我想了解有关gcp的pubsub环境中发布者设置的信息。我想排队将通过google函数使用的邮件。为此,发布会在达到一定数量的消息时或从某个时间开始触发。

我将主题设置如下:

topic.PublishSettings = pubsub.PublishSettings{
        ByteThreshold:  1e6, // Publish a batch when its size in bytes reaches this value. (1e6 = 1Mo)
        CountThreshold: 100, // Publish a batch when it has this many messages.
        DelayThreshold: 10 * time.Second, // Publish a non-empty batch after this delay has passed.
    }

当我调用发布功能时,每次调用都会有10秒的延迟。邮件未添加到队列中...

for _, v := range list {
    ctx := context.Background()
    res := a.Topic.Publish(ctx, &pubsub.Message{Data: v})

    // Block until the result is returned and a server-generated
    // ID is returned for the published message.
    serverID, err = res.Get(ctx)
    if err != nil {
        return "", err
    }
}

有人可以帮助我吗?

欢呼

1 个答案:

答案 0 :(得分:1)

为发布方提供批量处理的目的是在向Google Cloud Pub / Sub发送消息时提高成本效率。鉴于该服务的最小计费单位为1KB,因此在同一发布请求中发送多个消息可能会更便宜。例如,发送两个0.5KB的消息作为单独的发布请求将导致更改为发送2KB的数据(每个1KB)。如果将其批量处理为一个发布请求,则将按1KB数据收费。

批处理的权衡因素是延迟:要填充批处理,发布者必须等待接收更多消息以进行批处理。三个批处理属性(ByteThreshold,CountThreshold和DelayThreshold)使您可以控制权衡级别。前两个属性控制单个批处理中放入多少数据或多少条消息。最后一个属性控制发布者应等待多长时间发送一批。

例如,假设您将CountThreshold设置为100。如果您发布的消息很少,则可能需要一段时间才能接收100条消息进行批量发送。这意味着该批消息的等待时间会更长,因为它们正坐在客户端中等待发送。将DelayThreshold设置为10秒,这意味着如果批次中有100条消息,则将发送一个批次;如果至少10秒钟前收到批次中的第一条消息,则将发送该批次。因此,这限制了引入延迟的数量,以使单个批处理中具有更多数据。

您所拥有的代码将导致只包含一条消息的批处理,每条消息的发布时间为10秒。原因是对res.Get(ctx)的调用,它将一直阻塞,直到消息成功发送到服务器为止。将CountThreshold设置为100,DelayThreshold设置为10秒,则循环内发生的顺序是:

  1. 调用Publish会将消息批量发布。
  2. 该批次正在等待接收更多的99条消息,或者等待10秒钟,然后再将其发送到服务器。
  3. 代码正在等待将此消息发送到服务器并返回serverID
  4. 鉴于该代码直到Publish返回时才再次调用res.Get(ctx),它会等待10秒发送批处理。
  5. res.Get(ctx)对于单个消息返回serverID
  6. 回到1。

如果您实际上想将邮件一起批处理,则不能在下一个res.Get(ctx)调用之前调用Publish。您可能需要在goroutine中调用publish(因此,每条消息只有一个例程),或者要聚集列表中的res对象,然后在循环外对其调用Get

    var res []*PublishResult
    ctx := context.Background()
    for _, v := range list {
        res = append(res, a.Topic.Publish(ctx, &pubsub.Message{Data: v}))
    }
    for _, r := range res  {
        serverID, err = r.Get(ctx)
        if err != nil {
            return "", err
        }
    }

需要记住的一点是,批处理将优化发布方而不是订阅方的成本。 Cloud Functions是使用push subscriptions构建的。这意味着必须一次一次将消息传递给订户(因为响应代码是用于确认或否定每条消息的方式),这意味着没有成批的消息传递给订户。