`

tomcat7特性 serlvet async特性

 
阅读更多

 

每个请求来到Web容器,Web容器会为其分配一个线程来专门负责该请求,直到完成处理前,该执行线程都不会被释放回容器。 执行线程会耗用系统资源,若有些请求需要长时间处理(例如长时间运算、等待某个资源),就会长时间占用执行线程。 
若这类的请求很多,许多执行线程都被长时间占用,而在web容器内,可以使用的线程都是有限的,这对于系统就会是个负担,甚至造成应用程式的性能瓶颈。

基本上一些需长时间处理的请求,通常客户端也较不在乎请求后要有立即的回应。若可以,让这类请求先释放容器分配给该请求的执行线程,让容器可以有机会将执行线程资源分配给其它的请求,可以减轻系统负担。

很多项目在遇到需长时间处理的任务时,经常启一个新线程或者扔到线程池中,这样不耽误任务主线的流程,这个servlet的asynch特性其实发挥同样的作用

释放了容器所分配执行线程的请求,其回应将被延后,直到处理完成(例如长时间运算完成、所需资源已获得)再行对客户端的回应,如果超过浏览器的链接时长,会将servlet中的内容返回,而asyncContext中的内容则不能返回,服务器抛出java.lang.IllegalStateException错误

在Servlet 3.0中,提供了AsyncContext,对异步执行的上下文提供支持。在ServletRequest上提供了 startAsync( )方法,用于启动异步工作线程。而且AsynchContext还提供了Timeout等设置。

你可以透过AsyncContext的getRequest() 、 getResponse()方法取得Request、Response对象,此次对客户端的响应将暂缓至调用AsyncContext的complete()方法或dispatch()为止,前者表示回应完成,后者表示将响应调派给指定的URL 。

若要能调用ServletRequest的startAsync()使用AsyncContext,则此Servlet 必须能支援非同步处理,如果使用@WebServlet来标注,则可以设定其asyncSupported为true 。 例如:

@WebServlet(urlPatterns = "/some.do", asyncSupported = true )   
public class AsyncServlet extends HttpServlet 
...   
  • 1
  • 2
  • 3

如果使用web.xml设定Servlet,则可以设定标签为true :

...   
<servlet>   
<servlet-name>AsyncServlet</servlet-name>   
<servlet-class>com.pkgname.AsyncServlet</servlet-class>   
<async-supported>true</async-supported>   
</servlet>   
...   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如果Servlet将会异步处理,若其前端有过滤器,则过滤器亦需标示其支援异步处理,如果使用@WebFilter ,同样是可以设定其asyncSupported为true 。 例如:

@WebFilter(urlPatterns = "/some.do", asyncSupported = true )   
public class AsyncFilter implements Filter{   
...   
  • 1
  • 2
  • 3

如果使用web.xml设定过滤器,则可以设定标签为true :

...   
<filter>   
< filter -name>AsyncFilter</ filter -name>   
< filter -class>com.pkgname.AsyncFilter</ filter -class>   
<async-supported>true</async-supported>   
</ filter >   
...   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意: 
使用异步处理方式,web容器的请求处理线程释放了,可以服务其他的请求处理。但是该Request的处理并没有结束,在使用AsyncContext的complete或者dispatch完成后,这个request的处理才结束。

简单的示例:
  • 1
  • 2
package com.ss;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//  import com.cndatacom.thread.BusinessHandleThread;

/**
 * 异步处理Servlet
 * @author 
 */

/**
 * asyncSupported属性默认是false,如果需要开启支持异步处理功能,需要设置为true
 */
@WebServlet(name = "AsyncServlet", urlPatterns = "/AsyncServlet2", asyncSupported = true)
public class AsyncServlet2 extends HttpServlet {
    /**
     * 
     */
    private static final long serialVersionUID = -2749650094193187229L;

    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss Z");

        out.println("Servlet  begin --" + sdf.format(date) + "<br>");// 响应输出到客户端

        // 进入异步模式,调用业务处理线程进行业务处理
        // Servlet不会被阻塞,而是直接往下执行
        // 业务处理完成后的回应由AsyncContext管理
        AsyncContext asyncContext = request.startAsync();
        BusinessWorkerThread businessHandleThread = new BusinessWorkerThread(
                asyncContext);
        Thread thread = new Thread(businessHandleThread);
        thread.start();
        //asyncContext.start(businessHandleThread);//也可以用这种方法启动异步线程

        date = new Date(System.currentTimeMillis());
        out.println("Servlet end --" + sdf.format(date) + "<br>");
        out.flush();

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
------
  • 1
  • 2
package com.ss;

import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.AsyncContext;
import javax.servlet.ServletResponse;

/**
 * 业务处理线程
 * 
 * @author 
 */
public class BusinessWorkerThread implements Runnable {

    // 异步操作的上下文对象,通过构造方法传进来
    private AsyncContext asyncContext;

    public BusinessWorkerThread(AsyncContext asyncContext) {
        this.asyncContext = asyncContext;
    }

    @Override
    public void run() {
        try {
            // do some work...
            Thread.sleep(8000); // 和browser的timeout时间相关。如果browser上timeout是30s,则大于30时,网络已经断开。这是就会异常。

            ServletResponse response = asyncContext.getResponse();
            PrintWriter out = response.getWriter();
            Date date = new Date(System.currentTimeMillis());
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss Z");

            out.println("business worker finished --"+ sdf.format(date));// 响应输出到客户端

            // 告诉启动异步处理的Servlet异步处理已完成,Servlet就会提交请求响应
            asyncContext.complete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
输出: 在浏览器中,输出的内容按照后面的时间显示在页面上。
  • 1
  • 2
Servlet begin --22:33:57 +0800
Servlet end --22:33:57 +0800
business worker finished --22:34:05 +0800
  • 1
  • 2
  • 3

注意: 使用浏览器访问,因为各个浏览器的http请求超时设置不同,比如我的chrome是30秒。AsyncContext中对应的工作线程的持续时间需要小于浏览器的http超时时间。

AsyncListener

AsyncContext还可以设置一个Listener,对4个事件进行处理:

示例:

 package com.ss;

import java.io.IOException;

import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class AsyncServletTest
 */
@WebServlet(asyncSupported = true, urlPatterns = { "/AsyncTest" })
public class AsyncServletTest extends HttpServlet {

    String param = "";

    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public AsyncServletTest() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        // 1 start async
        final AsyncContext ctx = req.startAsync();
        param = ctx.getRequest().getParameter("seq");
        System.out.println("getRequest request seq: " + param);

        // 2 set the timeout
        ctx.setTimeout(0);

        // 3 add listener
        ctx.addListener(new AsyncListener() {

            @Override
            public void onTimeout(AsyncEvent arg0) throws IOException {
                System.out.println("onTimeout...");
            }

            @Override
            public void onStartAsync(AsyncEvent arg0) throws IOException {
                System.out.println("onStartAsync...");
            }

            @Override
            public void onError(AsyncEvent arg0) throws IOException {
                System.out.println("onError...");
            }

            @Override
            public void onComplete(AsyncEvent arg0) throws IOException {
                System.out.println("onComplete...");
            }
        });

        // 4 run a thread
        ctx.start(new Runnable() {
            @Override
            public void run() {
                String seq = ctx.getRequest().getParameter("seq");

                System.out.println(">>>>>now respone: " + seq);

                int n = 0;
                try {
                    // hold until receive exit
                    while (!param.equals("exit")) {

                        n++;
                        if (n % 100000000 == 0) {

                            System.out.println(seq + ": ..." + n);
//                          
                        }
                    }
                    ctx.getResponse().getWriter().write(seq+" -- "+n);

                } catch (IOException e) {
                    e.printStackTrace();
                }

                ctx.complete();
            }

        });
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("doPost...");
    }

}
分享到:
评论

相关推荐

    apache-tomcat-9.0.82.tar.gz

    Tomcat简单的说就是一个运行JAVA的网络服务器,底层是Socket的一个程序,它也是JSP和Serlvet的一个容器。如果你学过html,css,你会知道你写的页面只能自己访问,别人不能远程访问你写的页面,Tomcat就是提供能够让...

    jp+serlvet购物车

    - **Tomcat**:作为Servlet容器运行应用。 - **MVC模式**:Model-View-Controller架构设计,用于分离业务逻辑、数据和用户界面。 - **HTML/CSS/JavaScript**:用于构建前端页面。 - **Ajax**:实现异步通信,...

    tomcat6.0web服务器

    Apache Tomcat V6.0 Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总...

    apache-tomcat-7.0.82

    Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...

    apache-tomcat-6.0.20.rar

    Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...

    tomcat-5.5.26

    Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...

    jakarta-tomcat-5.0.30.tar.gz

    总的来说,Jakarta Tomcat 5.0.30是一款高效且可靠的Web服务器,它的轻量级特性使得它成为中小型项目的理想选择。通过深入理解其内部结构和配置,开发者能够更好地利用Tomcat构建和部署Java Web应用,从而提高开发...

    apache-tomcat-6.0.18.rar(tamcat服务器6.0)

    Apache Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中...

    Serlvet CRUD 示例

    在实现这些功能时,开发者可能使用了工具如Eclipse或IntelliJ IDEA作为集成开发环境,Tomcat或Jetty作为Servlet容器,MySQL或Oracle作为后台数据库。他们可能还介绍了如何使用MVC(Model-View-Controller)设计模式...

    apache-tomcat-8.5.39

    Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...

    serlvet-api.jar

    serlvet-api.jar。使用tomcat开发时,需要引入的jar包。

    tomcat安装及配置教程资源合集

    Tomcat 是一个免费的开源的 Serlvet 容器,它是 Apache 基金会的 Jakarta 项目中的一个核心项目,由 Apache,Sun 和其它一些公司及个人共同开发而成。由于有了 Sun的参与和支持,最新的 Servlet 和 Jsp 规范总能在 ...

    jsp+serlvet BBS系统

    总的来说,"jsp+serlvet BBS系统"是一个典型的Web应用开发实例,它涵盖了Web开发的多个关键领域,对于学习和理解Java Web技术,尤其是JSP和Servlet的结合使用,具有很高的实践价值。通过深入研究这个项目,开发者...

    基于serlvet的员工部门管理系统

    首先,Servlet的基本工作流程是:客户端发送HTTP请求到服务器,服务器接收到请求后,通过Servlet容器(如Tomcat)调用相应的Servlet实例进行处理。Servlet根据请求内容执行业务逻辑,然后生成响应,最后由服务器将...

    jaxmao-tomcat-5.5.20中文版

    Tomcat是一个免费的开源的Serlvet容器,它是Apache基金会的Jakarta项目中的一个核心项目,由Apache,Sun和其它一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和Jsp规范总能在Tomcat中得到体现...

    java serlvet 高校学生画像平台Myeclipse开发mysql数据库web结构java编程计算机网页项目echart

    java serlvet 高校学生画像平台系统是一套完善的java web信息管理系统 系统采用serlvet+dao+bean 模式开发本系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代 码和数据库,系统主要采用B/S模式开发。...

    JSP仓库管理系统(Javabean+serlvet)

    **7. 用户界面与交互设计** 用户界面应直观易用,提供清晰的操作指南和反馈信息。在仓库管理系统中,可能包括库存查询、入库出库操作、订单管理等功能模块,每个模块都需要良好的用户体验设计,使工作人员能快速熟悉...

    serlvet_1_web_

    在"serlvet_1_web_"这个主题中,我们主要探讨的是Servlet的基本概念、工作原理以及如何进行入门级别的编程实践。 Servlet是一种Java类,它扩展了服务器的功能,使得我们可以编写代码来动态生成Web内容。Servlet...

Global site tag (gtag.js) - Google Analytics