精华内容
下载资源
问答
  • 并通过源码调试的方式分析了tomcat初始化过程中各个组件主要做的事情,我们知道,tomcat作为一款企业应用级的容器,其最重要的功能就是发布应用,接收客户端的请求并响应,但是从tomcat底层其究竟是怎么从接收一个...

    前言

    在之前的篇章中,基本上了解了tomcat的整体架构,并通过源码调试的方式分析了tomcat初始化过程中各个组件主要做的事情,我们知道,tomcat作为一款企业应用级的容器,其最重要的功能就是发布应用,接收客户端的请求并响应,但是从tomcat底层其究竟是怎么从接收一个请求到最后响应给客户端,这个过程是怎么执行的呢?本篇通过源码的方式简单分析一下

    环境准备

    编写一个简单的web工程,使用本地的tomcat部署起来并运行,由于这个过程比较简单,相信做过web应用开发并使用tomcat部署过项目的同学都知道,将主要的几个文件直接贴出来,方便学习的小伙伴们参考
    在这里插入图片描述

    DemoServlet

    public class DemoServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("doGet  demo servlet .... working");
            resp.getWriter().write("hello servlet");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("doPost  demo servlet .... working");
        }
    }
    

    web.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <servlet>
            <servlet-name>demoServlet</servlet-name>
            <servlet-class>com.congge.servlet.DemoServlet</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>demoServlet</servlet-name>
            <url-pattern>/demo/findServlet</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    最后浏览器访问下,http://localhost:8080/demo/findServlet,即可得到响应结果

    在这里插入图片描述

    以上是一个非常简单的使用tomcat进行请求处理与响应的例子,通过这个案例接下来我们就要思考,从请求到响应,tomcat为我们做了哪些事情呢?

    Tomcat 请求处理流程

    在这里插入图片描述
    其实总结起来就是一句话,tomcat负责将请求交给合适的servlet处理这个请求

    还记得tomcat的容器架构图吗?通过一层层的包裹,设计了多层次容器,Tomcat是怎么确定每一个请求应该由哪个Wrapper容器里的 Servlet来处理呢?答案是,Tomcat是用Mapper组件来完成这个任务的

    Mapper组件的功能就是将用户请求的URL定位到一个Servlet,它的工作原理是: Mapper组件里保存了Web应用的配置信息,其实就是容器组件与访问路径的映射关系, 比如Host容器里配置的域名、Context容器里的Web应用路径,以及Wrapper容器里 Servlet映射的路径,你可以想象这些配置信息就是一个多层次的Map

    当一个请求到来时,Mapper组件通过解析请求URL里的域名和路径,再到自己保存的 Map里去查找,就能定位到一个Servlet。请你注意,一个请求URL最后只会定位到一个 Wrapper容器,也就是一个Servlet

    下面的示意图中 , 就描述了 当用户请求链接 order/buy接口 之 后, 是如何找到最终处理业务逻辑的servlet

    上面这幅图描述了根据请求的URL如何查找到需要执行的Servlet , 下面我们再来解析一下 , 从Tomcat的设计架构层面来分析Tomcat的请求处理

    在这里插入图片描述

    整个执行步骤分解如下:

    • Connector组件Endpoint中的Acceptor监听客户端套接字连接并接收Socket
    • 将连接交给线程池Executor处理,开始执行请求响应任务
    • Processor组件读取消息报文,解析请求行、请求体、请求头,封装成Request对象
    • Mapper组件根据请求行的URL值和请求头的Host值匹配由哪个Host容器、Context容
      器、Wrapper容器处理请求
    • CoyoteAdaptor组件负责将Connector组件和Engine容器关联起来,把生成的 Request对象和响应对象Response传递到Engine容器中,调用 Pipeline
    • Engine容器的管道开始处理,管道中包含若干个Valve、每个Valve负责部分处理逻 辑。执行完Valve后会执行基础的 Valve–StandardEngineValve,负责调用Host容器的 Pipeline
    • Host容器的管道开始处理,流程类似,最后执行 Context容器的Pipeline
    • Context容器的管道开始处理,流程类似,最后执行 Wrapper容器的Pipeline
    • Wrapper容器的管道开始处理,流程类似,最后执行 Wrapper容器对应的Servlet对象 的 处理方法

    源码分析前准备

    找到上面创建的servlet的demo位置,windows下在项目的out目录中
    在这里插入图片描述

    将整个servlet_demo1_war_exploded拷贝出来,拷贝至本地的某个tomcat的webapps目录下,文件重新命名为servlet_demo1,
    在这里插入图片描述
    启动本地的tomcat,浏览器访问:http://localhost:8080/servlet_demo1/demo/findServlet
    在这里插入图片描述

    至此,我们完成了一个简单的web应用部署到tomcat容器的过程,但这样并不利于我们阅读源码,分析请求的执行流程,为了达到这个目的,我们只需要将上面的srevlet_demo1放到源码的webapps目录下,将源码工程启动即可

    注意这里有个坑,本人在搭建这个过程时,翻了很多资料也没有人能够解答这个问题,当时在部署tomcat源码的时候,还记得在本地重新创建了一个文件目录吗?将原来的tomcat源码文件全部拷贝过来进行编译打包的

    在这里插入图片描述
    事实上,上面的servlet_demo应该放到这个catalina-home的webapps下,因为这里才是实际源码调试的位置,之前我一直放到tomcat源码目录下的webapps中导致怎么也访问不了

    在这里插入图片描述

    按照上面的步骤操作之后,我们来到源码环境,找到Bootstrap这个类,按照之前调试源码的方式右键运行main即可完成在tomcat源码环境下启动tomcat的过程
    在这里插入图片描述

    源码调试过程与分析

    参照上文中tomcat请求流程分析的时序图,下面通过断点来调试一下请求是如何执行的

    还记得在tomcat源码初始化流程分析中谈到的,当全部组件的初始化执行到最后一步,是tomcat的endpoint准别完毕,等待外部的请求进行连接吗

    那么分析请求执行流程时,我们找到这个endpoint的接收请求位置即可开始分析

    来到NioEndPoint类,从Acceptor这个内部中run中的serverSock.accept()开始,从注释也可以看出来,这里表示接收请求开始的位置
    在这里插入图片描述
    继续跟进,来到该类中的processKey方法,进去来到processSocket方法
    在这里插入图片描述
    在这个方法中我们注意到,有一个executor.execute(sc)的方法,在时序图中有交代,请求到来的时候,不会直接去处理这个请求,在tomcat8的默认线程模型中,会创建一个线程池,交给线程池去处理
    在这里插入图片描述
    既然请求要交给线程池处理,不管是线程也好,线程池也好,最终都是要执行里面derun方法的,这样去找到响应的run方法,看看都做了什么事,来到SocketProcessorBase类
    在这里插入图片描述
    在doRun这个方法中,前面的部分很好理解,做http握手的工作
    在这里插入图片描述
    在这个方法中,来到process方法
    在这里插入图片描述

    从这里开始,差不多就看到了处理请求连接的影子了,来到process方式实现类AbstratProtocol中的process
    在这里插入图片描述
    在这个方法中,其实最重要的工作就是将连接进来的请求处理并包装为request请求,以及后续将响应的请求转为response对象

    断点继续往下,来到:processor.process,即在这个方法的实现中,解析请求并包装为request请求
    在这里插入图片描述

    继续进入,
    在这里插入图片描述
    来到这个方法中的service方法
    在这里插入图片描述
    继续跟进,从这里可以看到,这里首先构造了一个request对象,然后将传入过来的socket包装对象进行解析,填充request
    在这里插入图片描述
    断点往下来到该方法的:getAdapter().service(request, response)
    在这里插入图片描述
    在这里插入图片描述

    对这个图想必大家一定不陌生,当请求对象都准备好了以后,就要开始处理请求了,具体怎么处理呢?当然是需要有一个组件能够根据你请求中的URL路径找到一个具体的servlet来处理啊

    这就是Adapter的作用,翻译过来就是请求处理的适配器,通过getAdapter获取合适的处理器,然后调用service方法进行后续的处理

    在这里插入图片描述

    往下走来到invoke方法,从这里开始,可以猜想后面的逻辑就要到容器组件层了,
    在这里插入图片描述
    也就是到达图中的 container模块了
    在这里插入图片描述

    继续往下,来到StandardEngineValve中的invoke方法,这里进入容器之后,大家一定要联想到server.xml中的容器组件层级结构,就很好理解执行的逻辑,参见下面这幅图,后面的代码逻辑就是按照这个层级进行步步解析操作
    在这里插入图片描述

    在这里插入图片描述
    继续往下走,在方法:host.getPipeline().getFirst().invoke(request, response)进入,来到StandardHostValve中
    在这里插入图片描述
    通过request获取host主机下面配置的context对象,就可以获取到我们部署的web应用
    在这里插入图片描述
    来到: context.getPipeline().getFirst().invoke(request, response),沿着上面的思路,这时候应该就要到context的处理逻辑中,
    在这里插入图片描述
    在这里插入图片描述

    继续往下,来到:wrapper.getPipeline().getFirst().invoke(request, response),接下来就走到了context中的wrapper处理器中
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在上面的容器层级结构图中发现,在Wrapper中存放的就是Servlet,在这个方法中往下,我们看到了Servlet
    在这里插入图片描述
    来到下面这里,通过wrapper得到一个servlet,给上面初始化的servlet赋值,并且得到的servlet正好就是Demo中自己编写的DemoServlet
    在这里插入图片描述
    servlet得到了之后,就要走到时序图中的filterChain那一串逻辑了,即通过得到的servlet构造出一个filterChain的对象
    在这里插入图片描述
    对于servlet中的filterChain有必要简单解释下,容器这样做个人理解可以说是提升了容器的扩展性和安全性,设想没有过滤器,所有的请求都可以访问后端的资源,这样就无法保证应用的安全性,通过过滤器,对请求的参数等进行过滤,拦截之后再访问真正的资源确保了后端资源的安全性

    同时,我们在开发web项目时,经常会自定义一些过滤器,只需要实现Filter接口重新里面的逻辑即可,最终都要在真正由servlet执行逻辑之前加入到filterChain之中,filterChain是由多个Filter的组合,各个filter负责各自的业务逻辑,但是任何一个filter执行失败,都可以阻止继续往下

    回到源码,继续往下,走到:filterChain.doFilter方法,
    在这里插入图片描述

    在这里插入图片描述

    最终来到:servlet.service(request, response)方法处
    在这里插入图片描述

    继续进入service方法,在这个方法可以发现,根据请求类型的不同执行响应的业务逻辑模块代码,
    在这里插入图片描述

    当执行doGet时候,由于上面已经定位到我们自己的DemoServlet了,这时就会去执行自定义的servlet的doGet方法
    在这里插入图片描述
    通过控制台可以看到输出的结果
    在这里插入图片描述

    到这里整个请求到达servlet并通过servlet处理之后响应结果的流程就完成了,当然response中的请求结果是如何输出的有兴趣的同学可以通过断点再一路返回就可以知道了

    本篇主要通过源码的跟踪方式了解了tomcat的请求是如何到达servlet进行处理的,篇幅较长,跟着断点走,相信对整个请求的执行链和底层的逻辑会有一个更深的认识

    本篇到此结束,最后感谢观看!

    展开全文
  • Tomcat是一个web应用服务器,是一个Servlet/Jsp容器,主要负责将客户端请求传递给对应的Servlet,并且将Servlet的响应数据返回给客户端。 Tomcat是基于组件的服务器。 二、Tomcat体系结构 Tomcat是一个基于组件的...

    Tomcat处理HTTP请求过程分析
    一、Tomcat是什么?
    Tomcat是一个web应用服务器,是一个Servlet/Jsp容器,主要负责将客户端请求传递给对应的Servlet,并且将Servlet的响应数据返回给客户端。
    Tomcat是基于组件的服务器。
    二、Tomcat体系结构
    Tomcat是一个基于组件的服务器,它的构成组件都是可配置的。其各个组件都在Tomcat安装目录下的…/conf/server.xml文件中配置。

    <?xml version="1.0" encoding="UTF-8"?>
     
    <!--顶层类元素,可以包含多个Service-->
     
    <Server port="8005" shutdown="SHUTDOWN">  
     
      <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
     
      <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
     
      <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
     
      <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
     
      <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
     
      <GlobalNamingResources>
     
        <Resource name="UserDatabase" auth="Container"
     
                  type="org.apache.catalina.UserDatabase"
     
                  description="User database that can be updated and saved"
     
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
     
                  pathname="conf/tomcat-users.xml" />
     
      </GlobalNamingResources>
     
      <!--顶层类元素,可包含一个Engine(container),多个connector-->
     
      <Service name="Catalina">
     
      <!--连接器类元素,代表通信接口-->
     
        <Connector port="8080" protocol="HTTP/1.1"
     
                   connectionTimeout="20000"
     
                   redirectPort="8443" />
     
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
     
        <!--容器类元素,为特定的service组件处理客户请求-->
     
        <Engine name="Catalina" defaultHost="localhost">
     
            <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
     
                   resourceName="UserDatabase"/>
     
            </Realm>
     
            <!--容器类元素,为特定的虚拟主机组件处理客户请求-->
     
          <Host name="localhost"  appBase="webapps"
     
                unpackWARs="true" autoDeploy="true">
     
            <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
     
                   prefix="localhost_access_log" suffix=".txt"
     
                   pattern="%h %l %u %t "%r" %s %b" />
     
          </Host>
     
        </Engine>
     
      </Service>
     
    </Server>
    

    在这里插入图片描述
    由上图可以看出Tomcat的心脏是两个核心组件:Connector(连接器)和Container(容器)。其中一个Container可以选择多个Connector。
    扩展:Tomcat默认提供两个Connector连接器,一个默认监听8080端口,一个默认监听8009端口,这两种连接器有什么区别呢?redirectPort有什么作用?
    (1)8080端口监听的是通过HTTP/1.1协议访问的连接,而8009端口主要负责和其他HTTP服务器(如Apache、IIS)建立连接,使用AJP/1.3协议,当Tomcat和其他服务器集成时就会使用到这个连接器。如下图。

    在这里插入图片描述

    Web1和Web2都是访问服务器的index.jsp页面。Web1直接访问Tomcat服务器,访问地址是http://localhost:8080/index.jsp。Web2访问HTTP服务器,HTTP服务器再通过访问Tomcat的8009端口找到index.jsp。假设HTTP服务器的端口为80端口,则访问地址为http://localhost:80/index.jsp 或者 http://localhost/index.jsp。
    Apache、IIS服务器一般只支持静态页面,如HTML,不支持JSP动态页面。Tomcat对HTML的解析速度不如Apache、IIS服务器。因此一般将两者整合使用。
    (2)redirectPort字面意思是重定向端口。当用户用http请求某个资源,而该资源本身又被设置了必须要https方式访问,此时Tomcat会自动重定向到这个redirectPort设置的https端口。
    三、组件
    1、Connector组件
    在这里插入图片描述

    Connector 最重要的功能就是接收连接请求然后分配线程让 Container来处理这个请求,所以Connector必然是多线程的,多线程的处理是 Connector 设计的核心。Connector监听指定端口上请求,当请求到来时创建一个request和response对象交换数据,然后新建一个线程来处理请求并把request和response传递给Engine组件,最后从Engine获取一个响应并返回给客户端。
    Connector组件常用属性说明:
    (1) address:指定连接器监听的地址,默认为所有地址,即0.0.0.0,可以自己指定地。(2) maxThreads:支持的最大并发连接数,默认为200;
    (3) port:监听的端口;
    (4) protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常为AJP/1.3;
    (5) redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口;
    (6) connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;
    (7) enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true; 进行反解的,可以设置为false。
    (8) acceptCount:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;

    2.container组件

    在这里插入图片描述

    Container是容器的父接口,该容器的设计用的是典型的责任链的设计模式,它由四个子容器组件构成,分别是Engine、Host、Context、Wrapper。这四个组件是负责关系,存在包含关系。其中Engine是最顶层,每个service 最多只能有一个Engine, Engine 里面可以有多个Host ,每个Host 下可以有多个Context ,每个Context 下可以有多个Wrapper。通常一个Servlet class对应一个Wrapper,如果有多个Servlet则定义多个Wrapper,如果有多个Wrapper就要定义一个更高的Container,如Context。 Context定义在父容器 Host 中,其中Host 不是必须的,但是要运行 war 程序,就必须要 Host,因为 war 中必有 web.xml 文件,这个文件的解析就需要 Host 了,如果要有多个 Host 就要定义一个 top 容器 Engine 了。而 Engine 没有父容器了,一个 Engine 代表一个完整的 Servlet 引擎。
    2.1、Engine
    Engine是Servlet处理器的一个实例,即servlet引擎, 一个Service 最多只能有一个Engine。默认为定义在server.xml中的Catalina。Engine需要defaultHost属性来为其定义一个接收所有请求的虚拟主机host组件。
    2.2、Host
    Host是Engine的子容器。一个 Host 在 Engine 中代表一个站点,也叫虚拟主机,这个虚拟主机的作用就是运行多个应用、接收并处理请求、保存一个主机应该有的信息。
    常用属性说明:
    (1)appBase:此Host的webapps目录,项目存放路径,可以使用绝对路径;
    (2)autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true;
    (3)unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true;
    2.3、Context
    Context :代表一个应用程序,对应着平时开发的一套程序,或者一个WEB-INF 目录以及下面的web.xml 文件。它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 可以没有 Engine 和 Host。Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的,还有一点就是 Context 如何才能找到正确的 Servlet 来执行它呢? Tomcat5 以前是通过一个 Mapper 类来管理的,Tomcat5 以后这个功能被移到了 request 中,获取子容器都是通过 request 来分配的。
    常用属性定义:
    (1) docBase:相应的Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字;
    (2)path:相对于Web服务器根路径而言的URI;如果为空“”,则表示为此webapp的根路径;如果context定义在一个单独的xml文件中,此属性不需要定义,有可能是别名;
    (3) reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false;
    2.4、Wrapper
    Wrapper :每个Wrapper 封装着一个servlet,也代表一个 Servlet,它负责管理一个 Servlet,包括Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错。 Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。
    2.5、Value
    Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。

    四、Tomcat处理一个HTTP请求的过程
    在这里插入图片描述

    1.用户在浏览器中输入网址localhost:8080/test/index.jsp,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得;
    2.Connector把该请求交给它所在的Service的Engine(Container)来处理,并等待Engine的回应;
    3.Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host;
    4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)。名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为“ ”的Context去处理);
    5.path=“/test”的Context获得请求/index.jsp,在它的mapping table中寻找出对应的Servlet。Context匹配到URL Pattern为*.jsp的Servlet,对应于JspServlet类;
    6.构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost(),执行业务逻辑、数据存储等;
    7.Context把执行完之后的HttpServletResponse对象返回给Host;
    8.Host把HttpServletResponse对象返回给Engine;
    9.Engine把HttpServletResponse对象返回Connector;
    10.Connector把HttpServletResponse对象返回给客户Browser。
    11.扩展:下图是struts使用tomcat处理请求的过程
    在这里插入图片描述

    五、线程池的原理和Tomcat的Connector及线程池配置
    Tomcat处理请求流程:
    先启动若干数量的线程,并让这些线程都处于睡眠 状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处理完这个请求后,线程又处于睡眠状态。可能你也许会 问:为什么要搞得这么麻烦,如果每当客户端有新的请求时,我就创建一个新的线程不就完了?这也许是个不错的方法,因为它能使得你编写代码相对容易一些,但 你却忽略了一个重要的问题??性能!例如:一个省级数据大集中的银行网络中心,高峰期每秒的客户端请求并发数超过100,如果 为每个客户端请求创建一个新线程的话,那耗费的CPU时间和内存将是惊人的,如果采用一个拥有200个线程的线程池,那将会节约大量的的系统资源,使得更 多的CPU时间和内存用来处理实际的商业应用,而不是频繁的线程创建与销毁。
    配置executor属性(各项参数值根据自身情况配置)
    1.1)打开/conf/server.xml文件,在Connector之前配置一个线程池:

    参数详解:
    name:共享线程池的名字。这是Connector为了共享线程池要引用的名字,该名字必须唯一。默认值:None;
    namePrefix:在JVM上,每个运行线程都可以有一个name 字符串。这一属性为线程池中每个线程的name字符串设置了一个前缀,Tomcat将把线程号追加到这一前缀的后面。默认值:tomcat-exec-;
    maxThreads:该线程池可以容纳的最大线程数。默认值:200;
    maxIdleTime:在Tomcat关闭一个空闲线程之前,允许空闲线程持续的时间(以毫秒为单位)。只有当前活跃的线程数大于minSpareThread的值,才会关闭空闲线程。默认值:60000(一分钟)。
    minSpareThreads:Tomcat应该始终打开的最小不活跃线程数。默认值:25。
    配置Connector

    参数详解:
    executor:表示使用该参数值对应的线程池;
    minProcessors:服务器启动时创建的处理请求的线程数;
    maxProcessors:最大可以创建的处理请求的线程数;
    acceptCount:指定当所有可以使用的处理请求的线程数都被使用时,可以放到处理队列中的请求数,超过这个数的请求将不予处理。
    问题:
    1.为什么要多线程?
    答:因为如果不采用多线程的策略,那么所有的请求放在一起处理,会大大降低CPU的使用效率,系统处理业务的效率也会因此大打折扣。采用多线程,可以提高CPU的使用效率,进而提高系统处理业务的效率。
    2.为什么多线程的情景下,系统只需要准备一份程序代码就够了?
    答:因为Tomcat从本质上来讲,是一个JVM进程。一个JVM可以派生出多个线程,每个线程都有自己的程序计数器、虚拟机栈、本地方法栈、所有线程共用堆区和方法区(元数据区)。学习ucosii操作系统时,可以知道真正在CPU上执行的单元是任务,并且任务之间可以切换。每个任务都有自己的任务控制块和任务堆栈,并且任务控制块中有一个指针SP指向任务堆栈,而任务堆栈中又有一个指针PC指向任务程序代码。ucosii中任务切换时,只要在代码中替换SP就可以实现任务切换。同理,在JVM中,线程的切换也是类似的道理。存在方法区或元数据区的代码是静态的,线程真正关心的是代码执行进度。形象的比喻一下,线程好比参加赛跑的运动员,存在方法区或元数据区的代码就好比一个用来制作跑到的模块,每个运动员都要依照模板制作一条属于自己的跑道,然后在上面跑起来。而自然的,系统只需要准备一份程序代码就够了。
    六、tomcat线程池和jdk线程池的关系
    前言
    Tomcat/Jetty 是目前比较流行的 Web 容器,两者接受请求之后都会转交给线程池处理,这样可以有效提高处理的能力与并发度。JDK 提高完整线程池实现,但是 Tomcat/Jetty 都没有直接使用。Jetty 采用自研方案,内部实现 QueuedThreadPool 线程池组件,而 Tomcat 采用扩展方案,踩在 JDK 线程池的肩膀上,扩展 JDK 原生线程池。
    JDK 原生线程池可以说功能比较完善,使用也比较简单,那为何 Tomcat/Jetty 却不选择这个方案,反而自己去动手实现那?
    JDK 线程池
    通常我们可以将执行的任务分为两类:
    cpu 密集型任务
    io 密集型任务
    cpu 密集型任务,需要线程长时间进行的复杂的运算,这种类型的任务需要少创建线程,过多的线程将会频繁引起上文切换,降低任务处理处理速度。
    而 io 密集型任务,由于线程并不是一直在运行,可能大部分时间在等待 IO 读取/写入数据,增加线程数量可以提高并发度,尽可能多处理任务。
    JDK 原生线程池工作流程如下:
    在这里插入图片描述
    上图假设使用 LinkedBlockingQueue 。
    灵魂拷问:上述流程是否记错过?在很长一段时间内,我都认为线程数量到达最大线程数,才放入队列中。 ̄□ ̄||
    上图中可以发现只要线程池线程数量大于核心线程数,就会先将任务加入到任务队列中,只有任务队列加入失败,才会再新建线程。也就是说原生线程池队列未满之前,最多只有核心线程数量线程。
    这种策略显然比较适合处理 cpu 密集型任务,但是对于 io 密集型任务,如数据库查询,rpc 请求调用等,就不是很友好了。
    由于 Tomcat/Jetty 需要处理大量客户端请求任务,如果采用原生线程池,一旦接受请求数量大于线程池核心线程数,这些请求就会被放入到队列中,等待核心线程处理。这样做显然降低这些请求总体处理速度,所以两者都没采用 JDK 原生线程池。
    解决上面的办法可以像 Jetty 自己实现线程池组件,这样就可以更加适配内部逻辑,不过开发难度比较大,另一种就像 Tomcat 一样,扩展原生 JDK 线程池,实现比较简单。
    下面主要以 Tomcat 扩展线程池,讲讲其实现原理。
    扩展线程池
    首先我们从 JDK 线程池源码出发,查看如何这个基础上扩展。
    在这里插入图片描述
    可以看到线程池流程主要分为三步,第二步根据 queue#offer 方法返回结果,判断是否需要新建线程。
    JDK 原生队列类型 LinkedBlockingQueue , SynchronousQueue ,两者实现逻辑不尽相同。
    LinkedBlockingQueue
    offer 方法内部将会根据队列是否已满作为判断条件。若队列已满,返回 false ,若队列未满,则将任务加入队列中,且返回 true 。
    SynchronousQueue
    这个队列比较特殊,内部不会储存任何数据。若有线程将任务放入其中将会被阻塞,直到其他线程将任务取出。反之,若无其他线程将任务放入其中,该队列取任务的方法也将会被阻塞,直到其他线程将任务放入。
    对于 offer 方法来说,若有其他线程正在被取方法阻塞,该方法将会返回 true 。反之,offer 方法将会返回 false。
    所以若想实现适合 io 密集型任务线程池,即优先新建线程处理任务,关键在于 queue#offer 方法。可以重写该方法内部逻辑,只要当前线程池数量小于最大线程数,该方法返回 false ,线程池新建线程处理。
    当然上述实现逻辑比较糙,下面我们就从 Tomcat 源码查看其实现逻辑。
    Tomcat 扩展线程池
    Tomcat 扩展线程池直接继承 JDK 线程池 java.util.concurrent.ThreadPoolExecutor ,重写部分方法的逻辑。另外还实现了 TaskQueue ,直接继承 LinkedBlockingQueue ,重写 offer 方法。
    首先查看 Tomcat 线程池的使用方法。
    在这里插入图片描述

    可以看到 Tomcat 线程池使用方法与普通的线程池差不太多。
    接着我们查看一下 Tomcat 线程池核心方法 execute 的逻辑。
    在这里插入图片描述

    execute 方法逻辑比较简单,任务核心还是交给 Java 原生线程池处理。这里主要增加一个重试策略,如果原生线程池执行拒绝策略的情况,抛出 RejectedExecutionException 异常。这里将会捕获,然后重新再次尝试将任务加入到 TaskQueue ,尽最大可能执行任务。
    这里需要注意 submittedCount 变量。这是 Tomcat 线程池内部一个重要的参数,它是一个 AtomicInteger 变量,将会实时统计已经提交到线程池中,但还没有执行结束的任务。也就是说 submittedCount 等于线程池队列中的任务数加上线程池工作线程正在执行的任务。 TaskQueue#offer 将会使用该参数实现相应的逻辑。
    接着我们主要查看 TaskQueue#offer 方法逻辑。
    在这里插入图片描述

    核心逻辑在于第三步,这里如果 submittedCount 小于当前线程池线程数量,将会返回 false。上面我们讲到 offer 方法返回 false ,线程池将会直接创建新线程。
    Dubbo 2.6.X 版本增加 EagerThreadPool ,其实现原理与 Tomcat 线程池差不多,感兴趣的小伙伴可以自行翻阅。
    折衷方法
    上述扩展方法虽然看起不是很难,但是自己实现代价可能就比较大。若不想扩展线程池运行 io 密集型任务,可以采用下面这种折衷方法。
    new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(100));
    不过使用这种方式将会使 keepAliveTime 失效,线程一旦被创建,将会一直存在,比较浪费系统资源。
    总结
    JDK 实现线程池功能比较完善,但是比较适合运行 CPU 密集型任务,不适合 IO 密集型的任务。对于 IO 密集型任务可以间接通过设置线程池参数方式做到。

    https://www.cnblogs.com/GooPolaris/p/8111837.html
    https://www.cnblogs.com/GooPolaris/p/8115784.html
    https://blog.csdn.net/gchd19921992/article/details/79071288
    https://blog.csdn.net/gchd19921992/article/details/79076926
    https://blog.csdn.net/LeiXiaoTao_Java/article/details/85003421
    https://www.cnblogs.com/pingxin/p/p00063.html
    https://blog.csdn.net/ljxljxljx747/article/details/80142293
    https://www.cnblogs.com/weiyiming007/p/12600027.html

    展开全文
  • 早期的 Web 应用主要用于浏览新闻等静态页面,HTTP 服务器(比如 Apache、Nginx)向浏览器返回静态 HTML,浏览器负责解析 HTML,将结果呈现给用户。 随着互联网的发展,我们已经不满足于仅仅浏览静态页面,还希望...

    用户请求/响应

             浏览器与服务器之间交互,是浏览器通过与服务器建立TCP连接,并通过http的应用层协议,来传递请求数据和响应数据:

    从图上你可以看到,这个过程是:

    Tomcat 作为一个 HTTP 服务器,在这个过程中都做了些什么事情呢?

    主要是接受连接解析请求数据处理请求发送响应这几个步骤。这里请你注意,可能有成千上万的浏览器同时请求同一个 HTTP 服务器,因此 Tomcat 和 Jetty 为了提高服务的能力和并发度,往往会将自己要做的几个事情并行化(线程模型),具体来说就是使用多线程的技术。

    Servlet技术

    早期的 Web 应用主要用于浏览新闻等静态页面,HTTP 服务器(比如 Apache、Nginx)向浏览器返回静态 HTML,浏览器负责解析 HTML,将结果呈现给用户。

    随着互联网发展,用户不满足于仅仅浏览静态页面,还希望有交互,有动态效果,因此也就需要一些扩展机制能够让 HTTP 服务器调用服务端程序。

    于是 Sun 公司推出了 Servlet 技术。你可以把 Servlet 简单理解为运行在服务端的 Java 小程序,但是 Servlet 没有 main 方法,不能独立运行,因此必须把它部署到 Servlet 容器中,由容器来实例化并调用 Servlet。

    而 Tomcat 和 Jetty 就是一个 Servlet 容器。为了方便使用,它们也具有 HTTP 服务器的功能,因此 Tomcat 或者 Jetty 就是一个“HTTP 服务器 + Servlet 容器”,我们也叫它们 Web 容器

    Tomcat的连接数和线程数的区别

    详解tomcat的连接数与线程池 - 编程迷思 - 博客园

    为什么要使用spring

    Spring学习随笔(1):为什么要使用Spring

    view对象的意义

    SpringMVC之View_菜鸡旭旭-CSDN博客

    参考文献

    极客时间:李号双老师的《深入拆解Tomcat & Jetty》

    在这里,强烈推荐李老师这门课程,高屋建瓴的讲解Tomcat,读完身心愉悦

    展开全文
  • Tomcat:Tomcat是一个JSP/Servlet容器,官网地址:http://tomcat.apache.org/ 源码地址:http://archive.apache.org/dist/tomcat/其作为Servlet容器,有三种工作模式:1、独立的...Tomcat目录:tomcat|---bin:存放启...

    Tomcat:

    Tomcat是一个JSP/Servlet容器,官网地址:http://tomcat.apache.org/    源码地址:http://archive.apache.org/dist/tomcat/

    其作为Servlet容器,有三种工作模式:

    1、独立的Servlet容器、

    2、进程内的Servlet容器

    3、进程外的Servlet容器。

    Tomcat目录:

    tomcat

    |---bin:存放启动和关闭tomcat脚本

    |---conf:存放不同的配置文件(server.xml和web.xml);

    |---doc:存放Tomcat文档;

    |---lib/japser/common:存放Tomcat运行需要的库文件(JARS);

    |---logs:存放Tomcat执行时的LOG文件;

    |---src:存放Tomcat的源代码;

    |---webapps:Tomcat的主要Web发布目录(包括应用程序示例);

    |---work:存放jsp编译后产生的class文件;

    Tomcat配置文件:

    我们打开con文件夹可以看到Tomcat的配置文件:

    server.xml: Tomcat的主配置文件,包含Service, Connector, Engine, Realm, Valve, Hosts主组件的相关配置信息;(下面重点介绍)

    web.xml:遵循Servlet规范标准的配置文件,用于配置servlet,并为所有的Web应用程序提供包括MIME映射等默认配置信息;

    tomcat-user.xml:Realm认证时用到的相关角色、用户和密码等信息;Tomcat自带的manager默认情况下会用到此文件;在Tomcat中添加/删除用户,为用户  指定角色等将通过编辑此文件实现;

    catalina.policy:Java相关的安全策略配置文件,在系统资源级别上提供访问控制的能力;

    catalina.properties:Tomcat内部package的定义及访问相关控制,也包括对通过类装载器装载的内容的控制;Tomcat在启动时会事先读取此文件的相关设置;

    logging.properties: Tomcat6通过自己内部实现的JAVA日志记录器来记录操作相关的日志,此文件即为日志记录器相关的配置信息,可以用来定义日志记录的组件级别以及日志文件的存在位置等;

    context.xml:所有host的默认配置信息;

    Tomcat架构及常用的组件:

    241f58132349e15c80fe4b30e7eaa8d1.png

    1、Server组件

    如上面示例文件中定义的:

    这会让Tomcat6启动一个server实例(即一个JVM),它监听在8005端口以接收shutdown命令,使用 telnet 连接8005 端口可以直接执行 SHUTDOWN 命令来关闭 Tomcat。

    各Server的定义不能使用同一个端口,这意味着如果在同一个物理机上启动了多个Server实例,必须配置它们使用不同的端口。

    这个端口的定义用于为管理员提供一个关闭此实例的便捷途径,因此,管理员可以直接telnet至此端口使用SHUTDOWN命令关闭此实例。

    不过,基于安全角度的考虑,这通常不允许远程进行。

    Server的相关属性:

    className: 用于实现此Server容器的完全限定类的名称,默认为org.apache.catalina.core.StandardServer;

    port: 接收shutdown指令的端口,默认仅允许通过本机访问,默认为8005;

    shutdown:发往此Server用于实现关闭tomcat实例的命令字符串,默认为SHUTDOWN;

    2、Service组件:

    Service主要用于关联一个引擎和与此引擎相关的连接器,每个连接器通过一个特定的端口和协议接收入站请求交将其转发至关联的引擎进行处理。

    因此,Service要包含一个引擎、一个或多个连接器。

    如上面示例中的定义:

    这定义了一个名为Catalina的Service,此名字也会在产生相关的日志信息时记录在日志文件当中。

    Service相关的属性:

    className: 用于实现service的类名,一般都是org.apache.catalina.core.StandardService。

    name:此服务的名称,默认为Catalina;

    Connector和Container的微妙关系

    一个请求发送到Tomcat之后,首先经过Service然后会交给我们的Connector,Connector用于接收请求并将接收的请求封装为Request和Response来具体处理,Request和Response封装完之后再交由Container进行处理,Container处理完请求之后再返回给Connector,最后在由Connector通过Socket将处理的结果返回给客户端,这样整个请求的就处理完了!

    Connector最底层使用的是Socket来进行连接的,Request和Response是按照HTTP协议来封装的,所以Connector同时需要实现TCP/IP协议和HTTP协议!

    3、Connector组件:

    进入Tomcat的请求,可以根据Tomcat的工作模式,分为如下两类:

    1)、Tomcat作为应用程序服务器:请求来自于前端的web服务器,这可能是Apache, IIS, Nginx等;

    2)、Tomcat作为独立服务器:请求来自于web浏览器;

    Tomcat应该考虑工作情形并为相应情形下的请求分别定义好需要的连接器才能正确接收来自于客户端的请求。

    一个引擎可以有一个或多个连接器,以适应多种请求方式。

    定义连接器可以使用多种属性,有些属性也只适用于某特定的连接器类型。

    一般说来,常见于server.xml中的连接器类型通常有4种:

    1) HTTP连接器 2) SSL连接器 3) AJP 1.3连接器 4) proxy连接器

    如上面示例server.xml中定义的HTTP连接器:

    定义连接器时可以配置的属性非常多,

    但通常: 定义HTTP连接器时必须定义的属性只有“port“,

    定义AJP连接器时必须定义的属性只有”protocol”,因为默认的协议为HTTP。

    以下为常用属性的说明:

    1) address:指定连接器监听的地址,默认为所有地址,即0.0.0.0; 可以自己指定地,如2) maxThreads:支持的最大并发连接数,默认为200;3) port:监听的端口,默认为0;4) protocol:连接器使用的协议,默认为HTTP/1.1,定义AJP协议时通常为AJP/1.3;5) redirectPort:如果某连接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口;6) connectionTimeout:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;7) enableLookups:是否通过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true; 进行反解的,可以设置为false8) acceptCount:设置等待队列的最大长度;通常在tomcat所有处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;

    下面是一个定义了多个属性的SSL连接器:

    maxThreads=”150″ minSpareThreads=”25″ maxSpareThreads=”75″

    enableLookups=”false” acceptCount=”100″ debug=”0″ scheme=”https” secure=”true”

    clientAuth=”false” sslProtocol=”TLS” />

    Connector分为四个方面进行理解:

    (1)Connector如何接受请求的?

    (2)如何将请求封装成Request和Response的?

    (3)封装完之后的Request和Response如何交给Container进行处理的?

    (4)Container处理完之后如何交给Connector并返回给客户端的?

    Connector的结构图,如下所示:

    65af7954c5acf43f22b59fefa05b68d4.png

    Connector就是使用ProtocolHandler来处理请求的,不同的ProtocolHandler代表不同的连接类型,比如:Http11Protocol使用的是普通Socket来连接的,Http11NioProtocol使用的是NioSocket来连接的。

    其中ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。

    (1)Endpoint用来处理底层Socket的网络连接,Processor用于将Endpoint接收到的Socket封装成Request,Adapter用于将Request交给Container进行具体的处理。

    (2)Endpoint由于是处理底层的Socket网络连接,因此Endpoint是用来实现TCP/IP协议的,而Processor用来实现HTTP协议的,Adapter将请求适配到Servlet容器进行具体的处理。

    (3)Endpoint的抽象实现AbstractEndpoint里面定义的Acceptor和AsyncTimeout两个内部类和一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时,Handler用于处理接收到的Socket,在内部调用Processor进行处理。

    4、Engine组件:

    Engine是Servlet处理器的一个实例,即servlet引擎,默认为定义在server.xml中的Catalina。

    Engine需要defaultHost属性来为其定义一个接收所有发往非明确定义虚拟主机的请求的host组件。如前面示例中定义的:

    常用的属性定义:

    1)、defaultHost:Tomcat支持基于FQDN的虚拟主机,这些虚拟主机可以通过在Engine容器中定义多个不同的Host组件来实现;但如果此引擎的连接器收到一个发往非明确定义虚拟主机的请求时则需要将此请求发往一个默认的虚拟主机进行处理,因此,在Engine中定义的多个虚拟主机的主机名称中至少要有一个跟defaultHost定义的主机名称同名;

    2)、name:Engine组件的名称,用于日志和错误信息记录时区别不同的引擎;

    3)、Engine容器中可以包含Realm、Host、Listener和Valve子容器。

    5、Host组件:

    位于Engine容器中,用于接收请求并进行相应处理的主机或虚拟主机,如前面示例中的定义:

    unpackWARs=”true” autoDeploy=”true”

    xmlValidation=”false” xmlNamespaceAware=”false”>

    常用属性说明:

    1) appBase:此Host的webapps目录,即存放非归档的web应用程序的目录或归档后的WAR文件的目录路径;可以使用基于$CATALINA_HOME的相对路径;

    2) autoDeploy:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy;默认为true;

    3) unpackWars:在启用此webapps时是否对WAR格式的归档文件先进行展开;默认为true;

    虚拟主机定义示例:

    reloadable=”true” crossContext=”true”/>

    主机别名定义:

    如果一个主机有两个或两个以上的主机名,额外的名称均可以以别名的形式进行定义,如下:

    feiyu.com

    6、Context组件:

    Context在某些意义上类似于apache中的路径别名,一个Context定义用于标识tomcat实例中的一个Web应用程序;如下面的定义:

    docBase=”/web/threads/bbs”

    reloadable=”true”>

    在Tomcat6中,每一个context定义也可以使用一个单独的XML文件进行,其文件的目录为$CATALINA_HOME/conf//。可以用于Context中的XML元素有Loader,Manager,Realm,Resources和WatchedResource。

    常用的属性定义有:

    1) docBase:相应的Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;

    切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,

    比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字;2) path: 相对于Web服务器根路径而言的URI;

    如果为空“”,则表示为此webapp的根路径;

    如果context定义在一个单独的xml文件中,此属性不需要定义,有可能是别名;3) reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false;

    7、Container架构分析

    Container用于封装和管理Servlet,以及具体处理Request请求,在Connector内部包含了4个子容器,结构图如下(图C):

    f8ca9ee982ac73b09752e4cab4c24245.png

    4个子容器的作用分别是:

    (1)Engine:引擎,用来管理多个站点,一个Service最多只能有一个Engine;

    (2)Host:代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点;

    (3)Context:代表一个应用程序,对应着平时开发的一套程序,或者一个WEB-INF目录以及下面的web.xml文件;

    (4)Wrapper:每一Wrapper封装着一个Servlet;

    下面找一个Tomcat的文件目录对照一下,如下图所示:

    a9afa8823daf9743ccdd16e62e3a2023.png

    Context和Host的区别是Context表示一个应用,我们的Tomcat中默认的配置下webapps下的每一个文件夹目录都是一个Context,其中ROOT目录中存放着主应用,其他目录存放着子应用,而整个webapps就是一个Host站点。

    我们访问应用Context的时候,如果是ROOT下的则直接使用域名就可以访问,例如:www.ledouit.com,如果是Host(webapps)下的其他应用,则可以使用http://www.ledouit.com/docs进行访问,当然默认指定的根应用(ROOT)是可以进行设定的,只不过Host站点下默认的主营用是ROOT目录下的。

    8、Realm组件:

    一个Realm表示一个安全上下文,它是一个授权访问某个给定Context的用户列表和某用户所允许切换的角色相关定义的列表。

    因此,Realm就像是一个用户和组相关的数据库。

    定义Realm时惟一必须要提供的属性是classname,它是Realm的多个不同实现,用于表示此Realm认证的用户及角色等认证信息的存放位置。

    展开全文
  • 1、收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞 这个是单线程模型,无法并发,一个请求没处理完服务器就会阻塞,不会处理下一个请求。一般的服务器不会使用这种方式实现。 2、收到一个请求就新开一...
  • s reload指令,重启ngnix,如果没有报错即重启成功 (5)发出请求,获得Json,url显示依然是80端口的资源,即我们说的反向代理的特点,掩饰url,效果如下图所示: 事实上,nginx是将请求转发到Tomcat服务器,是192....
  • 检查线程池是不是太小,存在线程等待过多查看tomcat的PIDps -aux|grep tomcat查看tomcat对应的线程数ps -Lf PID|wc -l修改tomcat线程池数以及tomcat运行模式(maxThreads:tomcat起动的最大线程数,即同时处理的任务...
  • Tomcat的Web请求与处理 文章目录Tomcat的Web请求与处理前言一、NioEndPoint二、使用步骤1.引入库2.读入数据总结 前言 Connector对象创建的时候,会创建Http11NioProtocol的ProtocolHandler,在Connector的...
  • Http工作原理Http工作原理Tomcat整体架构Http服务器请求处理Servlet容器工作流程Tomcat整体架构流程说明连接器 - `**Coyote**`架构介绍IO模型和协议IO模型Tomcat 支持的应用层协议协议分层连接器组件EndPoint:...
  • 先谈谈题主说的这两种服务器模型:1、收到一个请求就处理,这个时候就不能处理新的请求,这种为阻塞这个是单线程模型,无法并发,一个请求没处理完服务器就会阻塞,不会处理下一个请求。一般的服务器不会使用这种...
  • Tomcat

    2020-12-18 11:54:20
    服务器软件:接收用户请求,处理请求,做出响应 web服务器软件:接收用户请求,处理请求,做出响应。 在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目 1.2 常见的 web服务器软件 ...
  • Tomcat概述

    2021-06-10 10:24:57
    (3)Tomcat处理请求过程(4)Tomcat中的连接器(5)Tomcat的目录(6)Tomcat常见日志三、部署Tomcat(1)实验环境(2)实验目的(3)实验步骤(4)扩展—安装mariadb数据库配置Tomcat的manager管理界面
  • 排查:通过debug日志发现,后端没有接受到前端用户的登陆数据,检查发现Tomcat在server.xml中加入了,maxPostSize=0这个参数,删除这个参数之后发现数据过去了 分析:查询了maxPostSize=0表示post请求不限制大小的 ...
  • Tomcat调优指南

    2020-12-19 05:00:31
    1概述本文档主要介绍了Tomcat的性能调优的原理和方法。可作为公司技术人员为客户Tomcat系统调优的技术指南,也可以提供给客户的技术人员作为他们性能调优的指导手册。2调优分类由于Tomcat的运行依赖于JVM,从虚拟机...
  • Tomcat 部署及优化

    千次阅读 2021-10-14 18:47:19
    Tomcat 核心组件二、Tomcat 处理请求过程 引言 Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的...
  • 版权声明:本文为CSDN博主「ThinkWon」...Tomcat的缺省端口是多少,怎么修改tomcat 有哪几种Connector 运行模式(优化)?Tomcat有几种部署方式?tomcat容器是如何创建servlet类实例?用到了什么原理?Tomcat工作模式Tomc
  • tomcat流程 起始 ​ 刚开始做项目的时候就觉得tomcat这个东西很神奇,就给项目打一个包就能当一个网站来访问,那时候就产生了一个疑惑,为什么tomcat要用servlet来搭配着使用才行,而且为什么servlet没有主方法就能...
  • 添加描述谈谈 Tomcat 请求处理流程《谈谈 Tomcat 架构及启动过程[含部署]》已重新修订!(与本文在 GitHub 同一目录下)包括架构和 Tomcat Start 过程中的 MapperListener 相关描述。Connector 启动相关的内容与请求...
  • tomcat部署与优化

    千次阅读 2021-10-25 19:17:52
    Tomcat其开源、占用系统资源少、跨平台等特性被深受喜爱。这里将介绍如何部署 Tomcat 服 务,根据生产环境实现多个虚拟主机的配置,最后的重点是进行压测,根据压测结果如何优化 Tomcat 服务及常见的内存溢出如何...
  • tomcat

    2021-10-10 15:26:25
    Tomcat 1、简述 Tomcat 是一款开源的轻量级的 Web 服务器,实现了 Servlet 规范,提供 Http 服务 Java 语言开发 架构设计优雅,灵活使用模板方法模式,层次结构清晰 2、架构图 HTTP 服务器 + Servlet 容器 ...
  • Tomcat 面试题

    2021-11-09 15:59:50
    一、Tomcat的缺省端口修改 1、打开Tomcat配置文件server.xml(路径:Tomcat-conf-server.xml) 2、在server.xml文件里面找到下列信息  <Connector connectionTimeout="20000" port="8080" protocol=...
  • Tomcat学习笔记

    2021-10-29 14:59:59
    Tomcat是⼀个Http服务器(能够接收并且处理http请求,所以tomcat是⼀个http服务器) 我们使用浏览器向某⼀个网站发起请求,发出的是Http请求,那么在远程,Http服务器接收到这个请求 之后,会调用具体的程序(Java...
  • 请求到达时,Servlet容器通过调度线程(Dispatchaer Thread)调度它管理下的线程池中等待执行的线程(Worker Thread)给请求者; 出现不同的线程同一时间访问同一个servlet的时候,servlet的对象只有一个,但是...
  • 了解了Servlet、JSP等这些模块的使用,学会了这些模块的使用,了解了MVC的基本架构之后总感觉...如何处理请求?这些原理层面的内容我们一概不知。所以非常有必要对Tomcat内部一探究竟,才能通透的理解网站的运行方式
  • 查看tomcat中jvm内存结构 图形化界面查看 localhost:8080/manager/status 可以查看manager页面 如果是远程访问tomcat,会报403无法访问错误 1.红框1中告诉我们没有权限,提示我们修改context.xml文件 manager权限...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 47,233
精华内容 18,893
关键字:

tomcat如何接受用户请求