当在Go中发出http Get请求时,它会在返回错误之前等待完整的超时时间,即使没有网络连接。
我认为在内部,它很快就知道它失败了;我希望错误尽快传播,而不是等待超时时间。我确实希望它尝试20秒时,网络在那里,只是慢。如何设置具有此行为的客户端?
查看问题的代码:
var client = &http.Client{
Timeout: time.Second * 20,
}
response, err := client.Get(url)
如果重要的话,我正在使用gomobile,它在iOS模拟器上运行。
2条答案
按热度按时间bvjveswy1#
如果没有连接的网络接口,初始TCP握手将失败,此时没有成功的机会。接下来的19.99秒它在做什么?
Go语言的HTTP客户端在没有网络连接时会等待整个超时时间,然后返回错误,因为客户端在发起请求时不知道网络的状态。它只知道在指定的超时时间内没有收到响应。
当客户端无法建立连接时,客户端正在等待操作系统的TCP堆栈返回错误,由于网络配置、操作系统的TCP/IP实现等各种因素,这可能需要一些时间。
我不知道有什么直接的方法可以在Go的HTTP客户端没有网络连接的情况下设置更快的超时。
另一种方法是将上下文与超时和检查网络连接状态的单独goroutine结合使用。如果goroutine检测到没有网络连接,它会取消上下文。
请求将使用
NewRequestWithContext
例如:
你需要实现
isNetworkAvailable()
:检查是否存在可用的网络连接的功能。这可能是特定于平台的,在iOS上,您可能需要使用系统API来检查网络状态。请注意,这种方法可能无法在所有场景中完美工作。例如,网络可以在
isNetworkAvailable()
检查之后,但在HTTP请求发出之前变得可用。在这种情况下,即使网络可用,请求也将被取消。但在已知网络在较长时间内不可用的情况下,它可能会有所帮助。例如:
此函数尝试8.8.8.8在端口53(DNS服务器使用的端口)上建立到www.example.com的TCP连接,超时时间为2秒。
(as JimB在评论中添加:“您所能做的就是尝试使用较短的超时进行一些网络呼叫”)
如果函数在这段时间内无法建立连接,则假定没有网络连接并返回false。
如果可以建立连接,则关闭连接并返回true。
azpvetkf2#
这里的答案很简单:Golang内部能够并且确实知道何时没有网络,并且及时地向上传播故障,而不等待20 s超时。没有任何东西通过网络发送,也没有什么需要等待的。Go似乎可以正确地完成所有事情,并且不需要对示例代码进行任何更改。
该问题仍然持续重现,但仅在iOS模拟器上。这似乎是一个特定于iOS模拟器如何将连接Map到主机操作系统的问题。不确定这是一个长期存在的问题,还是我的MacOS/模拟器配对上的一次性问题。在主机MacOS和真实的的iOS设备上,它可以正常工作,在没有网络接口的情况下立即超时。
不需要额外的请求,因为这只是通往相同结论的另一条路径,这增加了其他失败的可能性。这可能有助于区分网络问题和特定服务的问题,或者更快地获得真实的网络状态(已连接网络接口的存在)的指示器。