jettyå¨6.0以åå¼å
¥äºcontinuationsï¼ é£ä¹ä»ä¹æ¯continuationsï¼ä»æä»ä¹ä¼ç¹ï¼
åå§çservletæ¯ä¸ä¸ªè¿æ¥å¯¹åºä¸ä¸ªçº¿ç¨ï¼å¨çè¿æ¥æ
åµä¸é½æ²¡ä»ä¹é®é¢ï¼ä½æ¯ç°å¨æè¶æ¥è¶å¤çè¿ç¨æ¯åºäºé¿è¿æ¥çï¼è¿æ ·ç¨æ·å¹¶åéä¸å»çè¯ï¼åå°ç线 ç¨æ°å°ä¼ä»¥æ£æ¯æ°ä¸åãä¸ä¸ªjava线ç¨ä¸è¬å ç¨64Kå
åï¼å
æ¬å
¶ä»çï¼èµæºä¼å ç¨å¾å¤ï¼åµä¸çº¿ç¨è°åº¦ï¼çº¿ç¨éæºå¶çé½å¾èCPUã
åæ¥åºç°ä¸ä¸ªè¯·æ±å¯¹åºä¸ä¸ªçº¿ç¨ãå¾çäºNIOï¼è¿æ¥è½å¤å¨è¯·æ±è¢«å¤çæ¶åé
ä¸ä¸ªçº¿ç¨ãå½è¿æ¥ç©ºé²æ¶ï¼é£ä¸ªçº¿ç¨å°ä¼è¢«æ¾å°çº¿ç¨æ± ä¸ï¼èè¿æ¥å次添å å°NIO Select Setä¸å»æ£æµæ°ç请æ±ãè¿ç§ä¸ä¸ªè¯·æ±å¯¹åºä¸ä¸ªçº¿ç¨ç模å¼è½åºå¯¹æ´å¤çç¨æ·è¿æ¥ã对äºajaxè¿ç¨æ¥è¯´ï¼è½®å¾ªè¯·æ±å»åæ°æ®ä¸å¤ªå¥½ï¼å 为è¦ä¸æ建ç«è¿æ¥ï¼è ä¸ä¸è¬è¿æ¥é½æ²¡åå°æ°æ®ï¼æµªè´¹å¾å¤è¿æ¥ï¼æ以æ¯è¾å¥½çåæ³æ¯æå¡å¨ä¿æä½é£ä¸ªè¯·æ±ï¼ç´å°æå¡å¨ææ°æ®å°±å¾å®¢æ·ç«¯è½¬éæè¶
æ¶ä¸ºæ¢ãè¿æ¯ä¸ä¸ªå¥½ææ¯ï¼ä½æ¯å®å æ¶ä¹è离äºä¸ä¸ªè¯·æ±ä¸ä¸ªçº¿ç¨çåè¡·ï¼å 为æ¯ä¸ªå®¢æ·ç«¯å¨æå¡ç«¯é½æä¸ä¸ªè¯·æ±çº¿ç¨ä¿æçï¼å æ¤æå¡ç«¯éè¦ä¸ºæ¯ä¸ªå®¢æ·ç«¯çæä¸ä¸ªæå¤ä¸ªçº¿ç¨ãå¨å¤§é并åç¨æ·ä¸ä» ç¶æé®é¢ã
jettyçcontinuationsæ£æ¯è§£å³ä¸é¢çé®é¢è产ççãå®çåçæ¯ï¼ä½¿ç¨SelectChannelConnectoræ¥å¤ç请æ±ï¼è¿ä¸ªç±» æ¯åºäºNIO APIä¸çãå æ¤ä½¿å®è½å¤ä¸ç¨æ¶èæ¯ä¸ªè¿æ¥ç线ç¨å°±å¯ä»¥ææå¼æ¾çè¿æ¥ã使ç¨continuations suspendæ¶ï¼è°ç¨çå®é
æ¯SelectChannelConnector.RetryContinuation.suspendï¼æ¤æ¶ä¼æåºä¸ä¸ªå¼ 常RetryRequest,该å¼å¸¸å°ä¼ æå° servlet 以å¤å¹¶éè¿è¿æ»¤å¨é¾ä¼ åï¼å¹¶ç± SelectChannelConnector æè·ã ä½æ¯åç该å¼å¸¸ä¹å并没æå°ååºåéç»å®¢æ·æºï¼è¯·æ±è¢«æ¾å°å¤äºçå¾
ç¶æç Continuation éåä¸ï¼è HTTP è¿æ¥ä»ç¶ä¿ææå¼ç¶æãæ¤æ¶ï¼ä¸ºè¯¥è¯·æ±æä¾æå¡ç线ç¨å°è¿å ThreadPoolï¼ç¨äºä¸ºå
¶ä»è¯·æ±æä¾æå¡ã æåç请æ±å°ä¸ç´ä¿æå¨çå¾
ç¶æç Continuation éåï¼ç´å°è¶
åºæå®çæ¶éï¼æè
å½å¯¹ resume() æ¹æ³ç Continuation è°ç¨ resume() æ¶,åºç°ä¸è¿°ä»»æä¸ç§æ¡ä»¶æ¶ï¼è¯·æ±å°è¢«éæ°æäº¤å° servletï¼éè¿è¿æ»¤å¨é¾ï¼ãäºå®ä¸ï¼æ´ä¸ªè¯·æ±è¢«éæ°è¿è¡å¤çï¼ç´å°é¦æ¬¡è°ç¨ suspend()ãå½æ§è¡ç¬¬äºæ¬¡åç suspend() è°ç¨æ¶ï¼RetryRequest å¼å¸¸ä¸ä¼è¢«æåºï¼æ§è¡ç
§å¸¸è¿è¡.å¤æçä¾æ®æ¯ï¼if (!_pending && !resumed && timeout >= 0) ..throw _retry;å
¶ä¸_pendingæ¯ææ¯ä¸æ¯ç¬¬äºæ¬¡è°ç¨äºsuspend....è¿æ ·åï¼jettyä¸çthread poolå°±ä¼æ空é²çº¿ç¨æ¥å¤çå
¶ä»ç请æ±ã
continuationsçå¼å
¥è½ç¨å¾å°ç线ç¨å¤ç大éç请æ±ããå®éªè§ä¸ï¼
public class App {
public static void main(String[] args) throws Exception {
Server server = new Server();
Connector conn = new SelectChannelConnector();
conn.setPort(8080);
server.setConnectors(new Connector[]{conn});
WebAppContext ctx = new WebAppContext();
ctx.setContextPath("/");
ctx.setWar("./webapp");
server.setHandler(ctx);
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(100);#设置jettyçthread poolæ大为100个线ç¨ã
server.setThreadPool(threadPool);
DaemonService.bind(server);
server.start();
}
}
DaemonServiceæ¯ä¸ä¸ªServletContextListenerï¼ä»£ç 为ï¼
public void contextInitialized(ServletContextEvent sce) {
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
#æ¯æ¬¡æå°åºå½å线ç¨æ± ç线ç¨å¤§å°å空é²çº¿ç¨
System.out.println("thread:" + server.getThreadPool().getThreads() + "#idle:" + server.getThreadPool().getIdleThreads());
}
}
}).start();
}
åä¸ä¸ªTestServletï¼å¯¹åºçmappingæ¯/test
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
resp.getWriter().write("Test");
resp.getWriter().flush();
}
}
使ç¨ab -c 200 -n 1000
http://localhost:8080/test æµè¯åç»æå¦ä¸ï¼
thread:2#idle:1
thread:2#idle:1
thread:89#idle:0
thread:100#idle:0
大æ¦è¿æ10å¤ä¸ªçthread:100#idle:0
thread:100#idle:0
thread:100#idle:0
thread:99#idle:19
thread:99#idle:88
thread:99#idle:98
thread:99#idle:98
thread:99#idle:98
说æäºå¨å¹¶å200个æ¶ï¼jetty线ç¨æ± éå ä¹æ²¡æ空é²çº¿ç¨æ¥å¤çå
¶ä»ç请æ±ã
abæµè¯ç»æ为ï¼
Requests per second: 44.54 [#/sec] (mean)
Time per request: 4490.625 [ms] (mean)
å½æTestServlet代ç æ¹ä¸ºContinuationæ¶ï¼åæ ·æ¯åé¡¿2ç§
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Continuation continuation = ContinuationSupport.getContinuation(req, null);
continuation.suspend(2000);
resp.getWriter().write("Test");
resp.getWriter().flush();
}
}
使ç¨ab -c 200 -n 1000
http://localhost:8080/test æµè¯åç»æå¦ä¸ï¼
thread:2#idle:1
thread:7#idle:6
thread:7#idle:6
thread:39#idle:26
thread:42#idle:41
thread:42#idle:36
thread:65#idle:64
thread:65#idle:46
thread:91#idle:90
thread:91#idle:90
thread:91#idle:89
thread:91#idle:90
thread:91#idle:83
说æå¨å¹¶å200个æ¶ï¼jetty线ç¨æ± ä¸ä¸ç´é½æå¾å¤ç©ºé²çº¿ç¨
abæµè¯ç»æ为ï¼
Requests per second: 79.21 [#/sec] (mean)
Time per request: 2525.000 [ms] (mean)
ç»è®ºï¼jettyçcontinuationså¨çè¿æ¥ä¸ä¸è§å¾æå¾å¤§çä¼å¿ï¼ä½æ¯å¨é¿è¿æ¥æè
å¨åå°è®¿é®IOèµæº(æ°æ®åºï¼ç½ç»çï¼é æç servletååºæ
¢é®é¢ä¸ï¼ä¼æå¾å¤§çä¼å¿ï¼ä»ä¸ä¼è®©ä¸ä¸ªçº¿ç¨å»å»å°å¨çå¾
æ°æ®åºè®¿é®å®æï¼èæ¯ä¼æ¾å
¥çº¿ç¨æ± å»å¤çå
¶ä»è¯·æ±ãçæ°æ®åºè®¿é®å®åï¼åè¿æ¥ å¤çã
servlet 3.0è§èå·²ç»å¼å
¥äºå¼æ¥servletåè½ï¼åæ³ä¸ºï¼
请æ±/url/A
AsyncContext ac = request.startAsync();
//...è¿è¾¹å¤çå
·ä½çèµæºæä½ï¼å¦db.getConnection()æå
¶ä»çæä½
ac.dispatch();