【问题标题】:Random Connection Error in Google Cloud Functions (Python)Google Cloud Functions (Python) 中的随机连接错误
【发布时间】:2020-06-23 17:19:13
【问题描述】:

因为过去几周我的浏览器控制台中出现了一些意外的 CORS 错误,所以我在 Google Cloud Functions 中设置了一个超级简单的 Python 脚本,其中包含一个函数:

def prepData(request):

    if request.method == 'OPTIONS':
        headers = {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'POST',
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Max-Age': '3600'
        }
        return ('', 204, headers)

    headers = {
        'Access-Control-Allow-Origin': '*'
    }
    return ("", 200, headers)

它看起来与 Google 在其 documentation page 上提供的功能非常相似,但有一个主要区别:我使用的是 POST 而不是 GET。

调用该函数时,我在大约 50% 的情况下看到成功消息 (Function execution took 13 ms, finished with status code: 200),在所有其他情况下看到连接错误 (Function execution took 11 ms, finished with status: 'connection error')。每当我在 GCF 中遇到连接错误时,Chrome 的控制台都会记录一个错误:No 'Access-Control-Allow-Origin' header is present on the requested resource.

我目前正在考虑三种可能的原因:

  1. GCP 基础架构。我发现了一些相关问题,其中 Google 承认了一些基础架构问题。
  2. Python 错误
  3. CORS 错误(用户 sideshowbarker 说:不太可能)

问题的原因是什么,我该如何解决?


下面是调用 Python 脚本的 JS 代码:

    const xhr = new XMLHttpRequest();
    xhr.open("POST", "[URL]");
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.send(stringified_serialized_data);

20 年 4 月 2 日编辑:

我发现了一种不触发错误的方法:在两个返回语句之间添加一些代码。我还没有弄清楚需要什么样的代码,但d = request.get_json() 似乎就足够了。新代码如下所示:

def prepData(request):

    if request.method == 'OPTIONS':
        headers = {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'POST',
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Max-Age': '3600'
        }
        return ('', 204, headers)

    d = request.get_json() #THIS LINE IS NEW

    headers = {
        'Access-Control-Allow-Origin': '*'
    }
    return ("", 200, headers)

【问题讨论】:

  • 这看起来不像云函数,它的签名类似于def function_name(request)。您能否将您在此处部署的功能也包括在内,它也调用prepData?
  • @DustinIngram 嗯,我不太明白你的意思。我目前正在使用内联编辑器 (cloud.google.com/functions/img/qs-python-console.png)。在代码输入字段下方,它显示“要执行的功能”,我在其中添加了“prepData”。我可以轻松地重命名该函数并重命名请求参数。也就是说,它已经这样工作了大约一年。
  • 知道了,我认为json_data 变量名让我失望了。这个变量实际上是一个请求,而不仅仅是 JSON 数据。
  • 明白,谢谢!这也解释了为什么 json_data.method 有一个值。我将对此进行调查并更改参数名称以进行澄清。但是,我认为这与上述主要问题无关。
  • 您可以安全地排除 CORS 作为可能的原因。问题中显示的 CORS 配置绝不会导致连接错误。所以总的来说,CORS 与问题无关。当您收到连接错误时,浏览器记录该 CORS 消息的唯一原因是浏览器在这种情况下得到的响应没有 Access-Control-Allow-Origin 标头 - 但这是正常的和预期的。连接错误情况下的任何响应都不会有 Access-Control-Allow-Origin 标头。

标签: python google-cloud-platform xmlhttprequest google-cloud-functions


【解决方案1】:

我通过增加分配给云功能的 RAM 解决了这个问题。发生此问题时,我的有 512MB。我将它增加到 1GB,它开始像魅力一样工作。

【讨论】:

    【解决方案2】:

    更新

    进一步挖掘后,我们意识到问题实际上是 Google Cloud Function 服务中的一个错误。此错误特别影响使用 Python 运行时的云功能。如果这些函数收到正文大于约 10 KB 的 HTTP POST 请求,它们将引发连接错误(并将返回代码 500)。有趣的是,这种情况不会发生在具有此类特征的每个请求中,但在大多数请求中都会发生。

    Google 支持服务已获悉此问题,并承认了该错误。他们创建了a public issue in their issue tracker,应根据解决方案的进度使用其他信息进行更新。在撰写本文时,该问题被标记为“新”。

    解决方法:正如@Timon 所建议的,在函数中调用request.get_json() 似乎可以解决带有JSON 主体的请求的问题。如果您的请求正文使用不同的格式,这将不起作用。


    老答案

    我刚刚使用您提供的完全相同的代码设置了一个干净的 GC 函数,它完美地工作。我可以通过浏览器发出请求(使用您的 JS 代码),它们永远不会失败。

    这给我们留下了两个选择:

    1. 您的浏览器或 Internet 连接中的某些问题导致您的某些请求失败。
    2. 您的 GCF 中存在导致错误的内容。

    对于选项 1,请检查:

    • 失败的请求是否分批出现?或者他们是随机抽样的?如果它们成批出现,则问题可能出在您的互联网连接上。
    • 您是否在使用某种 VPN 或代理?尝试禁用它。
    • 您是否尝试过多种浏览器?如果没有,请尝试。所描述的行为是否都相同?

    对于选项 2,请检查:

    • 您的函数与您发布的代码完全相同吗?如果不是,并且代码更多,那么问题可能就在那里。
    • 您是否使用某些命令行工具部署您的函数?是的,尝试通过 GCP 网站的内联编辑器来完成。
    • 在功能的网络设置中(在高级设置中),请务必选择“允许所有流量”

    【讨论】:

    • 非常感谢您帮助我调试代码/设置!在浏览您的答案时,我确实了解了“导致”问题的原因:我正在解析到函数的字符串化 JSON 对象。我玩了一下,并且能够通过解析足够大的 JSON 对象来在调用你的函数时强制出错(>100KB 几乎每次都会给你一个错误,但 50KB 左右就足够了);您应该会在您身边看到连接错误警告。我可能在这里遗漏了一些东西。我是否超出了限制?根据这个页面,我应该没问题:cloud.google.com/functions/quotas
    • 哇,您似乎在 Google Cloud Platform 中发现了一个错误:主体大于 50KB 的 POST 请求有时会失败。请求是否通过浏览器发出并不重要,使用 Postman 我得到了同样的错误。这也不是函数中的内存问题。我终于发现问题与他们的 Python 3.7 运行时有关,因为如果您使用 Node 运行时,则不会发生这种情况。我联系了技术支持团队,他们应该会尽快提供答复。
    • 您有没有收到 Google 的回复?我试过联系他们,但他们一点帮助都没有。目前正在考虑切换到 AWS Lambda。
    • 我一直在向支持服务发送电子邮件,但速度很慢。三天前,他们告诉我这个问题已经转给了 Cloud Function 工程团队。同时,您可以尝试使用 Node 运行时(虽然不是 Python)或按照您的建议切换到 AWS Lambda。
    • @Timon 我可以确认使用request.get_json() 可以解决我的问题,但仅适用于使用 JSON 格式的请求。我使用此信息和从支持服务获得的问题跟踪器链接更新了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 2019-07-11
    • 2017-11-17
    • 1970-01-01
    • 2017-12-31
    • 1970-01-01
    • 2019-05-26
    相关资源
    最近更新 更多