目录
=======================================================================
张贺,多年互联网行业工作经验,担任过网络工程师、系统集成工程师、LINUX系统运维工程师
笔者微信:zhanghe15069028807,现居济南历下区
=======================================================================
Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache服务器。目前Tomcat最新版本为9.0.31。
tomcat也是java语言写的,想要tomcat运行起来,就要安装tomcat的运行环境,也就是java se环境,jdk提供这个环境,所以先要安装jdk,然后再安装tomcat。
[root@kk tmp]# ll
drwxr-xr-x 9 root root 220 Mar 7 11:42 apache-tomcat-8.5.51
-rw-r--r-- 1 root root 126857158 Mar 7 11:48 jdk-7u67-linux-x64.rpm
[root@kk tmp]# rpm -ivh jdk-7u67-linux-x64.rpm
//配置jdk的环境变量
[root@kk ~]# vim /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/latest
export PATH=$JAVA_HOME/bin/:$PATH
[root@kk ~]# . /etc/profile.d/java.sh
[root@kk ~]# java -version
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
[root@kk local]# ln -sv apache-tomcat-8.5.51/ tomcat
‘tomcat’ -> ‘apache-tomcat-8.5.51/’
[root@kk ~]# vim /etc/profile.d/tomcat.sh
export CATLINA_HOME=/usr/local/tomcat
export PATH=$CATLINA_HOME/bin/:$PATH
[root@kk ~]# . /etc/profile.d/tomcat.sh
//验证
[root@kk ~]# version.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/java/latest
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Server version: Apache Tomcat/8.5.51
Server built: Feb 5 2020 22:26:25 UTC
Server number: 8.5.51.0
OS Name: Linux
OS Version: 3.10.0-957.el7.x86_64
Architecture: amd64
JVM Version: 1.7.0_67-b01
JVM Vendor: Oracle Corporation
//启动
[root@kk ~]# catalina.sh start|stop
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/java/latest
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
[root@kk ~]# ss -tnlp | grep 8080
LISTEN 0 100 :::8080 :::* users:(("java",pid=8653,fd=49))
//尝试自己写一个java测试页
[root@kk webapps]# mkdir mysapp/{lib,classes,WEB-INF,META-INF} -pv
[root@kk webapps]# vim mysapp/index.jsp
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title> JSP TEST PAGE </title>
</head>
<body>
<% out.println("hello,world"); %>
</body>
</html>
http://192.168.80.100:8080/myapp/
[root@kk tomcat]# tree work/
├── myapp
│?? └── org
│?? └── apache
│?? └── jsp
│?? ├── index_jsp.class #生成了这两个文件
│?? └── index_jsp.java #jasper转换的
这两个工具就是默认界面上的,很少使用:
manger app:webapp的管理工具
host manger:virtual hosts管理工具
启动、关闭
catalina.sh stop
catalina.sh start
tomcat组件:
catalina:用来实现servlet container
jsp:作用是将jsp代码转换成servlet格式的代码
coyote web,用来接收http协议
jasper:引擎的名称
tomcat的目录结构:
java webapp组织结构:
有特定的组织形式,层次型的目录结构,主要包含了servlet代码文件,jsp页面文件,类文件,部署描述文件等。
/usr/local/tomcat/webapps/ROOT
webapp归档格式:
配置文件:
tomcat的默认文件存放在$CATALINA_HOME/conf目录中,主要有以下几个:
/usr/local/tomcat/conf/server.xml
/usr/local/tomcat/conf/web.xml
/usr/local/tomcat/conf/context.xml
//主配置文件组织格式
<server>
<service>
<connector />
<connector />
…
<engine>
<host>
<context />
…
<host>
…
</engine>
</servie>
</server>
注意:每个组件都是由“类”来实现,有些组件的实现不止一种。
部署(deployment)webapp相关的操作:
所谓tomcat的部署是将webapp的源文件放置于目录目录,配置tomcat服务能够基于context.xml文件中定义的路径来访问此webapp,将共特有类通过class loader 装载至tomcat。
有两种部署方式:
冷部署:把webapp复制到指定位置,而后才启动tomcat;
热部署:不停止tomcat的前提下进行部署
部署工具:manger、ant脚本、tcd(tomcat client deployer)等;
tomcat以面对对象的方式运行,它可以在运行时动态加载加载配置文件中定义的对象结构,这有点类似于apache的httpd模块的调用方式。server.xml中定义的每个主元素都会被创建为对象,并以某特定的层次结构将这些对象组织在一起,下面是个样例的配置:
//server.xml配置文件
<Server port="8005" shutdown="SHUTDOWN"> #通过telnet登录8005端口可以关闭tomcat
[root@kk ~]# telnet 127.0.0.1 8005 #比较危险
SHUTDOWN
<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" /> #用户相关
//service,将引处的8080即侦听的端口,就在此处更改侦听的端口
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
//ssl连接器
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
//AJP(apache jserv protocol )端口8009,AJP的连接器,二进制协议,效率比较高,只有apche能对接上。
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443" />
//默认虚拟主机
<Engine name="Catalina" defaultHost="localhost">
//这里面用来定义主机的,
<Host name="localhost" appBase="webapps" #根路径,相对catalina_tome
unpackWARs="true" autoDeploy="true"> #war文档自动打开
//在主机里面,定义访问日志
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" /> #格式
tomcat的一个实例,通常一个JVM只能包含一个tomcat实例,因此,一台物理服务器可以在启动多个JVM的情况下在每一个JVM中启动一个tomcat实例,每个实例分属一个独立的管理端口,这是一个顶级组件。
一个服务组件通常包含一个引擎和此引擎相关联的一个或多个连接器。给服务命名可以方便管理员在日志文件中识别不同服务产生的日志,一个server可以包含多个service组件,但通常情况下只为一个service指派一个server
如果基于apache做为tomcat前端的架构来讲,apache通过mod_jk,mod_jk2或mod_proxy模块与后端的tomcat进程数据交换,而对tomcat来说,每个web容器实例都且人上java语言开发的连接器模块组件,在tomcat6当中,这个连接器是org.apache.catalina。
进入tomcat的请求可以根据tomcat的工作模式分为两类:
tomcat做为应用程序服务器,请求来自前端的web服务器,这可能是apahce,iis、nginx等,最是常见。
tomcat作为独立服务器,请求来自于用户浏览器。
tomcat应该考虑工作情况并为相应情形下的请求分别定义好需要的连接器才能正确接收来自客户端的请求,一个引擎可以有一个或多个连接器,以适应多种请求方式。
定义连接器可以使用多种属性,有些属性也只适用于某特定的连接器类型,一般来说,常见于server.xml中的连接器类型通常有4种:
HTTP连接器
SSL连接器
AJP 1.3连接器,专为apache准备。
//server.xml默认的连接器,用的是http协议
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
定义连接器时可用配置属性非常多,但通常寄定义http连接器时必须定义的属性只有port,定义AJP连接器时必须定义定义的属性只有protocol,默认连接器的类型为http,以下为常用属性的说明。
<Connector port="8080" protocol="HTTP/1.1"
maxThreads="150" minrSpeareThreads="25" maxSpareThreads="75" enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" connectionTimeout="20000" redirectPort="8443" />
引擎通常是指处理请求的servlet引擎组件,即catalina servlet引擎,它检查每一个请求的HTTP首部信息以判别此请求应该发往哪个host或context,并将请求处理后的结果返回相应的客户端。严格意义上来说,容器不必非得通过引擎来实现,它也可以只是一个容器,如果tomcat被配置成为独立服务器,默认引擎就是已经定义好引擎。而如果tomcat被配置为apache web服务器提供servlet功能的后端,默认引擎会被忽略,因为web服务器自身就能确定将用户请求发向何处,一个引擎可以包含多个host组件。
<Engine name="Catalina" defaultHost="localhost">
常用属性定义:
defaultHost: tomcat支持基于FQDN的虚拟主机,这些虚拟主机可以通过在engine容器中定义多个不同的host组件来实现,但如果此引擎的连接器收到一个发往非明确定义的虚拟主机的请求时则需要将此请求发往一个默认的虚拟主机进行处理,因此,在engine中定义的多个虚拟主机的主机名称至少要有一个跟defaultHost定义的主机名称相同。
name:engine组件的名称,用于日志和错误信息记录时区别不同的引擎
jvmrouter:在后面会讲,集群当中会用到
engine容器中可以包含realm、host,listener和valve子容器
位于engine容器中用于接收请求并进行相应处理的主机或虚拟主机。
主机级类型相当于apache当中的虚拟主机,但在tomcat中只支持基于FQDNr 虚拟主机,一个引擎至少 要包含一个主机组件。
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
常用属性:
appbase:此host的webapps目录,即存放非归档的web应用程序的目录或归档后的war文件的目录路径,可以使用基于$CATALINA_HOME的相对路径。
autodeploy:在tomcat处于运行状态时放置于appbase目录中的应用程序文件是否进行deploy,默认为ture。
unpackWars: 在启用此webapps时是否对var格式的归档文件先进行展开,默认为true。
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps">
<Context path="" docBase="ROOT"/>
<Context path="/bbs" docBase="/web/bss"
reloadable="true" crossContext="true"/>
</Host>
<Host name="mail.magedu.com" appBase="/web/mail">
<Context path="/" docBase="ROOT"/>
</Host>
</Engine>
主机别名定义:
如果一个主机有两个或两个以上的主机名,额外的名称均可以以别名的形式进行定义,如下:
<Host name="www.magedu.com" appBase="webapps" unpackWARs="true">
<Alias>magedu.com</Alias> #发往这个别名的请求会被定义到www.magedu.com中来
</Host>
context组件是最内层次的组件,它表示web应用程序本身。配置一个context最重要的是指定web应用程序的根目录,以便servlet容器能够将用户请求发往正确的位置。context组件也可以包含自定义的错误页,以实现在用户访问发生错误时提供友好的提示信息。
Context在某些意义上类似于apache中的路径别名,一个Context定义用于标识tomcat实例中的一个Web应用程序;如下面的定义:
<!-- Tomcat Root Context -->
<Context path="" docBase="/web/webapps"/> #PATH是指URL,docbase文件放置的位置
<!-- buzzin webapp -->
<Context path="/bbs"
docBase="/web/threads/bbs"
reloadable="true">
</Context>
<!-- chat server -->
<Context path="/chat" docBase="/web/chat"/>
<!-- darian web -->
<Context path="/darian" docBase="darian"/> #这里面的docbase是相对路径,相对于当前虚拟主机的appbase
在Tomcat6中,每一个context定义也可以使用一个单独的XML文件进行,其文件的目录为$CATALINA_HOME/conf/
常用的属性定义有:
1) docBase:相应的Web应用程序的存放位置;也可以使用相对路径,起始路径为此Context所属Host中appBase定义的路径;切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字;
2) path:相对于Web服务器根路径而言的URI;如果为空“”,则表示为此webapp的根路径;如果context定义在一个单独的xml文件中,此属性不需要定义;
3) reloadable:是否允许重新加载此context相关的Web应用程序的类;默认为false;
示例1:
<Host name="web1.zhanghe.com" appBase="/data/webapps" unpackWAR="true" autoDeploy="false">
<Contest path="" docBase="/data/webapps" reloadable="true" />
path什么也不写,表示根路径相当于web1.zhanghe.com,docbase就是文档放在哪里面了,这里面的位置代表/data/webapps/index.jsp
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs"
prefix="web1_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
[root@kk conf]# mkdir -pv /data/{webapps,logs}
mkdir: created directory ‘/data’
mkdir: created directory ‘/data/webapps’
mkdir: created directory ‘/data/logs’
[root@kk ROOT]# pwd
/data/webapps/ROOT
[root@kk ROOT]# ls
index.jsp
//访问
http://web1.zhanghe.com:8080/,如果通过IP地址访问,会再次跑到图形界面,因为它是default
示例2:
</Host>
<Host name="web1.zhanghe.com" appBase="/data/webapps" unpackWAR="true" autoDeploy="false">
<Contest path="" docBase="/data/webapps" reloadable="true" />
<Contest path="/shop" docBase="shopxx" reloadable="true" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs"
prefix="web1_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
这类组件通常包含于容器类组件中以提供具有管理功能的服务,它们不能包含其它组件,但有些却可以由不同层次的容器各自配置。
用来拦截请求并在将其转至目标之前进行某种处理操作,类似于servlet规范中定义的过滤器.value可以定义在任何容器类的组件中。value常被用来记录客户端请求,客户端IP地址和服务器等信息,这各处理技术通常被称作请求转储。请求转储value记录请求客户端请求数据包的http首部信息和cookie信息至文件中,响应转储value则记录响应数据包首部信息和cookie信息至文件中。
Valve类似于过滤器,它可以工作于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序。Tomcat6中实现了多种不同的Valve:
AccessLogValve:访问日志Valve
ExtendedAccessValve:扩展功能的访问日志Valve
JDBCAccessLogValve:通过JDBC将访问日志信息发送到数据库中;
RequestDumperValve:请求转储Valve;
RemoteAddrValve:基于远程地址的访问控制;
RemoteHostValve:基于远程主机名称的访问控制;
SemaphoreValve:用于控制Tomcat主机上任何容器上的并发访问数量;
JvmRouteBinderValve:在配置多个Tomcat为以Apache通过mod_proxy或mod_jk作为前端的集群架构中,当期望停止某节点时,可以通过此Valve将用记请求定向至备用节点;使用此Valve,必须使用JvmRouteSessionIDBinderListener;
ReplicationValve:专用于Tomcat集群架构中,可以在某个请求的session信息发生更改时触发session数据在各节点间进行复制;
SingleSignOn:将两个或多个需要对用户进行认证webapp在认证用户时连接在一起,即一次认证即可访问所有连接在一起的webapp;
ClusterSingleSingOn:对SingleSignOn的扩展,专用于Tomcat集群当中,需要结合ClusterSingleSignOnListener进行工作;
RemoteHostValve和RemoteAddrValve可以分别用来实现基于主机名称和基于IP地址的访问控制,控制本身可以通过allow或deny来进行定义,这有点类似于Apache的访问控制功能;如下面的Valve则实现了仅允许本机访问/probe:
<Context path="/probe" docBase="probe">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.0\.0\.1"/>
</Context>
其中相关属性定义有:
1) className:相关的java实现的类名,相应于分别应该为org.apache.catalina.valves.RemoteHostValve或org.apache.catalina.valves.RemoteAddrValve;
2) allow:以逗号分开的允许访问的IP地址列表,支持正则表达式,因此,点号“.”用于IP地址时需要转义;仅定义allow项时,非明确allow的地址均被deny;
3) deny: 以逗号分开的禁止访问的IP地址列表,支持正则表达式;使用方式同allow;
用于记录组件内部的状态信息,可被用于除context之外的任何容器中。日志记录的功能可被继承,因此,一个引擎级别的logger将会记录引擎内部所有组件相关的信息,除非某内部组件定义了自己的logger。
用于用户的认证和授权,在配置一个应用程序时,管理可以为每个资源或资源组定义角色及权限,而这些访问控制功能生效需要通过reaml来实现。realm的认证可以基于文本文件,数据库表、LDAP服务等来实现。realm的效用会遍及整个引擎或顶级容器,因此,一个容器内的所有应用程序将共享用户资源,同时,realm可以被其所在组件的子组件继承,也可以被子组件定义的realm所覆盖。
假如我们通过nginx向后端toucat进行反代,nginx的反代配置如下:
location / {
proxy_pass http://192.168.80.131:8080;
}
如上,在nginx上通过IP地址进行反代,这样做其实是有问题的。假如后端tomcat有多个虚拟主机,多个虚拟主机用的IP都是一样的,那么nginx的请求到底应该给哪一个虚拟主机呢?很有可能给的主机并不是我们想要的那一台,这种情况怎么办呢?很简单,我们只要告诉nginx不要通过IP地址代理,而是通过FQDN做代理,proxy_pass
是可以基于域名做代理的呀!注意本地要要加上域名解析,这样就行了,如下所示:
location / {
proxy_pass www.zhanghehe.com.cn:8080;
}
nginx通过域名访问后端tomcat时,在请求报文当中会加上www.zhanghehe.com.cn
,这样后端的tomcat就很容易知道nginx到底要访问哪台虚拟主机。
我们在nginx上做动静分离其实很简单,如下所示:
location / {
root /data/nginx/html;
index index.html index.htm;
}
location ~* .(jsp|do)$ {
proxy_pass http://192.168.80.131:8080;
}
所有的动态请求都转发到后端的tomcat,非动态nginx就自己响应了。
注意java的动态请求当中,不仅仅有jsp,还有do结尾的,所以要把do结尾的也要加上。
前端负载均衡可以用nginx,但后端的tomcat我们不可以让它单独工作,通常我们要给它加上apache,目的是为了tomcat,那为什么不用nginx,而用apache,因为tomcat和apche的亲和度非常好,tomcat就是apache项目里面的呀! nginx和tomcat交互只能通过http协议,而apche和tomcat可以通过ajp协议,ajp协议是tomcat专门用来对接apache而研制的二进制通信协议,速度非常快,所以架构就变成这个样子了:
哪怕apche不处理任何动静请求,仅仅是保护tomcat,也是有存在的必要的。我们可以让tomcat和apache在同一台主机当中,apache什么也不处理,仅仅做为一个代理。
httpd -M
less /etc/httpd/conf.modules.d/00-proxy.conf
//定义一个虚拟主机,用http
<VirtualHost *:80>
ServerName web1.zhanghe.com
ProxyVia On #打开代理功能
ProxyRequests Off #关闭正向代理,因为我们要用的反向代理功能
ProxyPreserveHost On #携带主机名,专门有这个选项
<Proxy *>
Require all granted #代理所有的url
</Proxy>
proxypass /status ! #不要把状态也代理后而了,排除
ProxyPass / http://192.168.80.131:8080/ #给谁
proxyPassReverse / http://192.168.80.131:8080/
<Location />
Require all granted #给所有人代理
</Location>
</VirtualHost>
//定义一个虚拟主机,用ajp协议
<VirtualHost *:80>
ServerName web1.zhanghe.com
ProxyVia On #打开代理功能
ProxyRequests Off #关闭正向代理,因为我们要用的反向代理功能
ProxyPreserveHost On #携带主机名,专门有这个选项
<Proxy *>
Require all granted #代理所有的url
</Proxy>
proxypass /status ! #不要把状态也代理后而了,排除
ProxyPass / ajp://192.168.80.131:8080/ #给谁
proxyPassReverse / ajp://192.168.80.131:8080/
<Location />
Require all granted #给所有人代理
</Location>
</VirtualHost>
原文:https://www.cnblogs.com/yizhangheka/p/12461009.html