GCP 云函数何时确认发布/订阅消息?

Posted

技术标签:

【中文标题】GCP 云函数何时确认发布/订阅消息?【英文标题】:When do GCP cloud functions acknowledge pub/sub messages? 【发布时间】:2021-04-24 19:35:14 【问题描述】:

我有一个从发布/订阅消息触发的云功能。此函数从不显式确认源代码中的消息。

如果源代码中从未发生确认,那么该函数何时确认发布/订阅消息?

更新:当函数崩溃时,我知道不应发生消息确认,但该消息的新函数调用永远不会出现在日志中

可重现的示例

创建一个名为 test_topic

的发布订阅主题

使用触发器 test_topic 创建一个名为 test_function 的云函数。给它所有的默认设置,包括不重试失败。在代码本身中,将语言设置为 python3.7,入口点为 hello_pubsub 和以下代码:

 import base64
 def hello_pubsub(event, context):
     pubsub_message = base64.b64decode(event['data']).decode('utf-8')
     print(pubsub_message)
     raise RuntimeError('error in function')

requirements.txt 保持空白

进入 test_topic 并以 go 作为文本发布消息。

test_function 日志中会出现错误。但是,只有一个函数调用会出现错误,并且即使在几天后仍然会出现这种情况。

【问题讨论】:

guillaume 的答案并不完全正确。事件驱动函数的默认行为是在成功/失败的情况下都确认发布/订阅。如果您希望您的云功能在失败时重试,您应该启用“--retry”参数。使用重试的最佳实践可以在这里找到 -> cloud.google.com/functions/docs/bestpractices/… 我认为这就是他在编辑中所说的 但是“如果函数错误退出,则消息为NACK”语句不是错误的吗? 【参考方案1】:

如果函数正常完成,则消息是确认。如果函数错误退出,则消息为 NACK。


编辑 1

我已经使用 Go 后台功能进行了测试。您需要使用参数--retry 部署您的云功能,以允许重试错误消息。否则,消息不会重试。

在 Go 中,这里是执行重试的情况:

返回错误(相当于 Java 或 Python 中的异常),日志中的状态为“错误” 在日志中执行 log.Fatal() (退出函数(函数崩溃)并显示特定日志)状态“连接错误” 执行显式退出,在日志中显示“连接错误”状态

这里是代码(如果有兴趣)

type PubSubMessage struct 
    Data []byte `json:"data"`



func PubsubError(ctx context.Context, m PubSubMessage) error 

    switch string(m.Data) 
    case "ok":
        return nil
    case "error":
        return errors.New("it's an error")
    case "fatal":
        log.Fatal("crash")
    case "exit":
        os.Exit(1)
    
    return nil

以及我如何部署我的云功能

gcloud beta functions deploy --runtime=go113 --trigger-topic=test-topic \
  --source=function --entry-point=PubsubError --region=us-central1 \
  --retry pubsuberror

【讨论】:

在这种情况下优雅地意味着什么。手动引发的异常算不算优雅? 不,如果你引发了一个异常,而没有在函数中捕获它,函数就会出错退出。 对于我已部署的功能,情况似乎并非如此。如果一个函数崩溃,一个新的函数不会像我预期的那样稍后启动。或者可能必须将重试标志设置为 True 才能发生这种情况? 自动重试,具有指数退避 因此,如果 pub/sub 消息触发了一个函数并且该函数崩溃了,您不应该在日志中看到几个函数崩溃的示例,而不仅仅是一个吗?【参考方案2】:

基于此描述: Google Cloud Pub/Sub Triggers

Cloud Functions 在函数调用成功后在内部确认 Pub/Sub 消息。

我确实理解作为确认的文档引用仅在代码执行完成且没有任何(未捕获的)错误的情况下发生。

同时,虽然执行可能仍在“进行中”,但 Pub/Sub 服务可能会决定从同一 Pub/Sub 消息中触发另一个云功能(实例)。

此问题跟踪器讨论中提供了一些其他详细信息: Cloud Function explicit acknowledgement of a pubsub message

在我看来,独立于调用发生的“成功”或“不成功”,云功能将以幂等方式开发,同时考虑到 Pub/Sub 的“至少一次交付”范式服务。换句话说,云功能的开发方式是正确处理来自一条消息的多次调用。

【讨论】:

以上是关于GCP 云函数何时确认发布/订阅消息?的主要内容,如果未能解决你的问题,请参考以下文章

来自发布/订阅主题的速率限制 GCP 云函数触发器

GCP 云功能未正确接收/确认 PubSub 消息

如何使用 GCP 在 pubsub 模型中一次向所有订阅者发送消息

使用云功能的拉订阅[关闭]

GCP Pubsub 主题持续时间中存在的消息数

我如何确认客户端(安卓应用程序)数据已由 GCP 云功能完成处理?