zoukankan      html  css  js  c++  java
  • servlet 最大线程数探索笔记

    1. servlet默认是单例模式的,所以是单例多线程的。如果实现了singleservlet是可以多个servlet实例,下面是一个servlet的请求生命周期
      1. 1  

        客户端请求该 Servlet;
        加载 Servlet 类到内存;
        实例化并调用init()方法初始化该 Servlet;
        service()(根据请求方法不同调用doGet() 或者 doPost(),此外还有doHead()、doPut()、doTrace()、doDelete()、doOptions()、destroy())。
        加载和实例化 Servlet。这项操作一般是动态执行的。然而,Server 通常会提供一个管理的选项,用于在 Server 启动时强制装载和初始化特定的 Servlet。
        Server 创建一个 Servlet的实例

        .然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法

      2. servlet可以是异步处理的,work线程立即返回,调用request.startAsync()获取到该请求对应的AsyncContext,然后调用AsyncContext的start()方法进行异步处理。但是另外一个线程池中又新增了一个线程,其中io操作还是会阻塞;
    2. servlet3.0和3.1

    https://www.cnblogs.com/davenkin/p/async-servlet.html
    在Servlet 3.0之前,Servlet采用Thread-Per-Request的方式处理请求,即每一次Http请求都由某一个线程从头到尾负责处理。如果一个请求需要进行IO操作,比如访问数据库、调用第三方服务接口等,那么其所对应的线程将同步地等待IO操作完成, 而IO操作是非常慢的,所以此时的线程并不能及时地释放回线程池以供后续使用,在并发量越来越大的情况下,这将带来严重的性能问题。即便是像Spring、Struts这样的高层框架也脱离不了这样的桎梏,因为他们都是建立在Servlet之上的。为了解决这样的问题,Servlet 3.0引入了异步处理,然后在Servlet 3.1中又引入了非阻塞IO来进一步增强异步处理的性能。

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    AsyncContext asyncContext = request.startAsync();
    
    asyncContext.start(() -> {
    new LongRunningProcess().run();
    try {
    asyncContext.getResponse().getWriter().write("Hello World!");
    } catch (IOException e) {
    e.printStackTrace();
    }
    asyncContext.complete();
    });
    
    }

    此时,我们先通过request.startAsync()获取到该请求对应的AsyncContext,然后调用AsyncContext的start()方法进行异步处理,处理完毕后需要调用complete()方法告知Servlet容器。start()方法会向Servlet容器另外申请一个新的线程(可以是从Servlet容器中已有的主线程池获取,也可以另外维护一个线程池,不同容器实现可能不一样),然后在这个新的线程中继续处理请求,而原先的线程将被回收到主线程池中。事实上,这种方式对性能的改进不大,因为如果新的线程和初始线程共享同一个线程池的话,相当于闲置下了一个线程,但同时又占用了另一个线程。

     Servlet 3.0对请求的处理虽然是异步的,但是对InputStream和OutputStream的IO操作却依然是阻塞的,对于数据量大的请求体或者返回体,阻塞IO也将导致不必要的等待。因此在Servlet 3.1中引入了非阻塞IO(参考下图红框内容),通过在HttpServletRequest和HttpServletResponse中分别添加ReadListener和WriterListener方式,只有在IO数据满足一定条件时(比如数据准备好时),才进行后续的操作

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            AsyncContext asyncContext = request.startAsync();
            ServletInputStream inputStream = request.getInputStream();
            inputStream.setReadListener(new ReadListener() {
                @Override
                public void onDataAvailable() throws IOException {
                }
                @Override
                public void onAllDataRead() throws IOException {
                    executor.execute(() -> {
                        new LongRunningProcess().run();
                        try {
                            asyncContext.getResponse().getWriter().write("Hello World!");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        asyncContext.complete();
                    });
                }
                @Override
                public void onError(Throwable t) {
                    asyncContext.complete();
                }
            });
        }
    }
  • 相关阅读:
    “我爱淘”冲刺阶段Scrum站立会议1
    《大道至简》阅读笔记3
    冲刺阶段站立会议每天任务3
    冲刺阶段站立会议每天任务2
    冲刺阶段站立会议每天任务1
    cnblogs体验
    《软件工程-理论、方法与实践》读书笔记三
    《软件工程-理论、方法与实践》读书笔记二
    《软件工程-理论、方法与实践》读书笔记一
    典型用户 persona
  • 原文地址:https://www.cnblogs.com/dzhou/p/10504740.html
Copyright © 2011-2022 走看看