如何使用 client_disconnected_before_any_response 调试失败的请求

Posted

技术标签:

【中文标题】如何使用 client_disconnected_before_any_response 调试失败的请求【英文标题】:How to debug failed requests with client_disconnected_before_any_response 【发布时间】:2019-02-15 03:42:13 【问题描述】:

我们有一个由 kubernetes 入口创建的 HTTP(s) Load Balancer,它指向由运行 nginx 和 Ruby on Rails 的一组 pod 形成的后端。

查看负载均衡器日志,我们发现越来越多的请求的响应代码为0statusDetails = client_disconnected_before_any_response

我们正试图了解他发生这种情况的原因,但我们没有发现任何相关信息。 nginx 访问或错误日志中没有任何内容。

这发生在从 GET 到 POST 的多种请求中。

我们还怀疑,有时尽管请求记录了该错误,但请求实际上已传递到后端。例如,我们看到 PG::UniqueViolation 错误,这是由于在我们的注册端点中向后端发送了两次相同的注册请求。

任何形式的帮助将不胜感激。谢谢!


 更新 1

根据请求的 here is the yaml 入口资源文件:


 更新 2

我创建了一个基于日志的 Stackdriver 指标,以计算出现此行为的请求数。这是图表:

大峰值与这些 kubernetes 事件的时间戳大致匹配:

完全错误:Readiness probe failed: Get http://10.48.1.28:80/health_check: net/http: request canceled (Client.Timeout exceeded while awaiting headers)"

因此,后端后面的 pod 的就绪性探测似乎有时会失败,但并非总是如此。

这里是readinessProbe的定义

readinessProbe:
  failureThreshold: 3
  httpGet:
    httpHeaders:
    - name: X-Forwarded-Proto
      value: https
    - name: Host
      value: [redacted]
    path: /health_check
    port: 80
    scheme: HTTP
  initialDelaySeconds: 1
  periodSeconds: 30
  successThreshold: 1
  timeoutSeconds: 5

【问题讨论】:

您能否将负载均衡器的 yaml 添加到您的问题中? 您的后端似乎无法与您的客户对话。您的集群上有任何传出流量规则吗? @mstorkson 为入口添加了 yaml @rico 请注意,并非所有请求都发生这种情况,仅针对其中一些请求(我会说少于 1% 或 5%),所以我不认为这是传出流量防火墙规则的问题。 这些事件是否会随着流量的增加而变得更加频繁?这个负载均衡器服务了多少个 Pod?你的节点的空闲内存/cpu 怎么样? 【参考方案1】:

响应代码 0 和 statusDetails = client_disconnected_before_any_response 表示客户端在负载均衡器能够根据此GCP documentation 提供响应之前关闭连接。

调查它为什么没有及时响应,原因之一可能是来自 nginx 的 keepalive timeouts 和 GCP 负载均衡器之间的差异,即使这很可能会提供由 502 Bad Gateway race condition 引起的 backend_connection_closed_before_data_sent_to_client。

为确保后端响应请求并查看是否需要多长时间,您可以重复此过程几次(因为您仍然会收到一些有效响应):

卷曲响应时间

$ curl -w "@curl.txt" -o /dev/null -s IP_HERE

curl.txt 内容(先创建并保存此文件):

   time_namelookup:  %time_namelookup\n
      time_connect:  %time_connect\n
   time_appconnect:  %time_appconnect\n
  time_pretransfer:  %time_pretransfer\n
     time_redirect:  %time_redirect\n
time_starttransfer:  %time_starttransfer\n
                ----------\n
        time_total:  %time_total\n

如果是这种情况,请查看任何类型循环的注册端点代码,例如您提到的 PG::UniqueViolation 错误。

【讨论】:

感谢您的回答@Daniel。我实际上对article you mentioned 很熟悉,我的nginx 配置中实际上有keepalive_timeout 650;keepalive_requests 10000;。我还尝试将 GCP 后端的超时从默认的 30 秒增加到 60 秒,但问题仍然存在。换句话说,我怀疑这是一个超时问题:( @jävi 感谢您清除超时的可能性。检查您更新的问题我想知道httpHeaders: 对您的应用程序有多重要。 所以X-Forwarded-Proto 存在是因为我们的应用程序使用 HTTPS,但 SSL 在负载均衡器级别得到解析。通过这个标头,我们告诉我们的应用程序(nginx 和后来的 ruby​​ on rails)请求最初是 HTTPS。 Host 标头用于确保 nginx 响应该请求,因为它目前仅限于响应来自我们生产域的请求。 Readiness 探测需要尽可能靠近应用机制,以便在能够回答请求的情况下进行准确反映。但是,如果应用程序真的卡住了,它将重新启动您的 pod 的 liveness probe。根据事件列表,我希望看到一些活动检查失败(除非过滤)。我希望this article,这对我了解如何协调这两个探针有很大帮助,对调查有所帮助。 “表示客户端关闭了连接”——注意这包括中止请求。例如,如果您调用XHR.abort(),或者浏览器会因为导航而自动中止下载静态资产。

以上是关于如何使用 client_disconnected_before_any_response 调试失败的请求的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 CSS 使多个内联块元素居中?

如何在 django 中使用模型进行查询

如何使用 __subclasscheck__ 魔术方法?

python如何使用__new__()函数的参数列表中的属性创建类?

如何在 8051 中使用 __func__

如何正确使用“__beginthreadex”?