Tomcat
Apache Tomcat 简介
Apache Tomcat 是一个免费的、开源的 Web 应用服务器,实现了 Java Servlet 和 JavaServer Pages (JSP) 技术规范。它被广泛用于部署和运行 Java Web 应用程序。Tomcat 是 Apache 软件基金会的一个顶级项目,以其轻量级、易于使用和灵活的特点而受到开发者的喜爱。
主要功能
- Servlet 容器:Tomcat 提供了一个 Servlet 容器,用于运行 Java Servlet,这是 Java Web 应用程序的核心组件。
- JSP 引擎:支持 JavaServer Pages (JSP),允许开发者在 HTML 页面中嵌入 Java 代码,从而实现动态 Web 内容。
- Web 应用部署:Tomcat 支持热部署,允许在不重启服务器的情况下更新 Web 应用程序。
- 安全性和管理:提供了多种安全机制,包括用户认证和授权,以及一个用于管理和监控的服务器管理界面。
版本历史
- Tomcat 3.0:1999年发布,实现了 Servlet 2.2 和 JSP 1.1 规范。
- Tomcat 4.x:引入了 Catalina(Servlet 容器)和 Jasper(JSP 引擎)等核心组件。
- 当前版本:Tomcat 9.0.x,但商业企业中主流版本为 8.x 和 7.x。
官方资源
- 官方网站 :Apache Tomcat
- 官方文档和帮助 :Apache Tomcat Wiki
- 常见问题解答 :Tomcat FAQ
安装 Tomcat
推荐从Apache官网下载源码包直接安装启动
1.安装java环境
bash
#安装java环境
[root@tomcat ~]# yum install java-1.8.0-openjdk.x86_64 -y
#查看java版本
[root@tomcatA ~]# java -version
openjdk version "1.8.0_402"
OpenJDK Runtime Environment (build 1.8.0_402-b06)
OpenJDK 64-Bit Server VM (build 25.402-b06, mixed mode)
#查看java的环境目录
[root@tomcatA ~]# which java
/usr/bin/java
[root@tomcatA ~]# ll /usr/bin/java
lrwxrwxrwx 1 root root 22 Jul 30 10:41 /usr/bin/java -> /etc/alternatives/java
#java的运行环境
[root@tomcatA ~]# cd /etc/alternatives/jre
[root@tomcatA jre]# ls
ASSEMBLY_EXCEPTION bin lib LICENSE THIRD_PARTY_README
2.安装并启动tomcat
bash
#解压并生成tomcat的程序目录
[root@tomcatA ~]# tar zxf apache-tomcat-9.0.107.tar.gz -C /usr/local/
[root@tomcatA ~]# cd /usr/local/
[root@tomcatA local]# ls
apache-tomcat-9.0.107 bin etc games include lib lib64 libexec sbin share
src
[root@tomcatA local]# mv apache-tomcat-9.0.107/ tomcat
[root@tomcatA local]# ls
bin etc games include lib lib64 libexec sbin share src tomcat
#启动tomcat
[root@tomcatA local]# cd tomcat/
[root@tomcatA tomcat]# cd bin/
[root@tomcatA bin]# ls
bootstrap.jar commons-daemon-native.tar.gz makebase.sh tomcatjuli.jar
catalina.bat configtest.bat setclasspath.bat tomcatnative.tar.gz
catalina.sh configtest.sh setclasspath.sh toolwrapper.bat
catalina-tasks.xml daemon.sh shutdown.bat toolwrapper.sh
ciphers.bat digest.bat shutdown.sh version.bat
ciphers.sh digest.sh startup.bat version.sh
commons-daemon.jar makebase.bat startup.sh
[root@tomcatA bin]# ./startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH:
/usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
3.查看端口
bash
[root@tomcat ~]# netstat -antlupe | grep java
tcp6 0 0 :::8080 :::* LISTEN 0 68636 32887/java
4.访问tomcat

tomcat的文件结构和组成
目录结构
目录 说明
bin 服务启动、停止等相关程序和文件
conf 配置文件
lib 库目录
logs 日志目录
webapps 应用程序,应用部署目录,相当于nginx的默认发布目录
work jsp 编译后的结果文件,建议提前预热访问
查看tomcat相关目录和文件
bash
[root@tomcat ~]# ls /usr/local/tomcat/
bin conf lib logs README.md RUNNING.txt webapps
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE RELEASE-NOTES temp work
生成tomcat的启动文件
1.生成tomcat的主配置文件
bash
[root@tomcat ~]# vim /usr/local/tomcat/conf/tomcat.conf
JAVA_HOME=/etc/alternatives/jre
2.生成启动文件
bash
[root@tomcat ~]# vim /lib/systemd/system/tomcat.service
[Unit]
Description=Tomcat
#After=syslog.target network.target remote-fs.target nss-lookup.target
After=syslog.target network.target
[Service]
Type=forking
EnvironmentFile=/usr/local/tomcat/conf/tomcat.conf
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/usr/local/tomcat/bin/shutdown.sh
PrivateTmp=true
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target
3.生成tomcat用户并设定软件安装目录权限
bash
[root@tomcatB bin]# useradd -s /sbin/nologin -M tomcat
[root@tomcatB bin]# chown tomcat.tomcat /usr/local/tomcat/ -R
4.用启动脚本开启服务
bash
[root@tomcatB ~]# systemctl enable --now tomcat
结合反向代理实现tomcat部署
常见部署方式介绍
-
Standalone 模式:Tomcat 单独运行,直接接受用户的请求。这种方式简单但不太推荐,因为Tomcat处理静态内容的能力不如专业的Web服务器,如Nginx或Apache。
-
单机反向代理:在这种模式下,使用一个反向代理服务器(如Nginx或Apache)来处理静态内容,并将动态内容(如JSP页面)的请求代理给Tomcat。这种方式的优点是能够更好地处理静态内容,提高整体性能。
- LNMT: Linux + Nginx + MySQL + Tomcat
- LAMT: Linux + Apache (Httpd) + MySQL + Tomcat
-
反向代理多机:这种模式下,一个Nginx实例作为前置代理服务器,后端连接多台Tomcat服务器。Nginx负责反向代理和负载均衡,将请求分发到不同的Tomcat实例上。这种方式适用于高并发场景,可以显著提高系统的扩展性和可靠性。
-
反向代理多级:在这种配置中,第一级Nginx作为前端代理服务器,后端连接多个二级Nginx服务器,每个二级Nginx服务器再连接到Tomcat实例。这种方式适用于非常大规模的系统,可以提供更高的性能和可靠性。
- LNNMT: Linux + Nginx + Nginx + MySQL + Tomcat

利用 nginx 反向代理实现

利用nginx反向代理功能,实现图中的代理功能,将用户请求全部转发至指定的同一个tomcat主机
利用nginx指令proxy_pass 可以向后端服务器转发请求报文,并且在转发时会保留客户端的请求报文中的 host首部
bash
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
location ~ \.jsp$ {
proxy_pass http://172.25.254.10:8080;
}
测试:
在浏览器中访问信息:lee.timinglee.org/test.jsp
实现tomcat中的负载均衡
负载均衡是一种技术,用于在多个服务器之间分配流量和工作负载。这种技术可以提高Web应用程序的可用性和可靠性,特别是在面对高并发请求时。通过负载均衡,可以确保没有一个单独的服务器过载,从而提高整体性能。
HTTP的无状态特性
HTTP是一种无状态的协议,这意味着服务器在处理每个请求时不会记住之前的状态。每个请求都是独立的,服务器不会自动关联来自同一用户的连续请求。这种设计简化了服务器的设计,但带来了状态管理的挑战。
Session和Cookie机制
为了解决HTTP的无状态问题,Web应用程序通常使用Session和Cookie机制。当用户第一次访问网站时,服务器会生成一个Session,并将其Session ID通过Cookie发送给用户的浏览器。浏览器在随后的请求中会将这个Session ID发送回服务器,这样服务器就能识别出连续的请求来自同一用户。
负载均衡和Session问题
在多服务器环境中,负载均衡器可能会将同一用户的请求分发到不同的服务器上。如果Session存储在单个服务器的内存中,那么当用户被路由到另一台服务器时,就可能出现找不到Session ID的情况。这个问题通常通过以下方法解决:
-
Session持久化:将Session数据存储在中央数据存储中,如数据库或分布式缓存(如Redis),这样任何服务器都可以访问到Session数据。
-
Session复制:在所有服务器之间复制Session数据,确保每台服务器都有最新的Session信息。
-
一致性哈希:使用一致性哈希算法确保来自同一用户的请求总是被路由到同一台服务器。
HTTP连接的特性
-
有连接:HTTP基于TCP协议,TCP是一种面向连接的协议,这意味着在数据传输之前需要建立一个连接,并且在传输完成后需要断开连接。这个过程涉及到三次握手和四次挥手。
-
短连接:在HTTP/1.1之前,每个HTTP请求都会建立一个全新的连接,请求完成后立即断开。这种短连接模式对服务器造成了较大的压力。为了解决这个问题,HTTP/1.1引入了持久连接(Keep-Alive),允许在一个TCP连接上发送多个HTTP请求,从而减少了连接建立和断开的开销。
负载均衡器的选择
在实现负载均衡时,可以选择如HAProxy或Nginx等负载均衡器。这些工具可以有效地分发流量,但需要注意Session管理的问题,确保用户在负载均衡的环境下能够无缝地使用应用程序
tomcat负载均衡实现
bash
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
upstream tomcat {
#ip_bash;
#hash $cookie_JSESSIONID;
server 172.25.254.10:8080;
server 172.25.254.20:8080;
}
server {
listen 80;
server_name lee.timinglee.org;
root /webdataw/nginx/timinglee.org/lee;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
try_files $uri $uri.html $uri/index.html /error/default.html;
location ~ \.jsp$ {
proxy_pass http://tomcat;
}
}
测试:
当使用ip_bash的算法时有什么问题? 不同浏览器里测试http://lee.timinglee.org/test.jsp
Memcached
Memcached简介
Memcached 是一个高性能、分布式内存对象缓存系统,主要用于减少数据库负载和加速动态Web应用。它通过在内存中缓存数据来减少对数据库的访问,从而提高应用的响应速度。
主要特性
-
Key-Value存储:Memcached 使用 Key-Value 的形式存储数据,其中 Key 是一个字符串,Value 是存储的数据。
-
不支持持久化:Memcached 不支持数据的持久化存储,所有的数据都存储在内存中。如果服务器重启或故障,存储在内存中的数据将会丢失。
-
集群同步:虽然 Memcached 不支持持久化,但可以通过集群同步的方式,让各 Memcached 服务器的数据进行同步,从而实现数据的一致性。即使有任何一台 Memcached 发生故障,只要集群中有一台 Memcached 可用就不会出现数据丢失。
-
高效读写:Memcached 借助操作系统的 libevent 工具做高效的读写。libevent 是一个程序库,它将 Linux 的 epoll、BSD 类操作系统的 kqueue 等事件处理功能封装成统一的接口,即使在连接数增加的情况下也能保持高性能。
-
最大存储对象大小:Memcached 支持的最大内存存储对象为 1MB。如果需要存储超过 1MB 的数据,可以使用客户端压缩或拆分报包放到多个 Key 中。
-
适合保存用户 Session:Memcached 最适合保存用户的 Session,实现 Session 共享。
-
内存管理:Memcached 存储数据时,会去申请 1MB 的内存,该块内存称为一个 Slab,也称为一个 Page。
-
多语言支持:Memcached 支持多种开发语言,包括 Java、C、Python、PHP、C#、Ruby、Perl 等。
Memcached 官网
更多信息可以访问 Memcached 官网: memcached - a distributed memory object caching system
总的来说,Memcached 是一个高性能的内存缓存系统,适用于需要快速读取数据的应用场景。通过减少数据库的负载,它可以显著提高应用的响应速度。
memcached的安装与启动
bash
[root@tomcat ~]# yum install memcached -y
[root@tomcat ~]# vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 0.0.0.0,::1"
[root@tomcat ~]# systemctl enable --now memcached
[root@tomcat ~]# netstat -antlupe | grep memcache
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 980 97815 34711/memcached
memcached 操作命令
五种基本 memcached 命令执行最简单的操作。这些命令和操作包括
set add replace get delete
bash
#前三个命令是用于操作存储在 memcached 中的键值对的标准修改命令,都使用如下所示的语法:
command <key> <flags> <expiration time> <bytes>
<value>
#参数说明如下:
command set/add/replace
key key 用于查找缓存值
flags 可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息
expiration time 在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
bytes 在缓存中存储的字节数
value 存储的值(始终位于第二行)
#增加key,过期时间为秒,bytes为存储数据的字节数
add key flags exptime bytes
示例:
bash
[root@tomcat ~]# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
#增加
add leekey 0 60 4 #0 是否压缩 60 过期时间 4 字长
test
STORED
add leekey1 0 60 3
lee
STORED
#查看
get leekey
VALUE leekey 0 4
test
get leekey1
VALUE leekey1 0 3
lee
#改
set leekey 0 60 5
test1
STORED
get leekey
VALUE leekey 0 5
test1
END
add leekey1 0 60 4
test
#删除
delete leekey
DELETED
get leekey
END
get leekey1
VALUE leekey1 0 3
lee
#清空
flush_all
OK
get leekey1
END
session 共享服务器
Memcached Session Manager (MSM)
Memcached Session Manager (MSM) 是一个用于 Tomcat 的库,它允许将用户的会话数据存储在 Memcached 中。这样做的好处是提高了会话数据的高可用性,因为 Memcached 是一个分布式缓存系统,可以在多个服务器之间共享会话数据。
MSM 的特点
-
高可用性:通过将 Session 数据存储在 Memcached 中,即使某个 Tomcat 实例发生故障,用户的会话数据也不会丢失。
-
支持多种 Tomcat 版本:MSM 支持 Tomcat 的 6.x、7.x、8.x 和 9.x 版本。
-
Session 数据的序列化和反序列化:MSM 使用序列化和反序列化类来处理 Session 数据。官方推荐使用 kyro 作为序列化库。
-
驱动类:MSM 支持 Memcached(使用 spymemcached.jar)和 Redis(使用 jedis.jar)作为驱动。
MSM 的使用
-
在 Tomcat 中添加 MSM 相关的 JAR 文件:包括 msm-core、msm-kryo-serializer、spymemcached 和 jedis 等。
-
配置 Tomcat:在 Tomcat 的 context.xml 或 server.xml 文件中添加相应的配置,以便使用 MSM。
-
在应用程序中添加序列化库:在 WEB-INF/lib/ 目录下添加 kyro 的 JAR 文件。
GitHub 项目链接
MSM 的项目早期托管在 Google Code,目前在 GitHub 上维护。您可以通过以下链接访问 MSM 的 GitHub 页面:https://github.com/magro/memcached-session-manager
总的来说,使用 Memcached Session Manager (MSM) 可以提高 Tomcat 应用程序的高可用性,特别是在需要多台服务器协同工作的场景下。通过将 Session 数据存储在 Memcached 中,可以确保用户的会话数据在服务器故障时仍然可用。
安装
参考链接: https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
将spymemcached.jar、memcached-session-manage、kyro相关的jar文件都放到Tomcat的lib目录 中,这个目录是 $CATALINA_HOME/lib/ ,对应本次安装就是/usr/local/tomcat/lib。
kryo-3.0.3.jar
asm-5.2.jar
objenesis-2.6.jar
reflectasm-1.11.9.jar
minlog-1.3.1.jar
kryo-serializers-0.45.jar
msm-kryo-serializer-2.3.2.jar
memcached-session-manager-tc9-2.3.2.jar
spymemcached-2.12.3.jar
memcached-session-manager-2.3.2.jar
t1和m1部署可以在一台主机上,t2和m2部署也可以在同一台。
当新用户发请求到Tomcat1时, Tomcat1生成session返回给用户的同时,也会同时发给memcached2备 份。即Tomcat1 session为主session,memcached2 session为备用session,使用memcached相当于 备份了一份Session
如果Tomcat1发现memcached2 失败,无法备份Session到memcached2,则将Sessoin备份存放在 memcached1中
配置过程
下载相关jar包,参考下面官方说明的下载链接
https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
修改tomcat配置
bash
[root@tomcat-1 ~]# vim /usr/local/tomcat/conf/context.xml
@@@@内容省略@@@@
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.254.10:11211,n2:172.25.254.20:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFacto
ry"
/>
[root@tomcat-2 tomcat]# vim /usr/local/tomcat/conf/context.xml
@@@@内容省略@@@@
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.254.10:11211,n2:172.25.254.20:11211"
failoverNodes="n2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFacto
ry"
/>
修改nginx配置
bash
[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.conf
upstream tomcat {
hash $cookie_JSESSIONID;
server 172.25.254.10:8080;
server 172.25.254.20:8080;
}
server {
listen 80;
server_name lee.timinglee.org;
root /webdataw/nginx/timinglee.org/lee;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
try_files $uri $uri.html $uri/index.html /error/default.html;
location ~ \.jsp$ {
proxy_pass http://tomcat;
}
}
测试:
1.在两台tomcat都开启的情况下: http://lee.timinglee.org/test.jsp
2.在n1被停止后继续提交信息看是否可以读取到之前的会话信息