【问题标题】:Http 400 on PubSub push to cloud runPubSub 上的 Http 400 推送到云运行
【发布时间】:2020-06-22 09:18:56
【问题描述】:

我目前正在尝试在 GCP 中构建一个简单的文件(仅限 csv)处理系统,基本上它所做的就是在上传新文件时,代码对其进行解析并将其存储在数据库中。

我使用这些命令创建了一个新主题(文件上传)和一个新服务帐户(按照以下步骤操作:https://cloud.google.com/run/docs/tutorials/pubsub#integrating-pubsub):

gcloud projects add-iam-policy-binding my-project \
     --member=serviceAccount:service-0000000000@gcp-sa-pubsub.iam.gserviceaccount.com \
     --role=roles/iam.serviceAccountTokenCreator
   
gcloud iam service-accounts create cloud-run-pubsub-invoker \
   --display-name "Cloud run PubSub Invoker"
   
gcloud run services add-iam-policy-binding myservice \
   --member=serviceAccount:cloud-run-pubsub-invoker@my-project.iam.gserviceaccount.com \
   --role=roles/run.invoker

然后创建订阅:

gcloud pubsub subscriptions create file-upload-sub --topic file-upload \
   --push-endpoint=https://myservice-myurl.a.run.app/api/test/ \
   --push-auth-service-account=cloud-run-pubsub-invoker@my-project.iam.gserviceaccount.com

我有一个存储桶,我使用以下命令将“OBJECT_FINALIZE”事件绑定到它: gsutil notification create -t file-upload -f json -e OBJECT_FINALIZE gs://MyBucket

我的端点具有以下路由(注意:它是部署在云上运行的 docker 映像中的 .net 应用程序):

    [Route("api/[controller]")]
    [ApiController]
    public class TestController : ControllerBase
    {
        //GET : api/test
        [HttpGet]
        public IActionResult Get()
        {
            return Ok($"Get route pinged{Environment.NewLine}");
        }

        //POST : api/test
        [HttpPost]
        public IActionResult Post([FromBody] string bodyContent)
        {
            return Ok($"Content received : {bodyContent}{Environment.NewLine}");
        }
    }

当我使用 curl 命令发送请求时: curl https://myservice-myurl.a.run.app/api/test/ -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" -d '"data"'

一切正常(我在控制台和日志查看器中收到确认消息)但是当我尝试使用 gcloud pubsub topics publish file-upload --message '"test"' 将消息直接推送到主题时,我在日志查看器中只收到 400 个响应,没有有效负载向我解释它在哪里坏了

编辑: 所以显然这是一个与我尝试测试应用程序的方式相关的问题,由于某种原因,当消息是基本字符串时,PubSub 转换了将消息发送到云运行的方式,因此它破坏了 .net 内容验证。我更改了代码以接受参数中文件的元数据,一切正常

编辑 2: 写了一个正确的答案来解释我哪里错了

【问题讨论】:

  • 您能否查看 Pub/Sub (cloud.google.com/pubsub/docs/monitoring) 和 Cloud Run (cloud.google.com/run/docs/monitoring) 的 Cloud Monitoring 指标,以了解您的消息是否已成功发布和传递?
  • 我通常会在推送订阅之外创建一个拉订阅。像这样,我可以拉它(在命令行或控制台中)并查看消息内容。然后我将其复制并手动提交到我的 Cloud Run 服务。
  • 再次运行带有“--verbosity=debug”和“--log-http”的命令,这将获得有关正在发生的事情的更多信息。
  • 终于找到错误了,我编辑了第一个帖子解释一下
  • 当消息是基本字符串时,“PubSub 会改变将消息发送到云运行的方式”是什么意思?

标签: .net google-cloud-platform google-cloud-pubsub google-cloud-run


【解决方案1】:

正如我原始帖子的 cmets 所指出的,我正在写一个正确的答案来解释我错在哪里:

PubSub 发送的数据结构与 curl 不同,因此当我尝试读取收到的数据时,cloud run 响应 400 错误,因为 .net json 到对象验证失败。

起初,我认为 pub sub 只是将元数据文件发送到云运行,事实并非如此。 PubSub 以如下结构发送文件信息:

    public class Body
    {
        public Message Message { get; set; }

        public Body()
        {
            
        }
    }

    public class Message
    {
        public string MessageId { get; set; }
        public string PublishTime { get; set; }
        public string Data { get; set; }

        public Message()
        {
            
        }

        public Message(string messageId, string publishTime, string data)
        {
            MessageId = messageId;
            PublishTime = publishTime;
            Data = data;
        }
    }

因此,当我通过使用 curl 发送基本字符串来测试我的代码时,一切正常,而当我尝试直接在主题中编写消息时却没有。仅仅因为数据结构。

我为此更改了代码:

        public IActionResult Post([FromBody] Body body)
        {
            var base64EncodedBytes = Convert.FromBase64String(body.Message.Data);
            var readableContent = Encoding.UTF8.GetString(base64EncodedBytes);

            var fileMetadata = JsonConvert.DeserializeObject<FileMetadata>(readableContent);

            var accounts = new List<Account>();

            try
            {
                accounts = CsvParser.Parse(fileMetadata.name);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            Console.WriteLine($"{accounts.Count} account(s) detected in csv file");

            return Ok();
        }

【讨论】:

    猜你喜欢
    • 2020-08-30
    • 2021-05-06
    • 1970-01-01
    • 2012-02-19
    • 2017-12-08
    • 1970-01-01
    • 2020-01-03
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多