Tomcat:简介
一、概念
Tomcat 服务器是一个开源的轻量级Web应用服务器,在中小型系统和并发量小的场合下被普遍使用,是开发和调试Servlet、JSP 程序的首选。
二、原理
Tomcat结构图:
Tomcat主要组件:服务器Server,服务Service,连接器Connector、容器Container。连接器Connector和容器Container是Tomcat的核心。
一个Container容器和一个或多个Connector组合在一起,加上其他一些支持的组件共同组成一个Service服务,有了Service服务便可以对外提供能力了,但是Service服务的生存需要一个环境,这个环境便是Server,Server组件为Service服务的正常使用提供了生存环境,Server组件可以同时管理一个或多个Service服务。
三、两大组件
1、Connector
一个Connecter将在某个指定的端口上侦听客户请求,接收浏览器的发过来的 tcp 连接请求,创建一个 Request 和 Response 对象分别用于和请求端交换数据,然后会产生一个线程来处理这个请求并把产生的 Request 和 Response 对象传给处理Engine(Container中的一部分),从Engine出获得响应并返回客户。
Tomcat中有两个经典的Connector,一个直接侦听来自Browser的HTTP请求,另外一个来自其他的WebServer请求。HTTP/1.1 Connector在端口8080处侦听来自客户Browser的HTTP请求,AJP/1.3 Connector在端口8009处侦听其他Web Server(其他的HTTP服务器)的Servlet/JSP请求。
Connector 最重要的功能就是接收连接请求然后分配线程让 Container 来处理这个请求,所以这必然是多线程的,多线程的处理是 Connector 设计的核心。
2、Container
Container是容器的父接口,该容器的设计用的是典型的责任链的设计模式,它由四个自容器组件构成,分别是Engine、Host、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 引擎。
- Engine 容器
Engine 容器比较简单,它只定义了一些基本的关联关系 - Host 容器
Host 是 Engine 的子容器,一个 Host 在 Engine 中代表一个虚拟主机,这个虚拟主机的作用就是运行多个应用,它负责安装和展开这些应用,并且标识这个应用以便能够区分它们。它的子容器通常是 Context,它除了关联子容器外,还有就是保存一个主机应该有的信息。 - Context 容器
Context 代表 Servlet 的 Context,它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 可以没有 Engine 和 Host。Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的,还有一点就是 Context 如何才能找到正确的 Servlet 来执行它呢? Tomcat5 以前是通过一个 Mapper 类来管理的,Tomcat5 以后这个功能被移到了 request 中,在前面的时序图中就可以发现获取子容器都是通过 request 来分配的。 - Wrapper 容器
Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错。
Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。
3、其他组件
Tomcat 还有其它重要的组件,如安全组件 security、logger 日志组件、session、mbeans、naming 等其它组件。这些组件共同为 Connector 和 Container 提供必要的服务。
四、HTTP请求过程
Tomcat Server处理一个HTTP请求的过程
1、用户点击网页内容,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得。
2、Connector把该请求交给它所在的Service的Engine来处理,并等待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。
四、安装使用:
准备环境(CentOS7):
- 下载最新版本的安装包:
wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-9/v9.0.11/bin/apache-tomcat-9.0.11.tar.gz
wget http://download.oracle.com/otn-pub/java/jdk/8u181-b13/96a7b8442fe848ef90c96a2fad6ed6d1/jdk-8u181-linux-x64.tar.gz
2、创建tomcat用户(为了安全生产环境建议使用普通用户):
[root@zabbix-node1 ~]# useradd -u 520 tomcat
[root@zabbix-node1 ~]# passwd tomcat
Changing password for user tomcat.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
3、解压jdk和tomcat:
[root@zabbix-node1 ~]# tar zxf jdk-8u181-linux-x64.tar.gz
[root@zabbix-node1 ~]# mv jdk1.8.0_181/ /usr/local/
[root@zabbix-node1 ~]# ln -s /usr/local/jdk1.8.0_181/ /usr/local/jdk
[root@zabbix-node1 ~]#
[root@zabbix-node1 ~]# tar zxf apache-tomcat-9.0.11.tar.gz
[root@zabbix-node1 ~]# mv apache-tomcat-9.0.11 /usr/local/
[root@zabbix-node1 ~]# ln -s /usr/local/apache-tomcat-9.0.11/ /usr/local/tomcat
4、设置环境变量:
[root@zabbix-node1 ~]# tail -4 /etc/profile //最后加这四行
export JAVA_HOME=/usr/local/jdk
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar
export TOMCAT_HOME=/usr/local/tomcat
[root@zabbix-node1 ~]# source /etc/profile
[root@zabbix-node1 ~]# java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
- 将jdk和tomcat目录赋予tomcat权限:
[root@zabbix-node1 ~]# chown -R tomcat:tomcat /usr/local/jdk
[root@zabbix-node1 ~]# chown -R tomcat:tomcat /usr/local/tomcat/
- 切换到tomcat用户,启动tomcat服务:
[root@zabbix-node1 ~]# su - tomcat
[tomcat@zabbix-node1 ~]$ ls /usr/local/tomcat/bin/
bootstrap.jar ciphers.sh daemon.sh setclasspath.bat startup.sh version.bat
catalina.bat commons-daemon.jar digest.bat setclasspath.sh tomcat-juli.jar version.sh
catalina.sh commons-daemon-native.tar.gz digest.sh shutdown.bat tomcat-native.tar.gz
catalina-tasks.xml configtest.bat makebase.bat shutdown.sh tool-wrapper.bat
ciphers.bat configtest.sh makebase.sh startup.bat tool-wrapper.sh
[tomcat@zabbix-node1 ~]$ /usr/local/tomcat/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/jdk
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
[tomcat@zabbix-node1 ~]$ netstat -tunlp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN -
tcp6 0 0 :::3306 :::* LISTEN -
tcp6 0 0 :::8080 :::* LISTEN 2843/java
tcp6 0 0 :::80 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::443 :::* LISTEN -
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 2843/java
tcp6 0 0 :::8009 :::* LISTEN 2843/java
注意:因为tomcat监听的是8080端口,所以启动前是否有其他服务在使用者8080端口:
[tomcat@zabbix-node1 ~]$ ls /usr/local/tomcat/logs/ //日志的路径
catalina.2018-08-22.log host-manager.2018-08-22.log localhost_access_log.2018-08-22.txt
catalina.out //启动日志 localhost.2018-08-22.log manager.2018-08-22.log
7、访问页面http://192.168.91.133:8080/:
8、添加个用户(注意:生产环境password密码一定要复杂):
修改完重启服务:
[tomcat@zabbix-node1 ~]$ /usr/local/tomcat/bin/shutdown.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/jdk
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
[tomcat@zabbix-node1 ~]$ /usr/local/tomcat/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/jdk
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
9、测试一下web登录用户和密码:
报权限错:
403 Access Denied的解决方法,报错提示我们打开/webapps/manager/META-INF/和/webapps/host-manager/META-INF/目录下context.xml文件,不是conf/目录下的context.xml文件,一定不要搞错了:
我们将里面的内容注释掉或者修改为:
[root@zabbix-node1 ~]# vi /usr/local/apache-tomcat-9.0.11/webapps/manager/META-INF/context.xml
<!-- <Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
-->
[root@zabbix-node1 ~]# vi /usr/local/apache-tomcat-9.0.11/webapps/host-manager/META-INF/context.xml
<!-- <Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
-->
[tomcat@zabbix-node1 ~]$ /etc/init.d/tomcat.sh restart //重启再访问
下面是Manager的JVM的详情:
下面是server start,此网页为了安全,最好屏蔽或者删掉:
10、为了方便使用写了个启动脚本:
[root@zabbix-node1 ~]# vi /etc/init.d/tomcat.sh
#/bin/bash
TOMCAT_RM=/usr/local/tomcat/
TPID=$(ps aux |grep java | grep tomcat | grep -v "grep" | awk '{print $2}')
usage(){
echo "Usage: $0 [start|stop|restart|status]"
}
start_tomcat(){
/usr/local/tomcat/bin/startup.sh
}
stop_tomcat(){
kill -9 $TPID
sleep 2;
UPID=$(ps aux |grep java | grep tomcat | grep -v "grep" | awk '{print $2}')
if [ -z $UPID ];then
echo "tomcat stop!!"
else
kill -9 $UPID
cd $TOMCAT_RM
rm -rf temp/*
rm -rf work/*
fi
}
main(){
case $1 in
start)
start_tomcat
echo "start_tomcat OK"
;;
stop)
stop_tomcat
echo "stop_tomcat OK"
;;
restart)
stop_tomcat && start_tomcat
echo "stop_tomcat OK"
echo "start_tomcat OK"
;;
status)
status_tomcat
;;
*)
usage
;;
esac
}
main $1;
[root@zabbix-node1 ~]# chmod +x /etc/init.d/tomcat.sh //给执行权限
11、切换用户测试脚本:
[root@zabbix-node1 ~]# su - tomcat
Last login: Wed Aug 22 07:26:59 EDT 2018 on pts/0
[tomcat@zabbix-node1 ~]$ /etc/init.d/tomcat.sh start
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/jdk
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
start_tomcat OK
[tomcat@zabbix-node1 ~]$ /etc/init.d/tomcat.sh status
tomcat 3883 77.5 20.4 2145104 68396 pts/0 Sl 07:30 0:03 /usr/local/jdk/bin/java -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpath /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/usr/local/tomcat/temp org.apache.catalina.startup.Bootstrap start
[tomcat@zabbix-node1 ~]$
12、主配置文件是server.xml:
[tomcat@zabbix-node1 ~]$ vi /usr/local/tomcat/conf/server.xml
下面看看《tomcat安全管理规范》