jetty6.0引入continuations continuations优点
原始servlet连接应线程短连接情况都没问题现越越运用基于连接用户并发量台线 程数比数升java线程般占用64K内存包括其资源占用况且线程调度线程锁机制等都耗CPU
现请求应线程益于NIO连接能够请求处理配线程连接空闲线程放线程池连接再添加NIO Select Set检测新请求种请求应线程模式能应更用户连接于ajax运用说轮循请求取数据太要断建立连接 且般连接都没取数据浪费连接所比较办服务器保持住请求直服务器数据往客户端转送或超止技术同 背离请求线程初衷每客户端服务端都请求线程保持着服务端需要每客户端或线程量并发用户仍 问题
jettycontinuations解决面问题产原理:使用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....jettythread 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);#设置jettythread pool100线程
server.setThreadPool(threadPool);
DaemonService.bind(server);
server.start();
}
}
DaemonServiceServletContextListener代码:
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 测试结:
thread:2#idle:1
thread:2#idle:1
thread:89#idle:0
thread:100#idle:0
概10thread: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
说明并发200jetty线程池几乎没空闲线程处理其请求
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 测试结:
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
说明并发200jetty线程池直都空闲线程
ab测试结:
Requests per second: 79.21 [#/sec] (mean)
Time per request: 2525.000 [ms] (mean)
结论:jettycontinuations短连接见优势连接或者台访问IO资源(数据库网络等)造 servlet响应慢问题优势让线程傻傻等待数据库访问完放入线程池处理其请求等数据库访问完再 处理
servlet 3.0规范已经引入异步servlet功能写:
请求/url/A
AsyncContext ac = request.startAsync();
//...边处理具体资源操作db.getConnection()或其操作
ac.dispatch();
温馨提示:答案为网友推荐,仅供参考