一、server.xml结构介绍
文件结构
<server>
<service>
<connector PORT />
<engine>
<host name=www.a.com appBase=/www/a >
<context path="" docBase=/www/a />
<context path="/xuexi" docBase=/www/a/xuexi />
</host>
<host>
<context />
</host>
</engine>
</service>
</server>
解释
1、server组件是管理tomcat实例的组件,可以监听一个端口,从此端口上可以远程向该实例发送shutdown关闭命令。
2、service组件是一个逻辑组件,用于绑定connector和container,有了service表示可以向外提供服务,
就像是一般的daemon类服务的service。可以认为一个service就启动一个JVM,更严格地说,
一个engine组件才对应一个JVM(定义负载均衡时,jvmRoute就定义在Engine组件上用来标识这个JVM),
只不过connector也工作在JVM中。
3、connector组件是 监听组件,它有四个作用:
(1).开启监听套接字,监听外界请求,并和客户端建立TCP连接;
(2).使用protocolHandler解析请求中的协议和端口等信息,如http协议、AJP协议;
(3).根据解析到的信息,使用processer将分析后的请求转发给绑定的Engine;
(4).接收响应数据并返回给客户端。
4、container是容器,它是一类组件,在配置文件(如server.xml)中没有体现出来。它包含4个容器类组件:engine容器、host容器、context容器和wrapper容器。
5、engine容器用于从connector组件处接收已建立的TCP连接,还用于接收客户端发送的http请求并分析请求,然后按照分析的结果将相关参数传递给匹配出的虚拟主机。engine还用于指定默认的虚拟主机。
6、host容器定义虚拟主机,由于tomcat主要是作为servlet容器的,所以为每个webapp指定了它们的根目录appBase。
7、context容器主要是根据path和docBase获取一些信息,将结果交给其内的wrapper组件进行处理(它提供wrapper运行的环境,所以它叫上下文context)。一般来说,都采用默认的标准wrapper类,因此在context容器中几乎不会出现wrapper组件。
8、wrapper容器对应servlet的处理过程。它开启servlet的生命周期,根据context给出的信息以及解析web.xml中的映射关系,负责装载相关的类,初始化servlet对象init()、执行servlet代码service()以及服务结束时servlet对象的销毁destory()。
9、executor 组件为每个Service组件提供线程池,使得各个connector和Engine可以从线程池中获取线程处理请求(connector),从而实现tomcat的并发处理能力。一定要注意,Executor的线程池大小是为Engine组件设置,而不是为Connector设置的,Connector的线程数量由Connector组件的acceptorThreadCount属性来设置。如果要在配置文件中设置该组件,则必须设置在Connector组件的前面,以便在Connector组件中使用executor属性来引用配置好的Executor组件。如果不显式设置,则采用Connector组件上的默认配置,默认配置如下:
(1). maxThreads:最大线程数,默认值200。
(2). minSpareThreads:最小空闲线程数,默认值25。
(3). maxIdleTime:空闲线程的线程空闲多长时间才会销毁,默认值60000即1分钟。
(4). prestartminSpareThreads:是否启动executor时就直接创建等于最小空闲线程数的线程,默认值为false,即只在有连接请求进入时才会创建。
根据上面描述的tomcat组件体系结构,处理请求的大致过程其实很容易推导出来:
Client(request)–>Connector–>Engine–>Host–>Context–>Wrapper(response data)–>Connector(response header)–>Client
撇开tomcat作为servlet容器的行为。它和apache、nginx的功能大致都能对应上。例如以nginx为例,以下是nginx提供web服务时的配置结构:
server {
listen PORT; # 对应connetcor组件
server_name www.a.com; # 对应于<host name=www.a.com>
location / { # 对应于context path="",没错context就相当于nginx的localtion指令
root html; # 对应于docBase
}
location /xuexi { # 对应于context path="/xuexi"
root html/xuexi;
}
}
engine组件则没有对应配置项,engine内可以包含多个host虚拟主机,这个功能nginx里也有
更多内容见
https://blog.csdn.net/agonie201218/article/details/110495766
https://www.cnblogs.com/kismetv/p/7228274.html
二、配置示例
2.1 修改配置重启服务
connector连接器可以对外暴漏http协议、也可以暴漏AJP协议
server.xml配置如下
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<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>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxParameterCount="1000"
/>
<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="www.egon1.com" appBase="/test1" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/test1" reloadable="true" />
<Context path="/test_uri1" docBase="xxx" reloadable="true" />
<Context path="/test_uri2" docBase="yyy" reloadable="true" />
</Host>
<Host name="www.egon2.com" appBase="/test2" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="" reloadable="true" />
<Context path="/test_uri3" docBase="zzz" reloadable="true" />
</Host>
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
</Host>
</Engine>
</Service>
</Server>
创建目录
mkdir /test1
mkdir /test1/xxx
mkdir /test1/yyy
mkdir /test2
mkdir /test2/zzz
测试代码index.jsp翻到上面五个文件夹下,输出内容分别是111、222、333、444、555
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
<body>
<% out.println("hello world 111"); %>
</body>
</html>
最后重启catalina。
catalina.sh stop
catalina.sh start
2.2 配置本地解析
C:\Windows\System32\drivers\etc\hosts中添加如下记录:
192.168.71.238 www.egon1.com www.egon2.com
2.3 测试
有时候因为个人环境的问题影响有的浏览器会不支持多虚拟主机,换个浏览器测试就好(我用谷歌就不行,用火狐可能)
以下的访问都是匹配的context path=”具体的uri路径的” 的情况,uri路径匹配成功后,会去appBase/docBase里找index.jsp
[root@web03 /tmp/tomcat]# curl www.egon1.com:8080/test_uri1/ hello world 222 [root@web03 /tmp/tomcat]# [root@web03 /tmp/tomcat]# curl www.egon1.com:8080/test_uri2/ hello world 333 [root@web03 /tmp/tomcat]# curl www.egon2.com:8080/test_uri3/ hello world 555
以下的访问都是匹配的context path=”” 的情况
用域名www.egon1.com:8080访问
访问www.egon1.com:8080/xxx
访问www.egon1.com:8080/yyy
用域名www.egon2.com:8080/访问
访问:www.egon2.com:8080/zzz