Tomcat 应用部署 小节1

207 阅读12分钟

@[TOC](Tomcat 应用部署 小节1)

Tomcat

历史 起始于SUN的一个Server的参考实现项目Java Web Server,作者是James Duncan Davidson,后将项目贡献给了ASF。和ASF现有的项目合并,bing'kai'yuan 成为顶级项目,官网tomcat.apache.org/。

Tomcat仅仅实现了Java EE规范中于Servlet、JSP相关的类库,是Java EE不完整实现。

著名图书出版商O’Reilly约稿该项目成员,Davidson希望使用一个公猫作为封面,但是公猫已经被另一本书使用,书出版后封面是一只雪豹。

《Tomcat权威指南》封面如下

图片.png 1999年发布初始版本是Tomcat3.0,实现了Servlet 2.2和JSP1.1规范。

Tomcat 4.x发布时,内建了Catalina(Servlet容器)和asper(JSP engine)等。

商用的有IBM WebSphere、Oracle WebLogic(原属于BEA公司)、Oravle Occupationj、Glassfish、JBoss等。

开源实现有Tomcat、Jetty、Resin。

安装

可以使用Centos7 yum源自带的安装。yum源中是Tomcat7.0版本。

应用软件

[root@centos7 ~]# ls
anaconda-ks.cfg            apache-tomcat-8.5.42.tar.gz    initial-setup-ks.cfg     
jdk-8u191-linux-x64.rpm    test.jsp
[root@centos7 ~]# yum install jdk-8u191-linux-x64.rpm -y

[root@centos7 ~]# vim /etc/profile.d/jdk.sh
export JAVA_HOME=/usr/java/default
export PATH=$JAVA_HOME/bin:$PATH

[root@centos7 ~]# . /etc/profile.d/jdk.sh
[root@centos7 ~]# tar xf apache-tomcat-8.5.42.tar.gz -C /usr/local/
[root@centos7 ~]# cd /usr/local/
[root@centos7 local]# ln -sv apache-tomcat-8.5.42 tomcat
[root@centos7 local]# cd  tomcat
[root@centos7 tomcat]# pwd
/usr/local/tomcat

#启动tomcat
[root@centos7 tomcat]# bin/catalina.sh start

#root身份启动tomcat
[root@centos7 tomcat]# ps aux| grep tomcat
root      67661  2.6  4.6 2999680 87340 pts/1   Sl   01:21   0:01 /usr/java/default/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
root      67796  0.0  0.0 112708   976 pts/1    S+   01:22   0:00 grep --color=auto tomcat

#关闭tomcat
[root@centos7 tomcat]# bin/catalina.sh stop

上例中,启动身份是root,如果使用普通用户启动可以使用

首先 useradd -r java 建立系统账号

[root@centos7 tomcat]# useradd -r java
[root@centos7 tomcat]# id java
uid=987(java) gid=981(java) groups=981(java)

[root@centos7 tomcat]# chown -R java.java ./*
[root@centos7 tomcat]# ll
total 124
drwxr-x--- 2 java java  4096 Aug 22 01:05 bin
-rw-r----- 1 java java 19534 Jun  4  2019 BUILDING.txt
drwx------ 3 java java   254 Aug 22 01:11 conf
-rw-r----- 1 java java  5407 Jun  4  2019 CONTRIBUTING.md
drwxr-x--- 2 java java  4096 Aug 22 01:05 lib
-rw-r----- 1 java java 57011 Jun  4  2019 LICENSE
drwxr-x--- 2 java java   197 Aug 22 01:11 logs
-rw-r----- 1 java java  1726 Jun  4  2019 NOTICE
-rw-r----- 1 java java  3255 Jun  4  2019 README.md
-rw-r----- 1 java java  7139 Jun  4  2019 RELEASE-NOTES
-rw-r----- 1 java java 16262 Jun  4  2019 RUNNING.txt
drwxr-x--- 2 java java    30 Aug 22 01:05 temp
drwxr-x--- 7 java java    81 Jun  4  2019 webapps
drwxr-x--- 3 java java    22 Aug 22 01:11 work


[root@centos7 tomcat]# su - java -c "/usr/local/tomcat/bin/catalina.sh start"
su: warning: cannot change directory to /home/java: No such file or directory
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/java/default
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.

#java身份启动tomcat
[root@centos7 tomcat]# ps aux| grep tomcat
java      68330  4.9  4.6 2995924 87028 ?       Sl   01:29   0:01 /usr/java/default/bin/jas -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKDorg.apache.catalina.security.SecurityListener.UMASK=0027 -Dignore.endorsed.dirs= -classpar -Dcatalina.base=/usr/local/tomcat -Dcatalina.home=/usr/local/tomcat -Djava.io.tmpdir=/us
root      68406  0.0  0.0 112708   976 pts/1    S+   01:29   0:00 grep --color=auto tomcat

目录结构

目录说明
bin服务启动,停止等相关
conf配置文件
lib库目录
logs日志目录
webapps应用程序,应用部署目录
workjsp编译后的结果文件

配置文件

文件名称说明
server.xml主配置文件
web.xml每个webapp只要"部署"后才能被访问,它的部署方式通常有web.xml进行定义,其存放位置为WEB-INF/目录中;此文件为所有的webapps提供默认部署相关的配置
contest.xml每个webapp都可以专用的配置文件,它通常由专用的配置文件contest.xml来定义,其存放位置为WEB-INF/目录中;此文件为所有的webapps提供默认配置
tomcat-users.xml用户认证的账号和密码文件
catalina.policy当使用-security选项启动tomcat时,用于为tomcat设置安全策略
catalina.propertiesjava属性的定义文件,用于设定类加载器路径,以及一些与JVM调优相关参数
logging.properties日志系统相关的配置。log4j

组件分离

  1. 顶级组件
  • Server,代表整个Tomcat容器
  1. 服务类组件
  • Service,组织Engine和Connector,里面只能包含一个Engine
  1. 连接器组件
  • Connector,有HTTP,HTTPS,AJP协议的连接器
  1. 容器类
  • Engine,Host,Context都是容器类组件,可以嵌入其他组件,内部配置如何运行应用程序、
  1. 内嵌类
  • 可以内嵌到其他组件内,valve,logger,realm,manager等。以logger举例,在不同容器组件内定义。
  1. 集群类组件
  • listener,cluster

Tomcat内部组成

有上述组件构成Tomcat,如下图

图片.png

名称说明
ServerTomcat运行的进程实例
Connector负责客户端的HTTP、HTTPS、AJP等协议的连接。一个Connector只属于某一个Engine
Service用来组织Engine和Connector的关系
Engine响应并处理用户请求。一个引擎上可以绑定多个Connector
Host虚拟主机
Context应用的上下文,配置路径映射path => directory

AJP(Apache Jserv Protocol)是一种基于TCP的二进制通讯协议。

核心组件

  • Tomcat启动一个Server进程。可以启动多个Server,但一般只启动一个
  • 创建一个service提供服务。可以创建多个Service,但一般也只创建一个
  • 每个Service中,是Engine和其连接器Connector的关联配置
  • 可以为这个Server提供多个连接器Connector,这些Connector使用了不同的协议,绑定了不同的端口。其作用就是处理来自客户端的不同的连接请求或响应。
  • Service内部还定义了Engine,引擎才是真正的处理请求的入口,其内部定义多个虚拟主机Host
  • Engine对请求头做了分析,将请求发送给相应的虚拟主机
  • 如果没有匹配,数据就发往Engine上的defaultHost缺省虚拟主机
  • Engine上的缺省虚拟主机可以修改
  • Host定义虚拟主机,虚拟主机有name名称,通过名称匹配
  • Context定义应用程序单独的路径映射和配置
<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">
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

      </Host>
    </Engine>
  </Service>
</Server>

举例:

假设来自客户的请求为:http://localhost:8080/test/index.jsp

  • 浏览器端的请求被发送到服务端端口8080,Tomcat进程监听在此端口上。通过侦听的HTTP/1.1 Connector获得此请求。
  • Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的响应。
  • Engine匹配到名为localhost的Host。即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机
  • localhost Host获得请求/test/index.jsp,匹配它所拥有的所有Context
  • Host匹配到路径为/test的Context
  • path=/test的Context获得请求/index.jsp,在它的maping table中寻找对应的servlet
  • Context匹配到URL PATTERN为*.jsp的servlet,对于JspServlet类构造HttpServletReques对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法。
  • Context把执行完了之后的HttpServletResponse对象返回给Host
  • Host把HttpServletResponse对象返回给Engine
  • Engine把HttpServletResponse对象返回给Connector
  • Connector把HttpServletResponse对象返回给浏览器端

应用部署

根目录

Tomcat中默认网站根目录时CATALINA_BASE/webapps/

在tomcat中部署主站应用程序和其他应用程序,和之前WEB服务程序不同。

nginx

假设在nginx中部署2个网站应用eshop、bbs,假设网站根目录是/var/www/html, 那么部署可以是这样的,
eshop解压缩所有文件放到/var/www/html/目录下。
bbs的文件放在/var/www/html/bbs下。

Tomcat

Tomcat中默认网站根目录是CATALINA_BASE/webapps/
在Tomcat的webapps目录中,有个非常特殊的目录ROOT,它就是网站默认根目录。
将eshop解压后的文件放到这个ROOT中。
bbs解压后文件都放在CATALINA_BASE/webapps目录下。

每个虚拟主机的目录都可以使用appBase配置自己的站点目录,里面都可以使用ROOT目录作为主站目录。

JSP WebApp目录结构

  • 主页配置:一般指定为index.jsp或index.html
  • WEB-INF/: 当前WebApp的私有资源路径,通常存储应用使用的web.xml和context.xml配置文件
  • META-INF/:类似于WEB-INF
  • classes/: 类文件,当前webapp需要的类
  • lib/: 当前应用依赖的jar包

首先把hosts文件修改 图片.png

默认主页信息 图片.png

主页实验

默认情况下,/usr/local/tomcat/webapps/ROOT/下添加一个index.html文件,

[root@centos7 ROOT]# pwd
/usr/local/tomcat/webapps/ROOT/
[root@centos7 ROOT]# echo "<h1>hello word</h1>" > index.html

刷新页面、发现有说明变化

图片.png

将/usr/local/tomcat/conf/web.xml中下面的<welcome-file-list>标签(默认页),复制到/usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml中、如下

[root@centos7 conf]# vim /usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml

图片.png

再次刷新、会回到欢迎页

图片.png

webapp归档格式

  • .war:WebApp打包
  • .jar:EJB类打包文件
  • .rar:资源适配器类打包文件
  • .ear:企业级WebApp打包 传统应用开发测试后,通常打包为war格式,这种文件部署盗链Tomcat的webapps下,还可以自动展开。
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">

部署Deploy

  • 部署:将webapp的源文件放置到目标目录,通过web.xml和context.xml文件中配置的路径就可以访问该webapp,通过类加载器加载其特有的类和依赖的类到JVM上。
    • 自动部署Auto Deploy:Tomcat发现多个这个应用就把它加载并启动起来
    • 手动部署
      • 冷部署:将webapp放到指定目录,才去启动Tomcat
      • 热部署:Tomcat服务不停止,需要依赖manager、ant脚本、tcd(tomcat client deployer) 等工具
  • 反部署undeploy:停止webapp的运行,并从JVM上清除已经加载的类,从Tomcat实例上卸载掉webapp
  • 启动start:是webapp能够访问
  • 停止stop:webapp不能访问,不能提供服务,但是JVM并不清除它

实验

  1. 添加一个文件,文件:test.jsp
[root@centos7 ~]# cat test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
<%
out.println("hello jsp");
%>
</body>
</html>

先把test.jsp放到ROOT下,试试看,访问http://YourIP:8080/(test/jsp)。

[root@centos7 ROOT]# pwd
/usr/local/tomcat/webapps/ROOT

#把/目录下的test.jsp拷贝到当前目录
[root@centos7 ROOT]# cp ~/test.jsp ./

图片.png

/usr/local/tomcat/work/Catalina/localhost/ROOT/org/apache/jsp下有转换后的文件。

#工作目录
[root@centos7 localhost]# pwd
/usr/local/tomcat/work/Catalina/localhost
[root@centos7 localhost]# ll
total 0
drwxr-x--- 2 java java  6 Aug 22 04:34 docs
drwxr-x--- 2 java java  6 Aug 22 04:34 examples
drwxr-x--- 2 java java  6 Aug 22 04:34 host-manager
drwxr-x--- 3 java java 17 Aug 22 06:45 manager
drwxr-x--- 3 java java 17 Aug 22 04:40 ROOT

#自动
[root@centos7 localhost]# cd ROOT/org/apache/jsp/
total 68
-rw-r----- 1 java java 18182 Jun  4  2019 index_jsp.class
-rw-r----- 1 java java 30078 Jun  4  2019 index_jsp.java
-rw-r----- 1 java java  5640 Aug 22 12:45 test_jsp.class   <--
-rw-r----- 1 java java  5008 Aug 22 12:45 test_jsp.java    <--
  1. 添加一个应用

模拟部署一个应用

~]# cd

#模拟常见开发项目目录组成
~]# mkdir -pv projects/myapp/{WEB-INF,METE-INF}

~]# cd projects/myapp/

#把家目录中test.jsp拷贝到此文件改名
myapp]# cp ~/test.jsp ./index.jsp
#返回上级目录
myapp]# cd ..

#手动复制项目目录到webapps目录下去
projects]# cp -r myapp/ /usr/local/tomcat/webapps/

使用http://YourIP:8080/myapp/访问试试看

配置详解

server.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
      </Host>
    </Engine>
  </Service>
</Server>
<Server port="8005" shutdown="SHUTDOWN">

8005是Tomcat的管理端口,默认监听在127.0.0.1上。SHUTDOWN这个字符串接收到后就会关闭此Server。

~]# telnet 127.0.0.1 8005
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
SHUTDOWN    <--

这个管理功能建议禁用,改为shutdown为一串猜不出的字符串。

<Server port="8005" shutdown="456asd456asd456asd">
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <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>

用户认证,配置文件是"conf/tomcat-users.xml"

打开tomcat-users.xml,我们需要一个角色manager-gui。

[root@centos7 conf]# pwd
/usr/local/tomcat/conf

[root@centos7 conf]# vim tomcat-users.xml 
...
  <role rolename="manager-gui"/>                                       <--
  <user username="123.com" password="123.com" roles="manager-gui"/>    <--
</tomcat-users>
...
conf]# pwd
/usr/local/tomcat/conf
conf]# ../bin/shutdown.sh 

conf]# ../bin/startup.sh 

Tomcat启动加载后,这些内容是常驻内存的。如果配置了新的用户,需要重启Tomcat

访问manager的时候告诉403,提示告诉去manager的context.xml中修改

图片.png 图片.png

文件路径/usr/local/tomcat/webapps/manager/META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
 <Context antiResourceLocking="false" privileged="true" >
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>

看正则表达式就知道是本地访问了,由于当前访问地址是192.168.x.x,可以修改为

conf]# pwd
/usr/local/tomcat/conf
conf]# vim  ../webapps/manager/META-INF/context.xml 
...
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192.168.*" />
...

再次测试,成功。

图片.png

图片.png


<Service name"Catalina">

一般情况下,一个Server实例配置一个Service,name属性相当于该 Service的ID。

<Connector port="8080" pprotocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

连接器配置。

redirectPort,如果访问HTTPS协议,自动转向这个连接器。但大多数时候,Tomcatl并不会开启HTTPS,因为Tomcat往往部署在内部,HTTPS性能较差。

<Engine name="Catalina" defaultHost="localhost">

引擎配置。

defaultHost指向内部定义某虚拟主机。缺省虚拟主机可以改动,默认localhost。

<Host name="localhost" appBase="webapps" unpackWAR="true" autoDeploy="true">

虚拟主机配置。

name不行是主机名,用主机名来匹配。
appBase,当期主机的网页根目录,是相对于CATALINE_HOME,也可以使用绝对路径
unpackWARs是否自动解压war格式
autoDeploy热部署,自动加载运行应用

虚拟主机配置实验

尝试再配置一个虚拟主机,并将myapp部署到/data/webapps目录下

#最后添加(如下图)
~]# vim /usr/local/tomcat/conf/server.xml
      <Host name="node1.123.com"  appBase="/data/webapps"
            unpackWARs="true" autoDeploy="true">
      </Host>

图片.png

#常见虚拟主机根目录
~]# mkdir /data/webapps/ROOT -pv

~]# cp -r ~/test.jsp /data/webapps/ROOT/index.jsp

#修改测试页面加以区分
~]# vim /data/webapps/ROOT/index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
<%
out.println("node1/jsp");    <--
%>
</body>
</html>

刚才再虚拟主机中主机名定义node1.123.com,所以需要主机再本机手动配置一个域名解析

如果是windows,修改在C:\Windows\System32\drivers\etc下的hosts文件,需要管理员权限。

使用node1.123.com:8080/访问试试看。 图片.png

Contest配置

Contest作用:

  • 路径映射
  • 应用代理配置,例如单独配置应用日志、单独配置应用访问控制
conf]# pwd
/usr/local/tomcat/conf
conf]# vim server.xml 

图片.png

path指的是访问路径

docBase,可以是绝对路径,也可以是相对路径(相对于Host的appBase)
reloadable,true表示如果WEB-INF/classes或META-INF/lib目录下.class文件有改动,就会将WEB应用重新加载。
生产环境中,会使用false来禁用。

将~/projects/myapp/下面的项目文件复制当/data/下

data]# pwd
/data

data]# cp -r webapps/ROOT/ ./mysqlv1

data]# ln -sv mysqlv1/ test
data]# ll
total 0
drwxr-xr-x 2 root root 23 Aug 23 02:34 mysqlv1
lrwxrwxrwx 1 root root  8 Aug 23 02:35 test -> mysqlv1/
drwxr-xr-x 3 root root 18 Aug 23 01:32 webapps

#修改index.jsp页面加以区分。
data]# vim mysqlv1/index.jsp 
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>jsp例子</title>
</head>
<body>
后面的内容是服务器端动态生成字符串,最后拼接在一起
<%
out.println("node1/data/test/jsp");    <--
%>
</body>
</html>

重启服务

conf]# pwd
/usr/local/tomcat/conf
conf]# ../bin/shutdown.sh 

conf]# ../bin/startup.sh 

Tomcat的配置文件server.xml中配置如下 图片.png 使用node1.123.com:8080/test/ 图片.png

注意:这里特别使用了软链接,原因就是以后版本升级,需要将软链接指向myappv2,重启Tomcat。如果新版本上线后,出现问题,重新修改软链接到上一版本的目录,并重启,就可以实现回归。