JavaScript 中的 Web 服务调用导致浏览器白屏死机 (WSOD)
规格如下:
- 的 ASP.NET 3.5
- 使用 ASP.NET AJAX AJAX Control Toolkit
- jQuery 1.3.2
- Web 服务
- Windows Server 2003 SP1 SP1 上的
- IIS6 SQLServer 2005 SP3 站点是 SSL
- Infragistics Web Components 2009 第 1 卷。 2(使用非合气道控件),主要使用UltraWebGrid和Tree控件。
问题是这样的: 我在 IE 7/8 中遇到白屏死机 (WSOD)。基本上,我有一个页面,其左窗格具有 AJAXControl Toolkit Accordion 控件,其中每个手风琴窗格内容都是 Infragistics 树控件。右侧窗格是一个
,其中有一个
,其内容根据左侧菜单窗格中的单击内容重新加载。在 中,当您单击左侧窗格中的菜单项时,会加载一个包含一个或多个 UltraWebGrid 控件的页面。网格都有一个模板化按钮列。当您单击网格行的编辑按钮时,将打开一个用于编辑记录的弹出窗口。这种方法大约可以正常工作十次,然后在第十次(有时更早)时,弹出窗口将打开,地址栏中显示正确的 URL,但页面从未加载。
我们有一个应用程序,它使用一个弹出窗口来更新记录。大多数情况下,当您单击[编辑]按钮编辑记录时,会打开弹出窗口并加载更新页面。然而,编辑记录一段时间后,突然会打开弹出窗口,但它保持空白并挂起。 URL 在地址栏中。
加载 Fiddler 时,我注意到更新页面的请求从未发送,这让我相信这是客户端的某种锁定。如果我将弹出窗口中的相同 URL 复制到新的浏览器窗口中,页面通常会正常加载。
观察结果: - 由于请求永远不会发送到服务器,因此它肯定与客户端或浏览器相关。 - 仅当网站上有一些看似奇怪的流量时才会发生,因为这似乎包含在客户端代码中 - 每隔几秒就会在后台调用一个 Web 服务来检查用户是否登录,但这不会导致冻结。
我真的很不知所措。我用 google 搜索过 WSOD,但似乎与我的特定 WSOD 相关的不多。有什么想法吗?
问题到底是什么
所以事实证明内存泄漏(尽管我已经在客户端密封了一些)不是问题。问题是在客户端进行 Web 服务调用。其中每 4 秒检查一次用户是否登录(以与另一个窗口同步),然后调用 Web 服务来获取用户对弹出窗口和网格状态的首选项。据我所知,Web 服务必须是异步的。我通过使用成功/失败回调从 JavaScript 调用它们来假设它们是异步的,但实际上不是。从客户端/浏览器的角度来看,它们是异步的,但从服务器端来看,会对 Web 服务进行调用,并在完成后返回,因为连接数量有限,因此会阻止任何其他操作。
那么使 Web 服务方法异步的最简单方法是什么? Web 服务是否需要转换为 WCF Web 服务,或者我可以使用现有的 ASP.NET Web 服务调用吗?
出于历史目的,我认为问题最初是这样的:
我无法在本地或我们的测试服务器上重现此问题。然而,我让 Fiddler 来模拟调制解调器速度,突然间我可以在本地 PC 上复制 WSOD。因此,在打开弹出窗口时,连接似乎很慢或暂时很慢,导致其阻塞,至少在我的测试环境中是这样。
我在没有附加组件的情况下运行 IE 进行了另一项测试,iexplore.exe -extoff
,但最终得到了相同的结果。我还修复了每次 iframe 的 URL 更改时都会重新创建页面上的 iframe 的问题。我的部分逻辑被省略了。现在 iframe 只创建一次。之后,当我想加载新内容时,只有 src 属性会更新......我的傻瓜。我注意到 JavaScript 闭包中存在一些挥之不去的窗口引用,因此现在当我完成它们时,它们在闭包中显式设置为 null。
我还做了一些内存泄漏调查: - 据我所知,我在 DOM 和 JavaScript 中没有任何循环引用或这里提到的其他泄漏模式, http://www.ibm.com/developerworks/web/library/wa-memleak/?S_TACT=105AGX52&S_CMP=cn -a-wa
我添加了 Crockenator 的 IE 内存泄漏清除代码(请参阅 http://www.crockford.com/javascript/memory/leak.html):
$(文档).ready(函数() { 函数清除(d) { var a = d.attributes, i, l, n;
<前><代码> if (a) { l = a.长度; for (i = 0; i < l; i += 1) { 如果(a[i]){ n = a[i].名称; if (typeof d[n] === '函数') { d[n] = 空; 清除计数++; } } } } a = d.childNodes; 如果(一){ l = a.长度; for (i = 0; i < l; i += 1) { 清除(d.childNodes[i]); } } } $(窗口).unload(函数() { 清除(文档.body); //alert("清除次数:" + purgeCount); });});
我的所有改进都没有解决问题。在我本地的测试场景中。有什么想法吗?有人吗?有人吗?布勒?
最后更新
感谢 David 指出是会话状态导致了 Web 服务中的问题。 “ASP.NET 将所有请求排队到同一个“会话”。因此,如果第一个请求阻塞时间过长,它将阻止任何其他排队的请求。”
因此,我们最终所做的是尝试使用会话状态最小化 Web 服务,但我们还添加了 Microsoft 建议的连接数设置,请参阅 http://msdn.microsoft.com/en-us/library/ff647786.aspx#scalenetchapt10_topic9
Here's the specs:
- ASP.NET 3.5 using ASP.NET AJAX
- AJAX Control Toolkit
- jQuery 1.3.2
- web services
- IIS6 on Windows Server 2003 SP1
- SP1 SQLServer 2005 SP3 Site is SSL
- Infragistics Web Components 2009 Vol. 2 (using non-Aikido controls), UltraWebGrid and Tree control are main ones used.
Here's the problem:
I'm getting the White Screen of Death (WSOD) in IE 7/8. Basically, I have a page that has a left pane that has an AJAXControl Toolkit Accordion control where each accordion panes content is an Infragistics Tree Control. The right pane is a <div>
that has an <iframe>
whose content is reloaded based on what's clicked in the left menu pane.
In the <iframe>
, a page with one or more UltraWebGrid controls loads up when you click on a menu item in the left pane. The grids all havea templated button column. When you click on the edit button of a grid row a popup window to edit the record is opened. This works fine for about ten times and then on the tenth time (sometimes earlier), the popup window opens with the correct URL in the address bar, but the page never loads.
We have an application that uses one popup window for updating records. Most of the time when you click on the [Edit] button to edit a record, the popup window opens and loads the update page. However, after editing records for a while, all of a sudden the popup window will open, but it stays blank and just hangs. The URL is in the address bar.
Loading up Fiddler I noticed that the request for the update page is never sent which leads me to believe it's some kind of lockup on the client-side. If I copy the same URL that's in the popup window into a new browser window, the page generally loads fine.
Observations:
- Since the request is never sent to the server, it's definitely something client-side or browser related.
- Only appears to happen when there is some semblance of traffic on the site which is weird because this appears to be contained within client-side code
- There is a web service being called in the background every few seconds checking if the user is logged on, but this doesn't cause the freeze.
I'm really at a loss here. I've googled WSOD but not much seems to appear related to my specific WSOD. Any ideas?
What the problem really is
So turns out the memory leaks (although I've sealed up some on the client-side) are not the issue. The issue is web service calls being made on the client-side. There is one that checks if a user is logged on every 4 seconds (to synchronize with another window) and then there are web service calls to get user preferences for a popup window and grid state. From what I've read, the web services have to be asynchronous. I assumed by calling them from JavaScript with success/fail callbacks that they were asynchronous but they really aren't. They're asynchronous from the client-side/browser point of view, but from the server-side, the call to the web service is made and returns when it is completed holding up any other operations since there is a limited number of connections.
So what is the easiest way to just make the web service methods asynchronous? Does the web service need to be converted to a WCF web service or can I use my existing ASP.NET web service call?
And for historical purposes, here's what I thought the problem was originally:
I wasn't able to reproduce this locally or on our testing servers. However, I got Fiddler to simulate modem speeds and all of sudden I can replicate the WSOD on my local PC. So it appears to be a slow or temporarily slow connection when opening a popup window that causes it to choke, at least in my test environment.
I did another test running IE without add-ons, iexplore.exe -extoff
, but end up with the same result. I also fixed an issue where the iframe on the page was being recreated everytime the URL for the iframe changed. Part of my logic was omitted. Now the iframe is only created once. After that only the src
attribute is updated when I want to load new content... my goof. I noticed some lingering window references in JavaScript closures, so now those are explicitly set to null in the closures when I'm done with them.
I've also done some memory leak investigation:
- As far as I can tell I do not have any circular references in the DOM and JavaScript or the other leak patterns mentioned here, http://www.ibm.com/developerworks/web/library/wa-memleak/?S_TACT=105AGX52&S_CMP=cn-a-wa
I've added the Crockenator's purge code for IE memory leaks (see http://www.crockford.com/javascript/memory/leak.html):
$(document).ready(function() {
function purge(d) {
var a = d.attributes, i, l, n;if (a) { l = a.length; for (i = 0; i < l; i += 1) { if (a[i]) { n = a[i].name; if (typeof d[n] === 'function') { d[n] = null; purgeCount++; } } } } a = d.childNodes; if (a) { l = a.length; for (i = 0; i < l; i += 1) { purge(d.childNodes[i]); } } } $(window).unload(function() { purge(document.body); //alert("purge count: " + purgeCount); });
});
None of my improvements have fixed the problem. in my local test scenario. Any ideas? Anyone? Anyone? Bueller?
Last Update
Thanks David for pointing out that it was session state causing the problems in the web services. "ASP.NET queues all requests to the same 'session'. So if the first request blocks for too long, it will hold up any other queued requests."
So what we ended up doing was try to minimize web services using session state but we also added the recommended settings by Microsoft for the number of connections, see http://msdn.microsoft.com/en-us/library/ff647786.aspx#scalenetchapt10_topic9
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您可能遇到会话请求同步问题。您是否已将 Web 服务处理程序标记为需要会话状态?
ASP.NET 将所有请求排队到同一个“会话”。因此,如果第一个请求阻塞时间过长,它将阻止任何其他排队的请求。您可以关闭页面的会话状态以避免这种情况并实现真正的异步,但是您将无法访问服务器上的会话等。
如果您使用 .ashx,则必须使用接口来访问会话状态,默认是关闭的,因此请检查您是否添加了这些接口之一,并在可能的情况下删除:
如果您使用的是 aspx 页面,则默认情况下它是打开的,您必须使用 Page 指令属性将其关闭:
I think you may be having an issue with Session request synchronization. Have you marked your web service handlers as requiring session state?
ASP.NET queues all requests to the same "session". So if the first request blocks for too long, it will hold up any other queued requests. You can turn off session state for the page to avoid this and be truly asynchronous, however you will be unable to access session on the server, etc.
If you are using .ashx, you have to use an interface to get access to session state,the default is off, so check if you added one of these interfaces and remove if possible:
If you are using an aspx page, it is on by default and you have to turn it off with a Page directive attribute: