https://blog.51cto.com/13570193/2165362
第一步:安装JDK。
tomcat在处理客户端请求的jsp文件的时候,会将jsp文件中的java程序提取出来并且运行,java程序能够运行是需要JDK的支持的。
目前jdk存在两个分支,一个是Oracle公司负责维护的jdk,一个是开源界维护的openjdk,并且openjdk软件在CentOS的光盘中会提供。
方法一:使用Oracle的分支,进入Oracle官网下载jdk10版本,网址是https://www.oracle.com/technetwork/java/javase/downloads/jdk10-downloads-4416644.html
会看到Linux相对应的两个文件,一个.rpm文件,一个.tar.gz文件(绿色版),.rpm文件就是普通rpm软件包的正常安装方式即可,.tar.gz文件下载下来之后直接解压至指定目录就可以使用。
然后安装,安装之后的文件目录会存放在/usr/java目录下。
[root@Web1 src]# pwd
/usr/local/src
[root@Web1 src]# ls jdk-10.0.2_linux-x64_bin.rpm
jdk-10.0.2_linux-x64_bin.rpm
[root@Web1 src]# yum -y localinstall jdk-10.0.2_linux-x64_bin.rpm
[root@Web1 src]# cd /usr/java/
[root@Web1 java]# ls
default jdk-10.0.2 latest
可以看到生成了三个目录,在jdk-10.0.2目录下的bin目录下存在一个java命令。需要将bin目录下的命令配置到系统的PATH变量中。配置如下:
[root@Web1 ~]# vim /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/jdk-10.0.2
export PATH=$JAVA_HOME/bin:$PATH
# 重载环境变量
[root@Web1 ~]# source /etc/profile.d/java.sh
[root@Web1 ~]# which java
/usr/java/jdk-10.0.2/bin/java
到此为止,JDK的安装和PATH变量的配置已经完成,可以使用java -version命令查看安装的JDK版本。
方法二:使用openjdk分支,openjdk在CentOS的本地光盘中就会提供,因此使用yum直接安装即可。
[root@Web2 ~ ]# yum list all *openjdk*
执行上面的命令之后,会看到很多openjdk版本和各个版本的各个组件,假如使用java-1.8.0-openjdk这个版本,另外还需要关注相对应版本的java-1.8.0-openjdk-devel这个组件。他们的关系如下:
java-1.8.0-openjdk java程序的运行环境
java-1.8.0-openjdk-devel java程序的编译开发环境
仅安装openjdk之后,只存在一个jre下的java命令,但是继续安装openjdk-devel之后,就会多出一个javac命令。
安装这两个组件,
[root@Web2 ~]# yum -y install java-1.8.0-openjdk.x86_64 java-1.8.0-openjdk-devel.x86_64
安装后我们不知道bin目录在什么位置,这样就无法配置系统的PATH变量。可以使用命令rpm来查看软件包安装后每个文件的位置:
[root@Web2 ~]# rpm -ql java-1.8.0-openjdk-devel |grep /bin$
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/bin
配置PATH变量
[root@Web2 ~]# vim /etc/profile.d/java.sh
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64
export PATH=$JAVA_HOME/bin:$PATH
[root@Web2 ~]# source /etc/profile.d/java.sh
[root@Web2 ~]# which java
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/bin/java
第二步:安装tomcat
方法一:tomcat在CentOS的本地光盘中就会提供,因此直接yum仓库安装即可。
[root@Web2 ~]# yum -y install tomcat tomcat-admin-webapps tomcat-webapps
其中tomcat-admin-webapps是一个tomca应用程序t的管理组件,tomcat-webapps是一个提供tomcat的默认欢迎首页文件的组件。
tomcat安装完成之后,会提供一个管理命令/usr/sbin/tomcat,而且还会提供相应的tomcat服务(CentOS6--/etc/init.d/tomcat start、CentOS7--systemctl start tomcat)。
启动tomcat
[root@Web2 ~]# /usr/sbin/tomcat start
tomcat默认工作在非特权用户下,因此tomcat就无法监听80端口,因此tomcat默认监听8080端口。
测试
浏览器中输入ip:8080,出现下图界面表示tomcat启动成功。
方法二:在tomcat的官网下载安装。网址为:https://tomcat.apache.org/
下载成功后如下,然后解压至/usr/local目录下就可以使用。
[root@Web1 src]# pwd
/usr/local/src
[root@Web1 src]# ls apache-tomcat-8.5.32.tar.gz
apache-tomcat-8.5.32.tar.gz
[root@Web1 src]# tar -zxvf apache-tomcat-8.5.32.tar.gz -C /usr/local/
[root@Web1 local]# ls -d /usr/local/apache-tomcat-8.5.32/
/usr/local/apache-tomcat-8.5.32/
这样/usr/local目录下的apache-tomcat-8.5.32太长,因此使用软链接的方式,
[root@Web1 local]# pwd
/usr/local
[root@Web1 local]# ln -sv apache-tomcat-8.5.32/ tomcat8
解压后的bin目录下提供了一套tomcat的管理脚本,例如启动tomcat的startup.sh,关闭tomcat的shutdown.sh,查看tomcat版本信息的version.sh等等。
tomcat的主配置文件server.xml文件的整体结构如下,而且文件结构也符合tomcat的架构层次。
...
...
tomcat是java语言开发的,因此配置文件也相符合于面向对象的思想,例如,文件中的每个元素创建“对象”,并为属性赋值实例化对象。
该配置文件中的元素都是大写字母开头。
Server
配置文件中的顶层元素,代表一个tomcat实例,并且配置文件中仅能有一个Server。
属性 | 备注 | 属性值 |
---|---|---|
classname | 实现server的类名 | |
port | 接受关闭tomcat请求的端口,仅能绑定至127.0.0.1 | 8005 |
shutdown | 定义关闭tomcat的字符串指令 | SHUTDOWN |
Listener
表示一个事件的监听器
属性 | 备注 | 属性值 |
---|---|---|
clsssname | 实现该监听器的类名 | |
SSLEngine | 是否使用SSL | on或者off |
GlobalNamingResources
全局JNDI资源,该元素没有任何属性,所有的应用程序都可以引用全局JNDI资源。那什么是JNDI资源呢?JNDI多用于java的数据库连接中,到这里我们首先要想到的是JDBC,在JDBC中,连接数据库需要用户名、用户名密码和数据库名称等参数,将来如果这三个参数中的任何一个修改,则整个程序中相关的地方都需要修改,简直是牵一发而动全身,因此出现JNDI技术,在JNDI中,将连接数据库需要的用户、用户密码和数据库名称等JDBC引用的参数定义为一个整体(即这个整体中包含JDBC要用到类库、数据库驱动程序、用户、用户密码等),然后为这个整体设置一个名称,这样以后连接数据库的时候直接在程序中引用这个整体的名称即可,无论用户、用户密码怎么变换,只要这个整体的名称不变,我们仅要修改这个整体的用户和用户密码,而无需修改整个程序。这里的这个整体就是JNDI数据源(JNDI资源)。
虽然GlobalNamingResources没有定义任何的属性,但是可以在
Resource
定义JNDI数据源
属性 | 备注 | 默认值 |
---|---|---|
name | 定义的JNDI资源的名称 | |
auth | 指定管理Resource的管理器 | 有Container和Application两种 |
type | 使用的类名 | |
description | 描述信息 | --- |
示例:
示例表示定义了一个名为UserDataBase的全局JNDI数据源,使用容器管理该Resource,该数据源为加载tomcat-users.xml文件至内存中而定义的用于用户授权的数据库。然后在认证文件tomcat-users.xml中添加如下几行。表示用户名为admin,用户密码为centos的认证用户分别以manager-gui和admin-gui的角色登录manager和host-manager的应用程序。
Service
包含一个或多个Connector和一个Engine的服务组件。属性name表示该Service的名称,默认保持 Catalina即可。
Connector
代表一个接受客户端请求的连接器。
属性 | 备注 | 属性值 |
---|---|---|
accepCount | 等待队列的长度 | 10 |
port | 连接器监听的端口 | |
protocol | 连接器应用的协议类型 | http/https/ajp |
connectionTimeout | 连接的超时时间,单位为毫秒 | 20000 |
address | 连接器监听的IP地址 | 默认为所有地址,0.0.0.0 |
maxThreads | 最大并发连接数 | http连接器默认200,https连接器默认150 |
enableLookups | 是否开启DNS反解 | true或false |
clientAuth | tomcat是否需要认证客户端 | 默认false |
redirectPort | 重定向至指定端口的Connector | 8443 |
scheme | 如果为SSL连接器,则为https | http/https |
secure | SSL连接器则为true | true或false |
SSLEnabled | 是否开启SSL | true或false |
sslProtocol | TLS |
其中ajp协议应用在Apache在反向代理tomcat的场景,Apache和tomcat之间就是使用ajp协议通信,它是一种二进制协议。
Engine
代表一个servlet实例,用于处理Connector接受并传递过来的请求。
属性 | 备注 | 属性值 |
---|---|---|
name | 定义Engine的名称 | Catalina |
defaultHost | 定义Engine的默认虚拟主机 | 默认为localhost |
jvmRoute | 应用于tomcat集群中的session共享,会在一次会话中添加该值,获得session sticky | --- |
Host
嵌套在
属性 | 备注 | 属性值 |
---|---|---|
name | 虚拟主机名 | |
appBase | 虚拟主机的站点根目录 | webapps |
unpackWARs | tomcat是否解开WAR归档文件,默认为true,自动解开 | true或false |
autoDeploy | 是否自动部署追加到根目录下的新应用程序,默认为true | true或false |
示例:
在Engine中新嵌套一个Host,也就是新增加一个虚拟主机,配置内容如下
创建appBase目录,并且tomcat虚拟主机中的每个应用程序都是单独放在一个目录内,因此创建ROOT目录,
[root@Web1 ~]# mkdir -p /data/webapps/ROOT
放入jsp测试页面
[root@Web1 ~]# vim /data/webapps/ROOT/index.jsp
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
My JSP 'first.jsp' starting page
九九乘法表
<%
for(int i=1;i<=9;i++) {
for(int j=1;j<=i;j++) {
out.println(i+"*"+j+"="+(i*j)+" ");
}
out.println("
");
}
%>
然后hosts文件中添加Web1.linux.com记录,浏览器中访问。
Realm
访问应用程序的时候需要安全认证,即需要输入用户和用户密码,Realm就是指定存储验证信息(用户和用户密码)的数据源。
表示通过UserDatabaseRealm的方式获取验证信息,并且该数据源为GlobalNamingResources元素定义的全局JNDI资源UserDatebase。Realm元素嵌套的位置代表验证的范围,例如嵌套在Engine中,则Engine中所有的Host虚拟主机都共用这个认证信息。嵌套在Host中,则Host中所有的应用程序都共用这个认证信息。嵌套在Context中,则该应用程序使用这个认证信息。
Valve
可以嵌套在Engine、Host、Context元素中的组件,不同的类型可以实现特定的功能,例如AccessLogValve可以实现生成访问日志的功能,RemoteAddrValve可以实现控制远程IP地址的访问。
示例:
继续访问Web1.linux.com,结果没有返回页面内容,并且在logs目录下生成了访问日志。
Context
嵌套在Host中的元素,代表某个虚拟主机中的应用程序。常用属性如下
属性 | 备注 |
---|---|
docBase | 对应的web应用程序的目录 |
path | 指定该应用程序映射为服务器根目录的URI路径,即host+path |
reloadable | 是否重新加载web应用程序类,默认为false |
注:tomcat虚拟主机中的每个应用程序必须单独存在一个目录中,docBase可以使用相对路径和绝对路径,相对路径是相对于Host虚拟主机的appBase目录。
如果path属性值为空字符串,则表示该应用程序为根web应用,即ROOT目录。
示例:
然后创建web应用程序的jsp代码,URL地址列中输入http://web1.linux.com:8080/test ,查看访问结果。
[root@Web1 ~]# mkdir -p /data/webapps/test
[root@Web1 test]# vim index.jsp
JSP test
<%
out.println("Hello World!!
");
%>
tomcat能够处理用户的web请求(包括动态资源和静态资源),但是tomcat在处理静态资源的时候性能并不是很好,更多的时候是让tomcat只处理动态资源请求,因此使用tomcat大多是使用如下的架构:
在tomcat的前端加一个Nginx反向代理,Nginx接受用户发来的Web请求,当请求的是静态资源的时候,Nginx自己处理,当请求的动态资源的时候,则Nginx将请求代理到后面的tomcat实例。这样来实现tomcat的性能最大化。
Nginx的反向代理配置如下:
当用户请求的是除了jsp|do以外的静态资源的时候,则Nginx自己到/data/webapps/html目录下响应请求,但用户请求的是jsp|do的动态资源的时候,则Nginx将请求代理到后边的tomcat。因此来实现动静分离。
[root@Web1 ~]# vim /etc/nginx/conf.d/proxy.conf
server {
listen 80;
server_name Web1.linux.com;
index index.jsp;
location / {
root /data/webapps/html;
expires 30d;
}
location ~* \.(jsp|do)$ {
proxy_pass http://localhost:8080;
}
}
tomcat的sever.xml的主要配置如下:
然后在/data/webapps/html目录下编辑一个测试静态资源,在/data/webapps/test目录下编辑一个测试jsp动态代码。
[root@Web1 ~]# cat /data/webapps/html/index.html
This is static resource!
[root@Web1 ~]# cat /data/webapps/test/index.jsp
<%@ page language="java" %>
JSP test
<%
out.println("This is dynamic resource!
");
%>
测试:
在浏览器中输入Nginx的IP地址。
通过前端负载均衡器调度到后端不同Tomcat服务器的时候,会出现session不一致的问题。为了解决这个问题,目前实现会话保持的方式主要一下三种:
① stickysession,会话绑定,通过前端调度器特定的算法,将同一个客户端总是调度到后端同一台服务器,例如Nginx做负载均衡的ip_hash算法。
② session replication,会话复制,这个操作在服务器自身上边进行,服务器之间通过复制会话来实现会话同步,例如Tomcat自带的会话集群功能Cluster。
③ session server,会话服务器,通过将session存储在特定的主机之上,服务器通过统一地访问session主机实现会话同步,例如redis、memcached就是这种会话服务器。
环境拓扑:
主机 | IP地址 | 功能 |
---|---|---|
Master.linux.com | 192.168.239.137 | 负载均衡调度器 |
Web1.linux.com | 192.168.239.129 | Nginx+tomcat1主机兼memcached1主机 |
Web2.linux.com | 192.168.239.140 | Nginx+tomcat2主机兼memcached2主机 |
注:Nginx+tomcat主机实现的tomcat的动静分离。
第一步:安装memcache
CentOS本地光盘中提供
[root@Web1 ~]# yum -y install memcached
[root@Web2 ~]# yum -y install memcached
然后开启memcached服务,查看memcached的端口监听状态,
第二步:安装tomcat的第三方类库memcached-session-manager(简称msm)。
该项目在GitHub上。地址为:https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
需要下载 memcached-session-manager-${version}.jar,memcached-session-manager-tc8-${version}.jar(具体的tc版本要和tomcat版本相同,catalina.sh脚本的 version选项可以查看tomcat的版本信息) 和 spymemcached-${version}.jar。
使用msm还依赖serializer序列化工具,msm提供了四种序列化工具,选择其中一种即可。
这四种连接memcached的序列化工具,分别为kryo-serializer,javolution-serializer,xstream-serializer,flexjson-serializer。
这里以javolution-serializer为例,其下的两个小组件的下载地址如下:
http://www.java2s.com/Code/JarDownload/javolution/javolution-5.5.1.jar.zip
该文件需要解压成jar文件。
http://repo1.maven.org/maven2/de/javakaffee/msm/msm-javolution-serializer/2.1.1/msm-javolution-serializer-2.1.1.jar
所有的jar文件(这里是5个)下载完成之后,将这些jar文件复制到$CATALINA_BASE/lib目录下,该目录下存放着tomcat调用的类库文件(jar文件),我这里的CATALINA_BASE为/usr/local/tomcat8,即安装目录。
第三步:配置Context
在两个tomcat主机的server.xml指定的应用程序下边(即Context),添加Manager元素。具体信息如下:
memcachedNodes属性指定每个memcache的节点信息,格式为<节点标志符:hostname:port>;
failoverNodes属性指定哪一个memcache节点为备用节点;
requestUriIgnorePattern属性指定无需将静态资源实现会话保持,因为会话本来就是针对动态资源的;
transcoderFactoryClass属性指定序列化工具。
第四步:实现前端的Nginx负载均衡
[root@Master ~]# vim /usr/local/nginx/conf/conf.d/balance.conf
upstream webserver {
# tomcat1
server 192.168.239.129:80 weight=1;
# tomcat2
server 192.168.239.140:80 weight=2;
}
server {
listen 80;
server_name web.linux.com;
root /data/html;
index index.php index.html index.htm;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forward-For $remote_addr;
proxy_pass http://webserver;
}
}
到此整个配置已经完成,重启tomcat重新加载新的server.xml文件。
添加测试代码文件index.jsp。
[root@Web1 ~]# vim /data/webapps/ROOT/index.jsp
<%@ page language="java" %>
Tomcat 1
Tomcat1.linux.com
Session ID
<% session.setAttribute("linux.com","linux..com"); %>
<%= session.getId() %>
Created on
<%= session.getCreationTime() %>
在浏览器中输入调度器的IP地址,一直刷新,可以看到调度到不同的tomcat,但是session却保持不变。另外也可以看到连接的是n2的memcache。后边的-n2表示session-id的后缀。
现在暂停n2的memcached服务,继续刷新,session保持不变,但是连接的memcache变成了备用节点n1。实现了memcache的高可用。