2011-12-08 34 views
5

Tôi đã cố gắng thực hiện trò chuyện COMET bằng cách sử dụng Async Processing được định nghĩa trong Servlet API 3. Nó không hoạt động - trò chuyện đã bị chặn, vì vậy tôi đã tạo ra servlet debug để kiểm tra phần async .Tomcat 7 Xử lý không đồng bộ không thành công - chỉ một yêu cầu được xử lý đồng thời

Đây là phương pháp doGet tôi:

@Override 
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    log.debug("doGet called"); 
    int timeout = 30 + RandomUtils.nextInt(60); 
    String message = RandomStringUtils.randomAlphanumeric(50 + RandomUtils.nextInt(250)); 
    response.setHeader("Access-Control-Allow-Origin", "*"); 
    final AsyncContext context = request.startAsync(); 

    synchronized(items) { 
     items.add(new RequestItem(context, message, timeout)); 
    } 
    log.debug("doGet created request and finished"); 
} 

Tôi đang đặt mục yêu cầu trong hàng đợi, và có một sợi chạy, sẽ đưa các mặt hàng thời gian chờ sau khi quy định và gửi thư trả lời để AsyncContext, thông điệp in ấn về nó . Vấn đề là, thread bị chặn cho đến khi AsyncContext được trả lời. Đây là những gì có thể nhìn thấy trong nhật ký của tôi sau khi yêu cầu 4 tải trang trong trình duyệt:

2011-12-08 13:56:36,923 DEBUG [my.servlet.TestAsyncServlet] doGet called 
2011-12-08 13:56:36,952 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished 
2011-12-08 13:57:39,934 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [[email protected], message=zEQpATavzwFl6qIbBKve4OzIY9UUuZBwbqN1TC5KpU3i8LM9B6ChgUqaRmcT2yF, timeout=0] 
2011-12-08 13:57:39,962 DEBUG [my.servlet.TestAsyncServlet] doGet called 
2011-12-08 13:57:39,962 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished 
2011-12-08 13:58:53,949 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [[email protected], message=pKHKC632CPIk7hGLV0YqCbQl1qpWIoyNv5OWCp21bEqoni1gbY79HT61QEUS2eCjeTMoNEwdqKzCZNGgDngULysSzVdzFTnQQ5cQ8JvcYnp1pLVqGTueJPWnbRdUuO, timeout=0] 
2011-12-08 13:58:53,960 DEBUG [my.servlet.TestAsyncServlet] doGet called 
2011-12-08 13:58:53,960 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished 
2011-12-08 13:59:36,954 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [[email protected], message=43FPeEUZWBLqgkAqS3WOFMiHUMVvx6o4jNqWLx8kUvwxqJqpOZyGCtiIcr7yw, timeout=0] 
2011-12-08 13:59:36,999 DEBUG [my.servlet.TestAsyncServlet] doGet called 
2011-12-08 13:59:36,999 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished 
2011-12-08 14:00:34,957 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [[email protected], message=r69Y4NQsyR1vj0kzUlHssic2x1Yrr6T09IGKjWAH1E6Lz4VhFTy9dQHi5CPeTObyjLLBDlCLEDfiyMUnVkVIEgYG7r47Ak4w30RklhzdEi9nthqdfNkry6nyjircsFPX534NqWjI1LwsrGq5nOa3ZYtfjfPVpGlk4KDmWP11L53YntO3GmptZPKa50gcqj9i, timeout=0] 

Vì nó là để xem, phương pháp doGet tiếp theo được gọi là chỉ sau khi yêu cầu trước đó là (về mặt lý thuyết không đồng bộ) đã trả lời. Vì vậy, toàn bộ điều không đồng bộ là không làm việc ở tất cả! Và đây là khai báo web.xml:

<servlet> 
    <servlet-name>TestAsyncServlet</servlet-name> 
    <servlet-class>my.servlet.TestAsyncServlet</servlet-class> 
    <async-supported>true</async-supported> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>TestAsyncServlet</servlet-name> 
    <url-pattern>/test-async</url-pattern> 
    </servlet-mapping> 

Tôi đang làm tất cả những gì được tìm thấy trên Internet. Tôi không thấy nơi xảy ra sai lầm. Tôi đã tìm thấy không có gì đặc biệt để cấu hình trong servlet.xml. Vì vậy, câu hỏi là, tại sao nó không hoạt động như nó nên?

Trả lời

5

OK, như một phần của nghiên cứu tôi đã viết chương trình thử nghiệm đã mở các kết nối nhân với tomcat và đã GET/POST trên servlet async. Tôi đã sửa lỗi và kiểm tra lại cấu hình server.xml của mình, hồ sơ chuỗi giới hạn để hiển thị tốt hơn kết quả kiểm tra, v.v. Bây giờ cấu hình kết nối của tôi trông như sau:

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" 
       minProcessors="3" 
       maxProcessors="8" 
       maxThreads="20" 
       connectionTimeout="150000" 
       asyncTimeout="150000" /> 

Và điều này đang hoạt động! Tôi đã thực hiện thử nghiệm bằng cách sử dụng NIO và thực hiện 1000 kết nối cùng một lúc và tất cả chúng đã được xử lý trong một lần.

Tuy nhiên, hiệu ứng tôi đã mô tả, vẫn tồn tại trong trình duyệt. Khi tôi cố gắng tải servlet trên 10 tab, đầu tiên được tải, hơn thứ hai vv Nó có vẻ là hành vi của trình duyệt, không có gì bị chặn trên máy chủ. Khi tôi mở 3 trình duyệt (Firefox, Chrome, Opera), tôi có 3 kết nối được xử lý một lần.Vì vậy, việc xử lý không đồng bộ được xác định trong Servlet API 3.0 hoạt động trên Tomcat 7, tuy nhiên, nó phải được thử nghiệm với programm riêng không có nhiều tab trong trình duyệt ... thử nghiệm COMET chat trong nhiều tab cũng không hoạt động như mong đợi. Tuy nhiên, trong ví dụ thực tế, một máy tính sẽ chỉ mở một kết nối. Và, hành vi của trình duyệt không phải là lỗi của máy chủ.

chỉnh sửa Sau khi giải pháp Spring MVC được đưa vào ứng dụng web, chế độ xử lý không đồng bộ đã bị dừng (tham số từ web.xml bị bỏ qua). Tuy nhiên, hỗ trợ không đồng bộ có thể được thiết lập theo cách thủ công thông qua việc thêm dòng:

request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true); 
+0

Kỳ lạ Chrome và Firefox dường như tuần tự hóa nhiều yêu cầu GET nếu URL giống nhau. Safari không làm điều đó mặc dù. – Mark

1

Tôi nghĩ rằng bạn đã cấu hình đúng máy chủ của mình. Nếu bạn chỉ tải bằng trình duyệt thì vấn đề có thể là cách trình duyệt của bạn đang hoạt động. Nếu bạn chỉ cần truy cập trang web bằng trình duyệt thì trình duyệt sẽ thử tải toàn bộ trang và chặn cho đến khi hoàn tất. Trình duyệt của bạn sẽ không kết thúc tải cho đến khi yêu cầu async kết thúc.

Ví dụ, nếu bạn đã nhìn vào tin nhắn với một công cụ như Fiddler tôi mong đợi bạn sẽ thấy như sau (chậm trễ giả định là 4):

Browser -> Server [Time: 0] Request 
Server -> Browser [Time: 0.1] Async Response 
Server -> Browser [Timer: 4] Complete Response 
Browser shows page loaded. 

Nếu bạn lấy ra async chế độ bạn muốn xem:

Browser -> Server [Time: 0] Request 
Server -> Browser [Time: 4] Response 
Browser shows page loaded. 

Trong cả hai ví dụ, trang sẽ không được tải đầy đủ cho dù yêu cầu hoàn toàn không đồng bộ và một là đồng bộ. Để tận dụng đầy đủ các yêu cầu không đồng bộ, bạn sẽ cần một ứng dụng khách thông minh hơn, ví dụ: Javascript hoặc flex hoặc một cái gì đó.

Nói cách khác, tôi không nghĩ bạn có thể nói máy chủ chính xác hay không bằng cách chỉ tải bằng trình duyệt. Tôi sẽ lấy một công cụ như Fiddler và xem chính xác những gì các thông điệp HTTP đang đi qua.

+0

Đây là những gì trình duyệt đang làm, nhưng theo tôi đã hiểu từ tài liệu, máy chủ dự kiến ​​sẽ xử lý yêu cầu không đồng bộ theo cách đó chuỗi sẽ được giải phóng, trong khi kết nối sẽ vẫn hoạt động. Nói cách khác, sử dụng I/O không bị chặn. Nếu không nó sẽ không có nhiều ý nghĩa. Tôi đã sử dụng mã tương tự với dòng jquery, nhưng hiệu quả là chính xác như nhau, nó chỉ difficulter để gỡ lỗi. –

Các vấn đề liên quan