先描述一下问题: 有一个管理Job的UI,选中一些Job可以Run,每次只能启动一个。还有一个UI通过Timer定时发Ajax请求服务端,查询并显示Job的运行状况(进度)。 奇怪的问题出现了: 1)在FireFox和IE8运行正常(貌似正常,稍后再解释)。其他浏览器未测试。 2)IE6,7及更早版本,Timer无法检测到多于1个的Job运行。 先检查了一遍代码,Timer的控制没有问题。不行就使用Fiddler吧。刚好是IE的问题。 观察HTTP发现一个现象,运行Job的HTTP似乎没有成功,因为Body是-1,之后是每隔一秒的Timer发起的HTTP。如果再启动一个Job,发现Timer停止了!! 等待第一个Job运行成功之后,Timer又恢复了(重新发送Ajax请求)!! 似乎是运行Job的请求阻塞了(实际上该请求长时间没有返回,因为运行Job需要几分钟甚至更多时间)。 为啥不使用DWR3.0的Push技术?后来跟同事讨论明白,这不过是把Timer从客户端转移到了服务端。 记起来了,俺好像读DWR源代码的时候(当时对如何实现推非常感兴趣),见过一段代码分析Browser的类型和连接数,有的情况还抛出了异常。 明白了,肯定是IE6有连接数限制问题,后来得知,默认情况下,它不支持同时超过2个连接。哈哈。这就对了。 RunJob占用了一个(几分钟不等), Timer占用了一个(很短暂)。 刚好2个。 Java代码
- public class BrowserDetect
- {
- /**
- * How many connections can this browser open simultaneously?
- * @param request The request so we can get at the user-agent header
- * @return The number of connections that we think this browser can take
- */
- public static int getConnectionLimit(HttpServletRequest request)
- {
- if (atLeast(request, UserAgent.IE, 8))
- {
- return 6;
- }
- if (atLeast(request, UserAgent.Firefox, 3))
- {
- return 6;
- }
- else if (atLeast(request, UserAgent.AppleWebKit, 8))
- {
- return 4;
- }
- else if (atLeast(request, UserAgent.Opera, 9))
- {
- return 4;
- }
- else
- {
- return 2;
- }
- }
- //....
- }
接下来就是查资料做试验,验证该问题是否正确。通过在注册表设置Internet Settings参数,实现了更多连接。例如10个。 但是Job可能很多,不可能无限制增加连接数,所以RunJob不应长期占用连接,它应该把Job插入队列并立即返回。 至此问题的源头终于找到了,Fiddler又帮了大忙。 读源代码是了解技术运作细节的最好方法,此外还能学到好的编程习惯。-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;