不信任默认超时

2020-08-29 21:12:22

现代应用程序不会崩溃;它们会挂起。其中一个主要原因是假设网络是可靠的。不是的。

当您在没有设置超时的情况下进行网络调用时,您是在告诉您的代码您百分之百确信调用将会成功。你真的愿意打赌吗?

如果您正在进行一个永远不会返回的同步网络调用,那么您的线程至少会永远占用您的线程。哎呦。不返回的异步网络调用也不是免费的。当然,您没有占用线程,但是您正在泄漏套接字。任何名副其实的HTTP客户端库都使用套接字池来避免重新创建连接。而这些池子的容量是有限的。与任何其他资源泄漏一样,没有套接字也只是时间问题。当这种情况发生时,您的应用程序将在等待连接释放时停滞不前。

如果网络不可靠,为什么我们要一直创建默认超时为无穷大的API?有些API甚至一开始就没有设置超时的方法!一个好的API应该容易使用正确的方式,很难使用错误的方式。当默认超时为无穷大时,客户端很容易搬起石头砸自己的脚。

如果你记得这篇文章中的一件事,那么就让它成为这样:永远不要使用“无限”作为默认超时。

JavaScript的XMLHttpRequest是从服务器异步检索数据的Web API。它的默认超时是零,这意味着没有超时!

Var xhr=new();xhr。Open(';GET';,';/api';,true);//默认情况下没有超时!xhr.timeout=10000;xhr。Onload=function(){//请求完成};xhr。Ontimeout=函数(E){//请求超时};xhr。发送(空);

客户端超时与服务器端超时一样重要。您的浏览器可以为特定主机打开的套接字数量是最大的。如果您发出的网络请求永远不会返回,您将耗尽套接字池。当池耗尽时,您将无法再连接到主机。

Fetch web API是XMLHttpRequest API的现代替代品,XMLHttpRequest API使用Promises。最初引入API时,根本没有办法设置超时!不过,浏览器最近添加了对中止API的试验性支持,以支持超时。

Const Controller=new();const Signal=Controller.ignal;const fetchPromise=FETCH(url,{ignal});//默认无超时!SetTimeout(()=>;控制器。Abort(),10000);FetchPromise。则(响应=>;{//请求完成})。

巨蟒世界的情况也好不到哪里去。请求库使用无限大的默认超时。

去吧?Go的HTTP包在默认情况下也不使用超时。

Var client=&;http.Client{//默认情况下没有超时!超时:时间.秒*10,}响应,_:=客户端。Get(Url)。

用于Java和.NET的现代HTTP客户端可以做得更好,并且通常带有默认超时。例如,.Net Core的HttpClient的默认超时为100秒。虽然很松散,但总比完全没有暂停要好得多。这并不令人惊讶,因为这些语言被用来构建大规模分布式系统,这些系统需要对网络故障具有健壮性。没有超时的网络请求是分布式系统的头号静默杀手。

经验法则是,在进行网络调用时始终设置超时。如果您构建库,请始终设置合理的默认超时,并使其可为您的客户端进行配置。

您想了解更多关于分布式系统的稳定性模式和反模式的知识吗?看看我即将出版的书。