微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Golang http 自动重试 StatusRequestTimeout (408) 响应

如何解决Golang http 自动重试 StatusRequestTimeout (408) 响应

设置

我有两个不同的应用程序,都是用 Go 编写的。第一个是服务器,第二个是调用服务器的较小的应用程序。他们使用 http 包进行调用,使用 router 包设置端点。

问题

当设备对服务器进行特定调用时,会返回 408 (StatusRequestTimeout) 响应。此响应不是由于我们的服务器实际超时,而只是用于描述错误(更多信息见下文)。设备第一次进行此调用时,它会收到 408 并正常进行。但是,如果再次进行相同的调用,则会在第二个调用完成后立即将新的“第三个”调用发送到服务器。第三次调用与前两次调用相同。没有为此调用启用 http 重试逻辑。

错误

为什么要发出第三个电话?当代码更新为返回 400 状态响应而不是 408 时,不再进行第三次调用。此外,更改不同的调用以返回 408 而不是 400 将开始表现出与发送三次三次调用相同的行为。我一直找不到解释这种行为的文档,也找不到其他描述这种行为的文章

预感

我发现很多像 this 这样的文章表明浏览器有时会重试请求。此外,其他一些类似 this 的 stackoverflow 帖子表明 http 请求不会在没有设置我们自己的重试逻辑的情况下重试。同样,我们已经设置了它,但是没有为这个给定的调用启用它,并且调试显示我们从来没有进入我们的自定义重试逻辑。

我相信这是一个功能。我试图用 Firefox 复制这个,但我没有成功,但是 Edge 表现出相同的行为。然而,Chrome 开发工具(和边缘)只显示两个网络调用,第一个和第三个。我认为它也可能是http库,但很奇怪的是浏览器之间的行为不同。

错误修复

鉴于 408 响应应该包含的性质,我决定不再将它们用于自定义错误响应。在这一点上,我只是更好奇为什么会出现这种行为,我的预感是否正确,或者是否有其他因素在起作用。

解决方法

让我们从方法 is408Message() 开始,它是 here。它检查缓冲区是否带有 408 Request timeout 状态代码。另一个 method 使用此方法检查来自服务器的响应,在 408 Request Timeout 的情况下,persistConn 会因 errServerClosedIdle 错误而关闭。错误是 assignedpersistConn.closed 字段。

在 http Transportmain loop 中,调用 persistConn.roundTrip here 作为错误返回存储在 persistConn.closed 字段中的值。几行below,您可以找到一个名为pconn.shouldRetryRequest 的方法,该方法将persistConn.roundTrip 返回的错误作为参数,并在错误为errServerClosedIdle 时返回true。由于整个操作都被 for 循环包裹,因此请求将再次发送。

分析 shouldRetryRequest method 可能对您很有价值,因为必须满足多个条件才能重试请求。例如第一次使用连接时不会重复请求。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。