【问题标题】:"new style" google pubsub golang functions not working right“新风格” google pubsub golang 功能无法正常工作
【发布时间】:2016-04-01 20:18:16
【问题描述】:

我正在尝试使用Go pubsub library 来对抗local emulated pubsub server。我发现“旧样式”(已弃用)函数(例如 CreateSubPullWait)可以正常工作,但“新样式”API(例如 IteratorsSubscriptionHandles)无法按预期工作。

我编写了两个不同的单元测试,它们都测试相同的动作序列,一个使用“新风格”API,一个使用“旧风格”API。

顺序是:

  • 创建订阅
  • 无法提取任何消息(因为没有可用消息)
  • 发布消息
  • 提取该消息,但不确认它
  • 最后再拉一次,这需要 10 秒,因为消息 ACK 超时必须先过期

https://gist.github.com/ianrose14/db6ecd9ccb6c84c8b36bf49d93b11bfb

使用旧式 API 的测试正如我所料:

=== RUN   TestPubSubRereadLegacyForDemo
--- PASS: TestPubSubRereadLegacyForDemo (10.32s)
    pubsubintg_test.go:217: PullWait returned in 21.64236ms (expected 0)
    pubsubintg_test.go:228: PullWait returned in 10.048119558s (expected 10s)
PASS

而使用新式 API 的测试工作不可靠。有时事情会按预期工作:

=== RUN   TestPubSubRereadForDemo
--- PASS: TestPubSubRereadForDemo (11.38s)
    pubsubintg_test.go:149: iter.Next() returned in 17.686701ms (expected 0)
    pubsubintg_test.go:171: iter.Next() returned in 10.059492646s (expected 10s)
PASS

但有时我发现iter.Stop() 并没有按应有的方式及时返回(并注意第二个 iter.Next 比它应该的时间长得多):

=== RUN   TestPubSubRereadForDemo
--- FAIL: TestPubSubRereadForDemo (23.87s)
    pubsubintg_test.go:149: iter.Next() returned in 7.3284ms (expected 0)
    pubsubintg_test.go:171: iter.Next() returned in 20.074994835s (expected 10s)
    pubsubintg_test.go:183: iter.Stop() took too long (2.475055901s)
FAIL

而其他时候我发现发布消息后的第一次拉取时间太长(应该接近即时):

=== RUN   TestPubSubRereadForDemo
--- FAIL: TestPubSubRereadForDemo (6.32s)
    pubsubintg_test.go:147: failed to pull message from iterator: context deadline exceeded
FAIL

有什么想法吗?是否有任何使用新型 API 的工作示例?不幸的是,Go starter project here 使用的是旧的、已弃用的 API。

【问题讨论】:

    标签: go google-cloud-pubsub


    【解决方案1】:

    (注意:您的示例输出中的行号似乎与您链接的代码不匹配。)

    但有时我发现 iter.Stop() 并没有按应有的及时返回

    最近进行了一些更改,这些更改修复了调用 iter.Stop 时的过度延迟。如果所有消息都已被确认,它现在应该立即返回。尝试同步并再次对其进行测试。

    (并注意第二个 iter.Next 比它应该长得多):

    在您使用新 API 的代码中,您首先使用具有 1 秒截止日期的上下文从空订阅中拉取。我们称之为“拉取请求 A”。尽管取消了基础 http 请求,但似乎连接并没有以服务器尊重的任何方式关闭。因此,就服务器而言,“A”仍处于未决状态。发布后,您立即提出一个新的拉取请求,我们称之为“B”。通过拉取请求 B 返回消息后,您将消息保持未确认状态,然后发出另一个拉取请求“C”。

    现在,当您发布消息时,服务器会将其传递给“A”或“B”。如果它首先将其交付给“A”,您将看到第一次拉取超过 5 秒上下文截止日期。如果它首先发布到“B”,您将看到第一个拉取快速返回,正如预期的那样。在消息发布到“B”并且未确认后,服务器会将其重新传递到“A”或“C”。如果它首先选择“A”,那么第二次拉动的时间将比预期的要长。如果它选择“C”,那么您将看到第一次和第二次拉动所花费的时间与您预期的一样长。

    如果您不从空订阅中进行初始拉取,您应该会看到您的测试行为符合您的预期。

    注意:当您使用旧 API 时,您看不到任何这些,因为您没有使用旧 API 执行额外的“从空订阅中拉取”请求(可能是因为它不正确支持可取消的上下文)。

    顺便说一句:如果你想不回复消息,你应该调用 Message.Done(false)。

    【讨论】:

    • 在提取过去几天的提交后,我确实看到 iter.Stop() 按预期工作 - 谢谢。关于您对第一个拉取请求(“A”)没有完全关闭的评论,这是一个 pubsub 错误吗?或者我可以解决的问题?否则这对我来说似乎是地雷。
    • 这尤其不是 Go 库的属性:如果您在发布消息之前使用其他机制发出(并取消)拉取请求,您将看到相同的行为。
    猜你喜欢
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 2013-04-08
    • 2013-11-06
    • 2013-10-29
    • 1970-01-01
    相关资源
    最近更新 更多