技术开发 频道

ASP.NET AJAX之内部揭秘(1)

只有第一个调用成功了。所以,任何时候如果浏览器的两个连接都处在拥堵状态的话,那么你期待的其他调用也都将会超时。

Pageflakes的运营中,我们曾经几乎每天都从客户端得到400个到600个超时错误报告,却从未能发现这是怎么发生的。起初怀疑是互联网连接过慢造成的,但是不可能如此多的用户都发生这种情况。后来,我们猜测是主机提供商的网络出现了问题。经过了大量的网络析去寻找问题是否是出现在网络上,但是依旧没有没有发现任何异常。接着使用SQL Profiler去查找是否是长时间运行的查询导致了ASP.NET请求执行时的超时。但是不幸,我们最终发现的是,大部分超时错误出现的情况都是先有一些坏的调用,然后好的调用也超时了。所以我们修改了Atlas运行时,引进了自动重试的功能,问题终于完全消失了。然而,自动重试需要对ASP.NET AJAX框架的Javascript做一次“心脏外科手术”,这个方法会要求每个调用在超时后都重试一次。为了实现它,我们需要截获所有web method调用并且在onFailure回调函数中作个钩子,如果失败的原因是超时,onFailure将再次调用相同的web method

另一个需要关注的发现是当我们外出旅行感到疲惫时,想通过酒店或机场的无线网络连接到互联网访问Pageflakes的时候,首次访问总是不成功,并且所有的web service调用在第一次尝试中总是失败。直到我们刷新之前都不会工作。这也是我们要实现web service调用立即自动重试的另一个主要原因,它正好可以解决这个问题。

这里我会告诉你怎么做。Sys$Net$WebServiceProxy$invoke函数是负责处理所有web service调用的。所以需要通过一个自定义onFailure回调函数来替换这个函数。只要有错误或者超时就会激发这个自定义回调函数。当有超时发生的时候,就会再次调用这个函数,重试就会发生。

Collapse Sys.Net.WebServiceProxy.retryOnFailure = function(result, userContext, methodName, retryParams, onFailure) { if( result.get_timedOut() ) { if( typeof retryParams != "undefined" ) { debug.trace("Retry: " + methodName); Sys.Net.WebServiceProxy.original_invoke.apply(this, retryParams ); } else { if( onFailure ) onFailure(result, userContext, methodName); } } else { if( onFailure ) onFailure(result, userContext, methodName); } } Sys.Net.WebServiceProxy.original_invoke = Sys.Net.WebServiceProxy.invoke; Sys.Net.WebServiceProxy.invoke = function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, timeout) { var retryParams = [ servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, timeout ]; // 初始调用失败 // 处理自动重试 var newOnFailure = Function.createDelegate( this, function(result, userContext, methodName) { Sys.Net.WebServiceProxy.retryOnFailure(result, userContext, methodName, retryParams, onFailure); } ); Sys.Net.WebServiceProxy.original_invoke(servicePath, methodName, useGet, params, onSuccess, newOnFailure, userContext, timeout); }

运行的时候,它将把每个超时调用都重试一次

这里可以看到第一个方法成功了,所有其他超时的调用都会被重试。而且重试一次后的调用都成功了。发生这种情况是因为在重试中服务端的方法不会做超时处理。这证明了我们的实现方法是正确的。

0
相关文章