ใน Web container ปัจจุบัน
model ของ thread จะเป็นแบบ Thread per Connection
นั่นก็คือ 1 connection ที่วิ่งเข้ามา จะมี 1 thread ที่ถูก assign ให้รับผิดชอบ
(ผลพวงมาจาก socket api, ที่มีการ assign connection ให้กับ thread)
แนวคิดใหม่ๆ ก็คือการใช้ NIO เข้ามาช่วย 
อย่างใน Jetty6  จะมี model ที่เรียกว่า Thread per Request 
ความหมายก็คือ connection ที่เปิดทิ้งไว้, แต่ไม่มี request วิ่งเข้ามา
จะไม่มี thread รองรับมัน  (thread จะถูกส่งกลับเข้า pool)
เมื่อไรก็ตามที่มี request เข้ามา จึงจะมีการ assign thread ให้
บางคนอาจจะสงสัยว่า 1 connection มีได้หลาย request ด้วยหรือ
Connection ใน HTTP1.1 จะมี default เป็น keep alive
และเมื่อบวกกับ App สมัยใหม่ที่เป็น ajax style 
มีข้อมูลวิ่งไปมาถี่ๆ, connection ที่ browser เปิดไว้ก็แทบจะไม่ disconnect เลย
บางคนถึงกับล้อว่า นี่เราจะเปลี่ยน browser ให้กลายเป็น client-server แบบเดิมๆหรืออย่างไร
(client-server แบบที่เปิด connection ค้างไว้)
แล้ว 
Jetty Continuations คืออะไร
Continuations ใน Jetty ไม่ใช่ 
continuation แบบใน scheme, ruby (พวก callcc)
ความหมายจริงๆของมันก็คือ ในระหว่างการทำงานของ Servlet,
servlet สามารถที่จะสั่ง suspend thread ได้
โดยถ้ามีการสั่ง suspend เมื่อไร, jetty จะทำการ detach thread ออกจาก request,
และคืน thread กลับเข้าสู่ thread pool
แล้ว App ประเภทไหนที่เหมาะกับ Continations?
ที่ชัดเจนที่สุด ก็น่าจะเป็นพวกที่ต้องมีการ polling เป็นระยะๆ เช่น พวก chat
หรือพวกที่มี nature การทำงานเป็น asynchronous
เช่น app ที่มีการเรียกใช้ service ผ่านทาง JMS แล้วต้องรอ reply message
ลองมาทดสอบ NIO กับ continuation ดู
เริ่มด้วย servlet แบบง่ายๆ
protected void processRequest(HttpServletRequest request, 
                              HttpServletResponse response)
throws ServletException, IOException {
    try {
        Thread.sleep(100);
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }
    response.setContentType("text/html;charset=UTF-8");
    PrintWriter out = response.getWriter();
    
    out.println("<html>");
    out.println("<head>");
    out.println("<title>Servlet HelloServlet</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>Servlet HelloServlet at " + request.getContextPath () + "</h1>");
    out.println("</body>");
    out.println("</html>");
    out.close();
}
ใน servlet ให้มี sleep 100 ms,
ส่วน version  ที่เป็น continuation ก็แค่เปลี่ยนจาก sleep เป็น
    Continuation ctn = ContinuationSupport.getContinuation(request,this);
    ctn.suspend(100); 
ผมใช้ jmeter ทดสอบ โดยเรียก 120 request ใน 1 วินาที
เป็นเวลา 20 วินาที (รวมทั้งหมด 2400 request)
ตั้ง duration assert ไว้ที่ 200 ms
Jetty 6 NIO
50 %         109  105  106
90 %         147  125  125
> 200 ms      69   91   82
Jetty 6 BIO
50 %         103  103  104
90 %         111  111  114
> 200 ms       0    2   83
Jetty 6 NIO + continuations
50 %         108  106  106
90 %         120  125  122
> 200 ms       0   78   89
Tomcat 5.0.30
50 %         104  103  103
90 %         111  114  113
> 200 ms       0    0    0
Note: 50, 90 % คือ distribution ของ response time
เช่น 50% ใช้เวลาน้อยกว่าหรือเท่ากับค่าที่ระบุดูแล้ว NIO จะช้ากว่า BIO (block IO) อยู่นะ
ส่วน continuation ก็ไม่ต่างกับ NIO 
และ jetty ใน version นี้เริ่มสู้กับ tomcat 5.0.x ได้แล้ว
ที่นี้ลองเปลี่ยนช่วงเวลาที่ sleep กับ suspend เป็น 1000 ms บ้าง
Thread.sleep(100);
==========================
ctn.suspend(1000); 
ใช้ JMeter เรียกที่ 120 request/ sec, 20 วินาที เหมือนเดิม
แต่เปลี่ยน assert เป็น 1100 ms 
ผลที่ได้
Jetty 6 NIO
50 %        1021 1008 1009
90 %        1397 1438 1419
> 1100 ms    956  919  883
Jetty 6 BIO
50 %        1002 1003 1002
90 %        1439 1549 1487
> 1100 ms    788  786  707
Jetty 6 NIO + Continuation
50 %        1002 1002 1002
90 %        1015 1011 1013
> 1100 ms    126   93   93
Tomcat 5.0.30
50 %        1005 1002 1002
90 %        1349 1035 1257
> 1100 ms    562  398  400
จะเห็นว่ากรณีที่ thread เริ่มสะสมกันมากๆ 
(เนื่องจากเราตั้งค่า sleep ไว้ที่ 1 sec. ทำให้ request ชุดที่ 2 เริ่มเข้ามากวน request ชุดที่ 1)
jetty continuations ให้ผลลัพท์ที่ดีขึ้นอย่างเห็นได้ชัด
ข้อที่ต้องระวังในการใช้ jetty continuation ก็คือ
หลังจากที่เราสั่ง suspend ไปแล้ว, เมื่อ thread resume กลับมาอีกครั้ง 
HttpServletRequest ที่ได้ในคราวนี้ จะไม่ใช่ตัวเดิมแล้ว
ค่า parameter ต่างๆ จะหายหมด
ดังนั้นเราต้อง save ค่านี้เก็บไว้ใน session หรือใน database ก่อน
นอกจากนี้ ยัง suspend ยังห้ามใช้หลังจากมีการเขียน response ไปแล้ว
ประเด็นที่ผมยังไม่รู้คำตอบ ก็คือ
ในการใช้งานจริง เรามักจะวาง web container ไว้หลัง web server
คำถาม ก็คือพวก persistent connection ที่เกิดขึ้น มันจะเกิดกับ web server 
แล้ว jetty continuation ยังมีประโยชน์อยู่อีกหรือเปล่า
case หนึ่งที่เห็นว่า น่าจะมีประโยชน์อยู่บ้าง ก็คือพวก asynchronouse nature
(พวกที่ใช้ jms ต่อไปยัง service) 
เพราะถ้าใช้ jetty contination เข้ามาช่วย ก็น่าจะทำให้เรา
เพิ่มจำนวน connection ระหว่าง web server กับ web container ได้
ซึ่งมีผล ทำให้ through put เพิ่มขึ้น