• 重温web服务器--细说Tomcat服务器


     从大学开始接触java web的开发时就开始使用tomcat部署web项目,对它的理解仅仅停留在"这是个开源免费的servlet容器"的阶段,后来也接触了一些tomcat的体系,原理等方面的知识,也是半知半解,最近又开始看这方面的东西,截止到写这篇博文,我也不没有完全理解它,但一些比较基础的东西总算有些眉目了,读源码不易,且行且珍惜,这里写篇笔记整理下.

    Tomcat体系结构

      先盗张图:

        

      可以看到,Tomcat有一个最顶层的容器,也就是server容器,它最大,在server容器中,可以有多个service,由service来提供服务,所以service不能没有,至少得有一个.

      在service中,主要包含两个组件,Connector和Container.Container上图中没有标出,其实就是包含了Engine的部分.

      Tomcat可以提供多种协议的请求,http协议就是其中一种,这里以http请求为例,一个http请求发到服务器时,由Connector来接收并进行转换,Connector就是用来处理连接相关工作的组件,比如可以进行Socket与request,response之间的转换,container是一个包含了servlet等众多资源的库,它接受Connector传过来的request请求,解析出请求的资源,返回给Container,所以Connector和Container一个主外一个主内,两人共同建立起美满的家庭.

      当然上述比喻是不严谨的,因为一个Service中只有一个Container,但却可以有多个Connector,下面一段代码来自Tomcat目录下conf下的server.xml:

    复制代码
    <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
      </Service>
    复制代码

      可以看到,默认的Tomcat服务配置文件有两个Connector,一个负责监听8080端口,一个负责监听8009端口,前者我们很熟悉了,它用来监听来自于浏览器的http请求,然后会new出一个线程来把请求传给Engine,而后者则是用来监听其他类型的servlet/jsp请求,叫AJP协议(我也没听说过).

    Container体系结构

      继续盗图,Container的体系结构:

        

      Container是tomcat中容器的接口,我们最熟悉的Servlet就封装在Container的子接口Wrapper中.看一下Server.xml中的配置:

    复制代码
    <Service name="Catalina">
        <Engine name="Catalina" defaultHost="localhost">
          <Realm className="org.apache.catalina.realm.LockOutRealm">
            <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 &quot;%r&quot; %s %b" />
          </Host>
        </Engine>
      </Service>
    复制代码

      Container有四个子容器,根据图示以及xml配置就可以看出来他们是逐层包含的关系.

      每个service中只有一个Engine,Engine中可以由多个Host,每个Host可以有多个Context,每个Context中可以有多个Wrapper,而每一个Wrapper里面就封装着一个Servlet.

      下面分别简单总结几个容器:

      Engine:顾名思义,引擎,它用来管理多个站点,也就是Host.

      Host:表示一个站点,也可以叫做虚拟主机,在上面xml配置中,可以看到Tomcat默认配置了一个名为localhost的虚拟主机,我们部署,运行项目时,就默认进入这个站点,Tomcat回去webapps目录下去定位请求的web项目资源.

      Context:意思是上下文,它表示一个应用程序,也就是我们开发的一个web项目,一个web项目就可以理解为一个Context.

      Wrapper:每个Wrapper封装一个servlet.

      默认配置下的webapps下的每一目录都是一个应用,其中有一个ROOT目录代表主应用,整个webapps表示一个站点(Host),当我们检测tomcat是否启动成功时一般都会打开http://localhost:8080/,这时候如果出现tomcat的官方站点就表示启动成功,其实这时候访问的就是ROOT应用下的资源,主应用就是直接使用域名访问就可以,假设webapps下还有一个helloword目录,如果你想访问helloword目录下的资源,就需要输入http://localhost:8080/helloword/.

    conf目录下的配置文件server.xml  

    复制代码
    <Server port="8005" shutdown="SHUTDOWN">
      <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" />
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
        <Engine name="Catalina" defaultHost="localhost">
          <Realm className="org.apache.catalina.realm.LockOutRealm">
            <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 &quot;%r&quot; %s %b" />
          </Host>
        </Engine>
      </Service>
    </Server>
    复制代码

      在server.xml 中首先配置了一个server,在8005端口监听关闭命令"shutdown".

      Server里定义了一个名为Catania的Service,Service里定义了两个Connector,一个是HTTP协议,一个是AJP协议,此外还定义了一个名为Catalina的Engine,Engine里定义了一个名为localhost的Host.

      Host中name属性表示域名,所以这个默认Host可以用localhost来访问,appBase属性指定了站点的位置,这里就是webapps目录,这里还有很多属性,详细介绍,可以参考这篇博文:http://www.blogjava.net/baoyaer/articles/107278.html

     Container体系结构

      没盗到图,自己画一张:

      Connector是用来接收请求并把请求封装成Request和Response来进行具体的业务处理的,底层使用的Socket连接.

      Connector实现了TCP/IP协议和HTTP协议,他会把Request和Response按照HTTP协议来进行封装,封装完之后交给Container来进行处理,待Container处理完之后,再返回回来,Connector使用Socket将返回结果返回给浏览器,完成整个处理请求.

      下面简单介绍Connector中的几个重要组件

      ProtocolHandler:处理不同连接类型的请求,比如普通Socket请求和NioSocket请求.

      Endpoint:处理底层Socket的网络连接.实现的是TCP/IP协议.

      Processor:将Endpoint接收到的Socket请求封装成Request,实现的HTTP协议.

      Adapter: 将Request请求适配给Container来处理.

      


      整个Tomcat服务器其实就是java编写的一个应用,我尝试着读了一些源码,但资历尚浅,读的很艰难,一些代码上的实现方式和原理也不懂,只能大概理解一些类的功能,所以这里只是简单总结一些比较肤浅的知识,以后,有决心和毅力再去研读.共勉.

  • 相关阅读:
    如何添加看板娘(转载的)
    golang gin LoadHTMLGlob 加载模板文件
    wpf Popup 不跟随窗口移动的问题
    golang 在vscode 安装插件失败的解决方法
    javaweb + tomcat + 部署 + 域名绑定 + 默认首页
    【RabbitMQ】三种Exchange模式——订阅、路由、通配符模式
    一切的浮点型进行计算操作都要用BigDecimal
    如何让mysql按照两个或多个字段排序
    JAVA枚举操作(获取值,转map集合)
    gitlab 配置 ssh key
  • 原文地址:https://www.cnblogs.com/aeexiaoqiang/p/6528908.html
Copyright © 2020-2023  润新知