Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML(标准通用标记语言下的一个应用)页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
部署Tomcat
配置Java环境(拖包),只建议比此版本更高的java,否则会没有后期使用的命令
$ tar zxf jdk-8u201-linux-x64.tar.gz
$ mv jdk1.8.0_201/ /usr/local/java
# 设置java的安装目录的变量
$ echo 'export JAVA_HOME=/usr/local/java
# 设置jre(Jave Runtime Environment:java运行时环境)的安装目录变量
> export JRE_HOME=/usr/local/java/jre/
# 设置类文件路径,冒号代表加的意思,引用以上设置的变量
> export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib
# 最后一行,相当于windows系统的命令环境变量,就是新添了两个java以及jre的命令变量
# $PATH代表原有的环境变量,使用变量复用
> export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin' >> /etc/profile
# 删除原先的旧java
$ rm -rf /usr/bin/java
# 执行一遍系统环境变量的脚本文件,bash和sh同样可以执行
$ source /etc/profile
$ java -version
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
安装Tomcat,不需要进行编译
tar zxf apache-tomcat-8.5.35.tar.gz
mv apache-tomcat-8.5.35 /usr/local/tomcat
启动服务:/usr/local/tomcat/bin/startup.sh
停止服务:/usr/local/tomcat/bin/shutdown.sh
Tomcat多实例
默认端口:8080
使用端口进行Tomcat多实例
cp -r /usr/local/tomcat{,1}
ls /usr/local/
tomcat tomcat1
修改配置文件
$ vim /usr/local/tomcat/conf/server.xml
修改
<Server port="8005" shutdown="SHUTDOWN"> # 关闭端口改为8006
# 服务端口和https端口分别更改8081/8444
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
# 同样也是更改端口,8010/8444
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
启动两个服务
/usr/local/tomcat/bin/startup.sh
/usr/local/tomcat1/bin/startup.sh
可以通过访问两个端口开获取页面
要首先将端口放行或者关闭防火墙
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --add-port=8081/tcp --permanent
firewall-cmd --reload
192.168.1.1:8080
和192.168.1.1:8081
Tomcat主配置文件的元素分类和整体结构
整体结构
server.xml的整体结构如下:
<Server>
<Service>
<Connector />
<Connector />
<Engine>
<Host>
<Context>
</Host>
</Engine>
</Service>
</Server>
以上只是文件中的一些核心组件
元素分类
1、顶层元素:<Server>
和<Service>
<Server>
元素是整个配置文件的根元素,只能有一个Server,<Service>
则代表一个Engine元素以及一组与之相连的Connector元素
2、连接器:<Connector>
<Connector>
代表了外部客户端发送请求到特定的Service接口;同时也是外部客户端从特定Service接收响应的接口
3、容器:<Engine><Host><Context>
容器的功能是处理Connector接收进来的请求,并产生相应的响应。Engine、Host和Context都是容器,都是它们不是平行关系,而是父子关系:Engine包含Host,Host包含Context。一个Engine组件可以处理Service中的所有请求,一个Host组件可以处理发向一个特定虚拟主机的所有请求,一个Context组件可以处理一个特定的web应用的所有请求
除了这些核心组件外,还有一些组件,可以归纳为内嵌组件
核心组件
1、Server:代表整个Tomcat容器,必须在server.xml中唯一一个最外层的元素,一个Server元素中,可以有多个Service元素
Server的主要作用就是提供一个接口让客户端能够访问到其中的Service集合
2、Service:在Connector和Engine外面报了一层Service,把他们组在一起,对外提供服务,一个Service可以包含多个Connector,都是只能包含一个Engine。
Connector是从客户端接收请求的,Engine是处理接收进来的请求
3、Connector用来接收连接请求,创建Request(请求)和Response(响应)用于和请求端交换数据;然后分配线程让Engine来处理这个请求,并把产生的Request(请求)和Response(响应)传给Engine
4、Engine用来处理接收进来的请求,Engine组件在一个Service组件中只能有一个。Engine组件从一个或者多个Connector中接收并处理,并将完成的响应返回给Connector,最终传递给客户端
5、Host:是Engine的一个子容器。Engine组件中可以内嵌一个或者多个Host组件,每个Host代表一个虚拟主机。
可以理解为一个Host就是一个网址,用来运行多个Web应用(一个Context代表一个Web应用),并负责安装/展开/启动/结束每个Web应用,Web应用也可以理解为一个网址下的目录
如:http://192.168.1.1/hello/
http://192.168.1.1
就是一个Host,/hello/
就是一个Web应用
Host配置
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
name:虚拟主机名
appBase:web应用库,该虚拟主机的所有web应用都存放正在tomcat安装目录下的webapps目录下
unpackWARs="true":对war包进行自动解压
war包时java的web项目打成的包,可以部署在tomcat,部署后就是Host下的一个web应用
autoDeploy="true":自动部署,对war包进行自动部署,在重启服务时
6、Context:表示是在Host上运行的一个Web应用,是Host的子容器,每个Host可以定义任意多的Context元素
默认Host中是没有Context的
Context配置
<Context path="/hello" docBase="/usr/local/tomcat/webapps/hello"
reloadable="false" crossContext="true"/>
path:当前web应用的存放路径
docBase:当前web应用的文件存放目录
reloadable:当class文件或者web.xml发生变化的时候,是否需要重启,false表示需要重启
crossContext:如果是集群,是否会共享会话
Context中的路径都是需要真实存在的,如果没有自己创建
mkdir /usr/local/tomcat/webapps/hello
cd /usr/local/tomcat/webapps/hello
echo "hello world" > index.jsp
/usr/local/tomcat/bin/startup.sh
curl http://192.168.1.1:8080/hello/
如果要修改网页根目录则,只需要将path=/hello
改为path=""
即可
Tomcat原理
如:现在要访问一个地址http://jf.ssjinyao.com/tags
首先客户端通过Server的接口8005来访问到这台Tomcat服务器,Tomcat服务器查看到请求是要访问http8080端口,所以Connector接收到了请求,然后分配Engine来处理这个请求,通过查看到主机域名来决定访问那一个Host(虚拟主机),经过确定,访问到jf.ssjinyao.com
,找到了/tags
的Web应用,将页面交给Connector,由它来响应给客户端
Tomcat功能
1、目录浏览
如果在访问目录中存在index.jsp
默认页面,会自动识别,如果没有则会报错404
vim /usr/local/tomcat/conf/web.xml
<param-name>listings</param-name> # 目录浏览
<param-value>true</param-value> # 是否开启
开启目录浏览后,当访问目录中不存在**index.jsp
**默认页面,会遍历目录,如下图所示,一般用于开发人员调试使用
2、JVM内存监控
Java Virtual Machine:Java虚拟机,java是不能在硬件上直接运行的,需要通过LVM,为一个java程序提供一个平台,Tomcat就是一个java程序,分为堆内存和栈内存,Tomcat使用的是堆内存
Java运行使用的内存是LVM向主机内存申请,Tomcat使用时再向LVM进行申请一部分内存
需要自己去写一下监控页面的代码
$ vim /usr/local/tomcat/webapps/hello/meminfo.jsp
<%
Runtime rtm = Runtime.getRuntime();
long mm = rtm.maxMemory()/1024/1024; # 是LVM向主机内存申请到
long fm = rtm.freeMemory()/1024/1024;
long tm = rtm.totalMemory()/1024/1024;
out.println("JVM memory detailed info:<br>");
out.println("Max memory:"+mm+"MB"+"<br>");
out.println("Free memory:"+fm+"MB"+"<br>");
out.println("Total memory:"+tm+"MB"+"<br>");
out.println("Available memory:"+(mm+fm-tm)+"MB"+"<br>");
%>
图中的440MB就是JVM申请到的内存,34是Tomcat运行申请到的内存,9是使用34后剩余的内存
JMX远程调用(Tomcat远程监控)
Tomcat假死现象
Linux服务器没有崩,有浏览器中访问页面,出现无法访问的情况,没有报4xx或5xx错误(假死),并且重启tomcat后,恢复正常
很大一部分假死的原因是tomcat空闲连接数太多,JVM内存溢出,简单理解来说就是,之前的连接没有断开,一直有新连接进来,导致tomcat假死,可以通过JVM监控监控内存以及cpu使用率发现异常。
可以根据以下的内核参数优化,以及并发的优化来处理这个问题
Tomcat远程监控
$ vim /usr/local/tomcat/bin/catalina.sh
# 307行添加以下
CATALINA_OPTS="-Djava.rmi.server.hostname=192.168.1.1 # 监控ip
-Dcom.sun.management.jmxremote # 使用JMX远程调用
-Dcom.sun.management.jmxremote.port=8080 # 监控远程调用端口8080
-Dcom.sun.management.jmxremote.ssl=false # 不使用https,使用http进行建立连接
-Dcom.sun.management.jmxremote.authenticate=true" # 监控时是否进行认证
既然选择了监控时需要认证,就要有账户密码
$ cd /usr/local/java/jre/lib/management
$ cp jmxremote.password.template jmxremote.password
$ vim jmxremote.password
取消注释,这两个就是远程调用的角色,QED和R&D用来占位,可以修改为你自己指定的密码
monitorRole QED # 默认只读
controlRole R&D # 默认可写
修改为
monitorRole 123456
controlRole 123456
授权文件
chmod 600 jmxremote.*
然后将Tomcat服务重启,使用另外一台虚拟机来验证(192.168.1.4),同样也需要java环境
# 在1.4执行命令
jconsole
会弹出一个java监视和管理控制台
远程ip为Tomcat的ip和端口号,用户名密码为刚才做的java认证用户
选择不安全的连接即可,因为在配置文件中是关闭了ssl验证的
tomcat后台管理
app manager 应用管理
vim /usr/local/tomcat/webapps/manager/META-INF/context.xml
修改:
allow="192.168.1.*" /> # 改为自己本网段
vim /usr/local/tomcat/conf/tomcat-users.xml
在文件倒数第二行添加
<role rolename="manager-gui"/> # 定义角色
<role rolename="manager-script"/>
<user username="manager" password="123.com" roles="manager-gui"/> # 用户名密码用户角色
<user username="script" password="123.com" roles="manager-script"/>
manager-gui:允许访问html接口、/manager/html,允许进入后台应用管理
manager-script:允许访问纯文本接口 /manager/text
manager-jmxproxy:允许访问jmx代理接口 /manager/jmxproxy
manager-status:允许访问Tomcat只读页面(状态页面/版本/JVM)/manager/status
前三种角色都可以访问Tomcat状态页面
重启服务
访问http://192.168.1.1:8080/manager/html
输入刚才设置好的用户名密码
登录成功
使用应用管理部署应用
直接选择一个war包文件,部署即可
可以根据以下这个表来对web应用进行简单的操作,停止,启动,重载,卸载部署
应用的部署方式
1、通过应用管理来部署
2、手动部署
拖入war包(Web应用压缩包)
如果是自动部署,只需要将war包拖入webapps目录中,重启服务,即会自动部署,可以通过查看目录的内容的变化来验证
而手动的方式,是为了不重启服务,在webapps目录中创建一个目录,作为web应用名,使用unzip将war包解压到该目录即可
mkdir /usr/local/tomcat/webapps/bdqnweb
unzip bdqnweb.war /usr/local/tomcat/webapps/bdqnweb/
host manager 主机(Host)管理
这里的主机就是Tomcat里面的虚拟主机
编辑访问权限
vim /usr/local/tomcat/webapps/host-manager/META-INF/context.xml
allow="^.*$" /> # 点表示任意一个字符,*代表前面字符的n次,代表全网段
编辑用户权限,在倒数第二行进行添加
vim /usr/local/tomcat/conf/tomcat-users.xml
<role rolename="admin-gui"/>
<user username="admin" password="123456" roles="admin-gui"/>
重启服务
/usr/local/tomcat/bin/shutdown.sh
/usr/local/tomcat/bin/startup.sh
访问http://192.168.1.1:8080/host-manager/html
输入文件中授权的用户admin
及密码
在图中的Host Name部分可以看到已有的虚拟主机
Add Virtual Host 可以添加新的虚拟主机
例:
Name(域名):jf.ssjinyao.com
Aliases(别名):
App Base:虚拟主机页面所在的web应用目录。如:/data,这个目录需要自己创建
Tomcat优化
安全(Tomcat加固)
1、端口防护
更改监听端口为非8080端口
2、禁用目录浏览
3、禁用后台管理
app-manager
host-manager
只需要将这两个目录删除即可
rm -rf /usr/local/tomcat/webapps/{app-manager,host-manager}
4、脚本权限
启动以及停止服务的文件权限修改为700,默认是750
5、服务器信息隐藏
服务器使用的程序以及版本号
$ vim /usr/local/tomcat/conf/web.xml
# 找个合适的空地编写
<error-page>
<error-code>404</error-code> # 报错404
<location>/notfound.jsp</location> # 404页面位置,在安装目录下的相对路径
</error-page>
自己在某个web应用下创建一个notfound.jsp页面
echo "page not found" > notfound.jsp
访问该页面没有的内容,将会报错page not found
参数优化
1、内核参数优化
$ vim /etc/sysctl.conf
添加
# 正常为客户端访问服务开放的端口为32768-65535,更改为2048-65535
# 其中的端口不会和访问端口冲突,是分布式访问
net.ipv4.ip_local_port_range = 2048 65535
# TCP三次握手,限制重试次数为2此,建立连接失败2次后,断开
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
# tcp连接之后1.5s之内没有传输则断开
net.ipv4.tcp_keepalive_time = 1500
# tcp挥手之后,有一方没有回应或者回应延迟,15s之后没有回应则自动断开
net.ipv4.tcp_fin_timeout = 15
# tcp连接时,队列的长度,默认1024
net.ipv4.tcp_max_syn_backlog = 20000
# 网卡接收tcp的syn的速度大于处理的速度时,允许网卡中最大的队列数
net.core.netdev_max_backlog = 65535
$ sysctl -p
2、JVM内存优化
$ vim /usr/local/tomcat/bin/catalina.sh
# 307行处添加
CATALINA_OPTS="-server -Xms256m -Xmx512m"
# -server一般放在配置项第一个,能让多核cpu的性能达到最佳
# -Xms:初始内存,第一次JVM申请的内存大小256MB
# -Xmx:JVM一共能申请内存的总大小
验证
重启服务后,8080端口处于监听状态则没有问题
3、模型优化
tomcat工作模式
1、BIO(blocking I/O阻塞I/O)
效率低,并发性能差
2、NIO(nonblocking I/O 非阻塞I/O)
基于系统缓冲区,可以提供非阻塞I/O操作,用于比BIO更高的并发
3、APR (Apache Portable Runtime Apache编写运行时)
调用httpd的动态链接库来进行文件的读取和传输,提高Tomcat对静态文件的处理能力,是Tomcat高并发的首选模式
默认工作模式是NIO,切换为APR工作模式,要先安装apr包
$ tar zxf apr-1.7.0.tar.gz -C /usr/src
$ cd /usr/src/apr-1.7.0/
$ ./configure --prefix=/usr/local/apr && make && make install
$ cd /usr/local/tomcat/bin/
[r$ ls *.tar.gz # tomcat自带
commons-daemon-native.tar.gz tomcat-native.tar.gz
$ tar zxf tomcat-native.tar.gz -C /usr/src
$ cd /usr/src/tomcat-native-1.2.18-src/native/
$ ./configure --prefix=/usr/local/apr --with-java-home=/usr/local/java && make && make install
$ echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib" >> /etc/profile
$ source /etc/profile
编辑配置文件
$ vim /usr/local/tomcat/conf/server.xml
# 找到下方位置,更改工作模式为org.apache.coyote.http11.Http11AprProtocol
<Connector port="8080" protocol="HTTP/1.1" # 这里的protocol指的是工作模式
connectionTimeout="20000"
redirectPort="8443" />
重启服务
端口号正常监听即可
$ netstat -anpt | grep 8080
tcp6 0 0 :::8080 :::* LISTEN 80406/java
4、并发优化
$ vim /usr/local/tomcat/conf/server.xml
# 找到以下的位置,检索8080即可
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol"
connectionTimeout="20000"
redirectPort="8443" />
# 修改为以下
<Connector port="8080"
protocol="org.apache.coyote.http11.Http11AprProtocol"
connectionTimeout="20000"
maxThreads="1000" # 性能最优时的最大并发量1000,Tomcat最好的并发在800-1000
minProcessors="100" # 最小线程数量
maxProcessors="1000" # 最大线程数量
minSpareThreads="100" # 最小空闲线程数量
maxSpareThreads="500" # 最大空闲线程数量
acceptCount="1000" # 请求的队列长度
URIEncoding="utf8" # 编码格式utf8
disableUploadTimeout="true" # 禁用上传超时
enableLookups="false" # 是否允许反向域名查询
redirectPort="8443" />
重启服务
监听端口8080正常监听即可