最近用SpringMVC寫了一個很簡單的測試程序,代碼如下:
@Controller public class LongTimeTaskController { @RequestMapping(value = "/sleep", method = RequestMethod.GET) public ModelAndView sleepTest(){ System.out.println(" begin sleep. " + Thread.currentThread().getId()); try { Thread.sleep(15000); } catch (InterruptedException e) { } System.out.println(" end sleep and return. " + Thread.currentThread().getId()); return new ModelAndView("sleep"); } }
這個sleepTest()的Action意圖很明確,對它的調用將sleep 15秒鍾再返回。接下來我用Chrome打開多個tab,打入“http://localhost:8080/sleep”進行訪問,很快我發現了個奇怪的現象,那就是標題所描述的那樣,sleepTest()這個Action同一時間里只有一個線程在跑,也就是說,如果我幾乎同時讓A、B、C三個Tab打開這個地址(事實上,A略微先於B,B略微先於C),我就觀察到,A成功返回的時候(看到“ end sleep and return.”),B才開始進入(看到“ begin sleep.”),B成功返回的時候C才開始進入,等到C成功返回的時候一共花了不下45秒鍾,很奇怪!
難道不支持多線程嗎?我把執行它們的線程ID打印了出來,發現是不同的線程,接下來進一步研究發現了:
1,sleep阻塞的時候,對別的Action的訪問並不受影響
2,如果啟動別的瀏覽器,訪問sleep,也不會被阻塞
這看起來像是SpringMVC的限制,因為這跟是否訪問同一個Action有關,但實在搞不懂為什么要這樣,最好就是Google一下,這種問題如果存在,問的人應該很多,但很遺憾,Google不到任何相關內容。
后來想想,干嘛不用Postman試試看呢?一嘗試,驚奇地發現Postman沒有這個問題,我的天,這竟然是瀏覽器的限制?答案是肯定的,接下來我很快發現了IE並沒有這個限制,這個奇怪的限制只在Chrome上出現了,要證明很簡單,用Wireshark抓一下包即可。
Chrome的限制規則是:瀏覽器同時只能對同一個URL提出一個請求,如果有更多的請求的話,對不起,請排隊。這個所謂“限制”到底好不好?可能不錯,想想對同一URL的請求,如果前請求阻塞,那么后請求想必也會被阻塞,這無端增加了開銷,並沒多大意義,Chrome這么做應該有它的合理性。