tomcat

Posted novalist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tomcat相关的知识,希望对你有一定的参考价值。

tomcat VS apache
Tomcat(最直接产生原因:可以直接提供Web服务的JSP服务器,当然同时也支持Servlet):
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应html(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat 部分是Apache 服务器的扩展,但它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
诀窍是,当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。
 
servlet
JSP容器对JSP文件进行自动解析并转换成Servlet类(jsp to servlet 编译过程)来交给WEB服务器运行。其中jsp与servlet是没有本质区别的,因为jsp最后在提交的时候还是要编译成servlet类。JSP是Servlet技术的扩展,是基于java servlet技术,本质上是Servlet的简易方式,更强调应用的外表表达。Servlet的应用逻辑是在Java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图,servlet主要用于控制逻辑。
当我们访问一个JSP页面的时候,这个文件首先会被JSP引擎翻译为一个Java源文件,其实就是一个Servlet,并进行编译,然后像其他Servlet一样,由Servlet引擎来处理。Servlet引擎装载这个类,处理来自客户的请求,并把结果返回给客户,以后再有客户访问这个页面的时候,只要该文件没有发生过更改,JSP引擎就直接调用已经装载的Servlet。如果已经做过修改的话,那就会再次执行以上过程,翻译、编译并装载。
Servlet的生命周期
servlet容器负责加载和实例化servlet 。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。
· 只有一个servlet对象
· 第一次请求的时候被初始化,只一遍
· 初始化后先调用init方法,只一遍
· 每个请求,调用一遍serviceàserviceàdoGet/doPost。以多线程的方式运行
· 不要在servlet中设计成员变量。
· 卸载前servlet容器调用destroy方法
 
Tomcat Server的结构图:
技术分享
1.Service是一个集合:它由一个或者多个Connector组成,以及一个Engine,负责处理所有Connector所获得的客户请求
2.一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,从Engine处获得回应并返回客户。TOMCAT有两个典型的Connector,一个直接侦听来自browser的http请求,一个侦听来自其它WebServer的请求
Coyote Http/1.1 Connector 在端口8080处侦听来自客户browser的http请求
Coyote JK2 Connector 在端口8009处侦听来自其它WebServer(Apache)的servlet/jsp代理请求
3. Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名
当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理
Engine有一个默认虚拟主机,当请求无法匹配到任何一个Host上的时候,将交给该默认Host来处理
 
Tomcat Server处理一个http请求的过程
假设来自客户的请求为:http://localhost:8080/wsota/wsota_index.jsp
1.请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得
2.Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应
3.Engine获得请求localhost/wsota/wsota_index.jsp,匹配它所拥有的所有虚拟主机Host
4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
5.localhost Host获得请求/wsota/wsota_index.jsp,匹配它所拥有的所有Context
6.Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)
7.path="/wsota"的Context获得请求/wsota_index.jsp,在它的mapping table中寻找对应的servlet
Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
8.构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
9.Context把执行完了之后的HttpServletResponse对象返回给Host
10.Host把HttpServletResponse对象返回给Engine
11.Engine把HttpServletResponse对象返回给Connector
12.Connector把HttpServletResponse对象返回给客户browser
 
 
tomcat多线程是怎么回事呢?
tomcat内部有一个线程池,如果这个servlet的访问量很大,一下子有100个人,全部过来了,tomcat 不会帮我们new出100个HelloWorldServlet的对象出来的,自始至终,这个对象只有一个,这个对象会提前准备出若干个线程,但是让一个线程跑起来,是有开销的,有时开销我们都会感觉出来的,因为线程比较耗时,所以,让线程提前跑起来,这些跑起来的线程组成一个线程池。
客户端的请求,比如,第一个请求过来了,tomcat会从线程池,分配一个空闲的线程,处理这个请求,如果同时有第二个客户端的请求过来了,tomcat从线程池里分配另外一个闲着的线程,处理第二个请求,也就是说,以是这种并发的方式进行处理的,多线程的方式处理的。
每一个线程,都是访问同一个servlet对象,都是通过这一个对象的引用,调用service()方法。
 
当容器收到一个Servlet请求,调度线程从线程池中选出一个工作者线程,将请求传递给该工作者线程,然后由该线程来执行Servlet的service方法。当这个线程正在执行的时候,容器收到另外一个请求,调度线程同样从线程池中选出另一个工作者线程来服务新的请求,容器并不关心这个请求是否访问的是同一个。
对于Tomcat可以在server.xml中通过元素设置线程池中线程的数目。
不过提醒题主一句,静态变量,这可不是线程安全的哦,要注意哇
 
1.WEB服务器:
理解WEB服务器,首先你要理解什么是WEB?WEB你可以简单理解为你所看到的HTML页面就是WEB的数据元素,处理这些数据元素的应用软件就叫WEB服务器,如IIS、apache。 WEB服务器与客户端打交道,它要处理的主要信息有:session、request、response、HTML、JS、CS等。
2.应用服务器:
应用服务器如JSP,处理的是非常规性WEB页面(JSP文件),他动态生成WEB页面,生成的WEB页面在发送给客户端(实际上当应用服务器处理完一个JSP请求并完成JSP生成HTML后它的任务就结束了,其余的就是WEB处理的过程了)。
WEB服务器与应用服务器的联系:
WEB服务器一般是通用的,而应用服务器一般是专用的,如Tomcat只处理JAVA应用程序而不能处理ASPX或php。而Apache是一个WEB服 务器f(HTTP服务器),后来连接Tomcat应用服务器来支持java。
 
1. Apache是web服务器,Tomcat是应用(java)服务器,它只是一个servlet容器,是Apache的扩展。
2. Apache和Tomcat都可以做为独立的web服务器来运行,但是Apache不能解释java程序(jsp,serverlet)。
3. Apache是普通服务器,本身只支持html即普通网页。不过可以通过插件支持php,还可以与Tomcat连通(单向Apache连接Tomcat,就是说通过Apache可以访问Tomcat资源。反之不然)
4. 两者都是一种容器,只不过发布的东西不同:Apache是html容器,功能像IIS一样;Tomcat是jsp/servlet容器,用于发布jsp及java的,类似的有IBM的webshere、EBA的Weblogic,sun的JRun等等。
5. Apache和Tomcat是独立的,在通一台服务器上可以集成。
打个比方:Apache是一辆卡车,上面可以装一些东西如html等。但是不能装水,要装水必须要有容器(桶),Tomcat就是一个桶(装像Java这样的水),而这个桶也可以不放在卡车上。
Apache只支持静态网页,但像asp,php,cgi,jsp等动态网页就需要Tomcat来处理。
6.Apache和Tomcat整合使用:如果客户端请求的是静态页面,则只需要Apache服务器响应请求;如果客户端请求动态页面,则是Tomcat服务器响应请求;因为jsp是服务器端解释代码的,这样整合就可以减少Tomcat的服务开销 。
 
catalina 就是Tomcat服务器使用的 Apache实现的servlet容器的 名字。
Tomcat的核心分为3个部分:
(1)Web容器---处理静态页面;
(2)catalina --- 一个servlet容器-----处理servlet;
(3)还有就是JSP容器,它就是把jsp页面翻译成一般的servlet。
 
tomcat文件:
技术分享
先看一下除了文件夹以外的其他文件。
LICENSE顾名思义就是许可证,里面记录了tomcat的一些条款等等。
NOTICE里面记录了tomcat的新的通知,公告。
RELEASE-NOTES这里面记录的是发行版本的说明,一些捆绑的API,新特性等等。
RUNNING.txt记录了tomcat的运行环境以及怎样配置参数,变量,启动等等。
1.bin文件夹
bin文件夹下面放的是可执行性文件,其中:bat/exe文件是windows下可执行的脚本文件。sh文件时Linux/Unix下可执行的脚本文件。其中还有一些jar文件,后面将会说到。
下面是bin文件夹下所有文件:
技术分享
技术分享
开始一一介绍。
bootstrap.jar 从文件名可以看出这个jar包是引导程序jar包,是tomcat的入口。
catalina.bat 这个脚本就比较重要了。这个脚本完成了很多基本操作,如启动关闭等,catalina.bat都参与其中。
catalina.sh文件作用同catalina.bat,只不过在Linux/Unix系统下运行。
catalina-tasks.xml 配置文件,主要是引入各种jar包。
commons-daemon-native.tar.gz Linux/Unix下。
configtest.bat 检测语法是否正确的脚本文件。
cpappend.bat 这个脚本可以这样理解,classpath(cp)append就是将指定参数添加到classpath里面。
digest.bat 博主暂时也没弄清。
service.bat 启动tomcat服务。和注册tomcat服务那块有关系。
setclasspath.bat 设置classpath的脚本,在catalin.bat脚本中调用,可以设置java_home,jre_home等。
shutdown.bat  主要是检查catalina.bat 执行所需环境,并调用catalina.bat 批处理文件关闭tomcat服务。
startup.bat 主要是检查catalina.bat 执行所需环境,并调用catalina.bat 批处理文件启动tomcat服务。
tcnative-1.dll 加速器组件,可以提高性能。(也是在网上搜到的)
 
tomcat8.exe
tomcat8w.exe
tomcat-juli.jar Apache Tomcat由一个自己的实现了java.util.logging多个关键元素的实现。这个实现被称为“JULI”。实现的核心组件是定制化的LogManager,可以获取运行在Tomcat中的不同web应用(以及不同的class loader)。他支持为应用配置单独的日志配置。当有web应用从内在中是被卸载时,会接到Tomcat的通知,以便他所引用的类可以被清除,避免内存泄露。
tomcat-native.tar.gz 里面放的是tomcat本地的library。
tool-wrapper.bat 工具包装脚本
version.bat 一般是用来判断系统版本获取系统版本信息等。
2.conf(configurator)文件夹
conf(configurator)文件夹下面放的是配置文件
技术分享
catalina.policy tomcat策略文件
catalina.properties catalina配置文件
context.xml tomcat公用的环境配置,也可以在server.xml中配置<context />
logging.properties 日志配置文件
server.xml 相当重要的配置,端口、线程池等都需要在这里配置。
web.xml 访问tomcat入口。配置加载类和资源,如欢迎页等。
3.lib文件夹
lib文件夹下面放的是tomcat提供的jar包,资源库文件。tomcat运行需要。
4.Log文件夹
log文件夹存放tomcat日志文件 
5.Temp文件夹
temp文件夹存放临时文件
6.webapps文件夹
webapps文件夹是Tomcat发布web项目的目录,默认存放了文档,examples,主机配置等文件。
7.work文件夹
存放jsp编译后的class文件。
 
tomcat组成
技术分享
Tomcat在接收到用户请求时,将会通过以上组件的协作来给最终用户产生响应。首先是最外层的Server和Service来提供整个运行环境的基础设施,而Connector通过指定的协议和接口来监听用户的请求,在对请求进行必要的处理和解析后将请求的内容传递给对应的容器,经过容器一层层的处理后,生成最终的响应信息,返回给客户端。
     Tomcat的容器通过实现一系列的接口,来统一处理一些生命周期相关的操作,而Engine、Host、Context等容器通过实现Container接口来完成处理请求时统一的模式,具体表现为该类容器内部均有一个Pipeline结构,实际的业务处理都是通过在Pipeline上添加Valve来实现,这样就充分保证整个架构的高度可扩展性。Tomcat核心组件的类图如下图所示:
技术分享
在介绍请求的处理过程时,将会详细介绍各个组件的作用和处理流程。本文将会主要分析Tomcat的启动流程,介绍涉及到什么组件以及初始化的过程,简单期间将会重点分析HTTP协议所对应Connector启动过程。
Tomcat在启动时的重点功能如下:
  • 初始化类加载器:主要初始化CommonLoader、CatalinaLoader以及SharedLoader;
  • 解析配置文件:使用Digester组件解析Tomcat的server.xml,初始化各个组件(包含各个web应用,解析对应的web.xml进行初始化);
  • 初始化连接器:初始化声明的Connector,以指定的协议打开端口,等待请求。
不管是通过命令行启动还是通过Eclipse的WST server UI,Tomcat的启动流程是在org.apache.catalina.startup. Bootstrap类的main方法中开始的,在启动时,这个类的核心代码如下所示:
技术分享
从以上的代码中,可以看到在Tomcat启动的时候,执行了三个关键方法即init、load、和start。后面的两个方法都是通过反射调用org.apache.catalina.startup.Catalina的同名方法完成的,所以后面在介绍时将会直接转到Catalina的同名方法。首先分析一下Bootstrap的init方法,在该方法中将会初始化一些全局的系统属性、初始化类加载器、通过反射得到Catalina实例,在这里我们重点看一下初始化类加载器的方法:
技术分享
在以上的代码总,我们可以看到初始化了三个类加载器,这三个类加载器将会有篇博文进行简单的介绍。
然后我们进入Catalina的load方法:
技术分享
在以上的代码中,关键的任务有两项即使用Digester组件按照给定的规则解析server.xml、调用Server的initialize方法。关于Digester组件的使用,后续会有一篇专门的博文进行讲解,而Server的initialize方法中,会发布事件并调用各个Service的initialize方法,从而级联完成各个组件的初始化。每个组件的初始化都是比较有意思的,但是我们限于篇幅先关注Connector的初始化,这可能是最值得关注的。
Connector的initialize方法,核心代码如下:
技术分享
在Http11Protocol的init方法中,核心代码如下:
技术分享
我们看到最终的初始化方法最终都会调到JIoEndpoint的init方法,网络初始化和对请求的最初处理都是通过该类及其内部类完成的,所以后续的内容将会重点关注此类:
技术分享
在上面的代码中,我们可以看到此时初始化了一个ServerSocket对象,用来准备接受请求。
如果将其比作赛跑,此时已经到了“各就各位”状态,就等最终的那声“发令枪”了,而Catalina的start方法就是“发令枪”啦:
技术分享
此时会调用Server的start方法,这里我们重点还是关注JIoEndpoint的start方法:
技术分享
从以上的代码,可以看到,如果没有在server.xml中声明Executor的话,将会使用内部的一个容量为200的线程池用来后续的请求处理。并且按照参数acceptorThreadCount的设置,初始化线程来接受请求。而Acceptor是真正的幕后英雄,接受请求并分派给处理过程:
技术分享
从这里我们可以看到,Acceptor接受Socket请求,并调用processSocket方法来进行请求的处理。至此,Tomcat的组件整装待命,等待请求的到来。关于请求的处理,会在下篇文章中介绍。
Tomcat对HTTP请求处理的整体流程
      Server:  其实就是BackGroud程序, 在Tomcat里面的Server的用处是启动和监听服务端事件(诸如重启、关闭等命令。 在tomcat的标准配置文件:server.xml里面, 我们可以看到“<Server port="8005" shutdown="SHUTDOWN" debug="0">”这里的"SHUTDOWN"就是server在监听服务端事件的时候所使用的命令字)
      Service: 在tomcat里面, service是指一类问题的解决方案。  通常我们会默认使用tomcat提供的:Tomcat-Standalone 模式的service。 在这种方式下的service既给我们提供解析jsp和servlet的服务, 同时也提供给我们解析静态文本的服务。
Connector: Tomcat都是在容器里面处理问题的, 而容器又到哪里去取得输入信息呢?
Connector就是专干这个的。 他会把从socket传递过来的数据, 封装成Request, 传递给容器来处理。
     通常我们会用到两种Connector,一种叫http connectoer, 用来传递http需求的。 另一种叫AJP, 在我们整合apache与tomcat工作的时候, apache与tomcat之间就是通过这个协议来互动的。 (说到apache与tomcat的整合工作, 通常我们的目的是为了让apache 获取静态资源, 而让tomcat来解析动态的jsp或者servlet。)

以上是关于tomcat的主要内容,如果未能解决你的问题,请参考以下文章

TomcatTomcat 原理架构

TomcatTomcat 用法 问题 整理

TomcatTomcat性能分析

TomcatTomcat的类加载机制

TomcatTomcat 介绍及使用教程

TomcatTomcat 介绍及使用教程