谷歌云平台推送订阅发送重复消息 ID 字段
Posted
技术标签:
【中文标题】谷歌云平台推送订阅发送重复消息 ID 字段【英文标题】:Google Cloud Platform push subscription sending duplicate message ID fields 【发布时间】:2021-09-30 02:12:32 【问题描述】:我们有一个 GCP 发布订阅主题,其中包含指向 Cloud Run 应用的推送订阅。推送订阅正在向我们的 Cloud Run 端点发送以下 json,其中包含重复的 messageId/message_id 字段:
"message":
"attributes":
"bucketId": "...",
"eventTime": "2021-07-22T15:56:45.913174Z",
"eventType": "OBJECT_FINALIZE",
"notificationConfig": "...",
"objectGeneration": "1626969405908262",
"objectId": "...",
"payloadFormat": "JSON_API_V1"
,
"data": "...",
"messageId": "2717017549133308",
"message_id": "2717017549133308",
"publishTime": "2021-07-22T15:56:46.081Z",
"publish_time": "2021-07-22T15:56:46.081Z"
,
"subscription": "projects/.../subscriptions/..."
当我们尝试将此 json 转换为 ReceivedMessage protobuf 对象时出现问题:
import com.google.pubsub.v1.ReceivedMessage;
ReceivedMessage.Builder receivedMessageBuilder = ReceivedMessage.newBuilder();
JsonFormat.parser().merge(json, receivedMessageBuilder);
我在我的 Cloud Run 应用中使用最新版本的 protobuf-java:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.17.3</version>
</dependency>
由于 json 是由 GCP 生成的,并且我们正在将 json 转换为 Google 定义的 protobuf 对象,我希望它可以正常工作。但相反,我们收到以下错误:
Caused by: com.google.protobuf.InvalidProtocolBufferException: Field google.pubsub.v1.PubsubMessage.message_id has already been set.
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeField(JsonFormat.java:1648)
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeMessage(JsonFormat.java:1500)
at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1458)
at com.google.protobuf.util.JsonFormat$ParserImpl.parseFieldValue(JsonFormat.java:1999)
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeField(JsonFormat.java:1663)
at com.google.protobuf.util.JsonFormat$ParserImpl.mergeMessage(JsonFormat.java:1500)
at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1458)
at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1340)
at com.google.protobuf.util.JsonFormat$Parser.merge(JsonFormat.java:476)
我在这里做错了吗?如果我手动删除重复的字段(messageId
和 publishTime
),则消息会按预期转换得很好。但是由于 json 是由 GCP 在内部生成的,所以我在云环境中无法控制它。有人对我如何成功地将这个 json 转换为 com.google.pubsub.v1.ReceivedMessage
有任何建议吗?
【问题讨论】:
【参考方案1】:不幸的是,JSON 中字段的表示方式发生了变化。原本使用“message_id”和“publish_time”,但为了匹配Protocol Buffer JSON standards,分别改为“publishTime”和“messageId”。为了确保那些依赖旧方式的人的向后兼容性,两者都被写入消息中。多年来,JSON 解析器中对这种情况的支持发生了变化,并且有一个 open issue for protocol buffers 来处理它。目前,唯一的选择是在调用 JsonFormat.parser().merge
之前从收到的 JSON 中删除字段。
【讨论】:
好的,很好的信息,谢谢!我最终提供了自己的 POJO,它反映了 ReceivedMessage protobuf,使用com.fasterxml.jackson.databind.ObjectMapper
反序列化 json,并以这种方式提取有效负载。以上是关于谷歌云平台推送订阅发送重复消息 ID 字段的主要内容,如果未能解决你的问题,请参考以下文章