当前位置: 首页 > news >正文

企业级web应用服务器TOMCAT入门详解

一. web

1.1 为什么“网页里的应用”≈“Tomcat 里的应用”?

  1. 浏览器只认识 HTTP。
    你在地址栏敲 http://xxx.com/login,浏览器发出去的就是一段纯文本 HTTP 报文。

  2. Tomcat 天生吃 HTTP。
    它实现了 JavaEE 里的 Servlet 规范:把 HTTP 请求封装成 HttpServletRequest → 交给程序员写的 LoginServlet → 生成 HTML → 再按 HTTP 格式返回。
    于是“浏览器 ↔ HTTP ↔ Tomcat ↔ 你的业务代码”这一条路就打通了。

  3. 因此,只要最终是通过浏览器访问的,几乎都可以说“由 Tomcat(或同类 Web 服务器)实现”。


1.2 B/S 与 C/S 的“空间之争”

维度C/SB/S
客户端必须安装专门软件(QQ、Steam、银行 U 盾)只用浏览器
升级每台电脑都要重新装包改服务器就行
磁盘占用客户端几百 MB 起步0 MB(浏览器不算)
网络协议随意(TCP/UDP、自定义)只用 HTTP/HTTPS
代表场景游戏、实时交易论坛、OA、博客、后台管理

结论:
“节省磁盘空间”只是 B/S 最直观的优势,真正让它统治世界的是 零安装、零维护、跨平台


1.3、三大核心技术到底各干什么?

  1. HTML(骨架)
    纯文本的标签积木:<form><input><table>……告诉浏览器“这里有个登录框,那里放个按钮”。

  2. CSS(皮肤)
    同一段 HTML,可以换不同 CSS 立刻变成“极简风”或“赛博朋克”。
    例:

    css

    复制

    input[type=text] {border-radius: 8px;box-shadow: 0 0 10px #00f;
    }
  3. JavaScript(肌肉)
    让页面“动起来”:

    • 表单实时校验(失焦就提示“密码太短”)

    • Ajax 异步拉数据(下面细讲)

    • 动画、游戏、可视化……

浏览器拿到 .html → 边解析边向服务器要 .css.js渲染引擎把三者拼成你看到的像素。


1.4、同步交互:整页刷新之痛

经典场景:注册页面
流程:

  1. 填 8 个字段 → 点【提交】

  2. 浏览器整页 POST 给服务器

  3. 服务器发现“两次密码不一致”

  4. 返回一个全新 HTML 页面

  5. 浏览器重新渲染 → 前 7 个字段全清空
    这就是“同步”——一次 HTTP 请求对应一次完整页面刷新。

缺点:

  • 带宽浪费(CSS/JS/图片全部重传)

  • 体验差(用户想骂人)


1.5、异步交互:Ajax 的魔法

  1. 关键技术:XMLHttpRequest(浏览器内置 API)。
    浏览器悄悄再开一条 HTTP 连接,只拿回 需要的那一小块数据(JSON/HTML 片段),然后用 JS 把页面局部更新。
    用户无感刷新。

  2. 流程对比:

    • 同步:填表单 → 提交 → 等待 → 整页刷新

    • 异步:输完邮箱 → JS 立即发请求 /checkEmail?email=xxx → 返回 {"ok":false,"msg":"已注册"} → 页面只把提示字变红,其他不动

  3. 关键词:

    • Ajax(Asynchronous JavaScript And XML)

    • 现在多用 JSON 代替 XML

    • 衍生:Fetch API、Axios、jQuery.ajax()


1.6、从“代码”到“网页”的完整链路

  1. 你在 IDEA 写 LoginServlet.java,继承 HttpServlet,处理 POST /login

  2. mvn package 打成 war → 扔到 Tomcat 的 webapps

  3. 浏览器访问 http://域名/login.html

  4. Tomcat 把 login.html 吐给浏览器(HTML+CSS+JS)。

  5. 用户填完账号密码,JS 用 Ajax POST /login

  6. LoginServlet 查询数据库 → 返回 JSON {status:0,token:xxx}

  7. JS 把 token 存 localStorage,页面跳转到 /index.html,全程无整页刷新。

二 tomcat

#安装java环境
[root@tomcat ~]# yum install java-1.8.0-openjdk.x86_64 -y#查看java版本
[root@tomcatA ~]# java -versionopenjdk 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/javalrwxrwxrwx 1 root root 22 Jul 30 10:41 /usr/bin/java -> /etc/alternatives/java#java的运行环境
[root@tomcatA ~]# cd /etc/alternatives/jre[root@tomcatA jre]# lsASSEMBLY_EXCEPTION  bin  lib  LICENSE  THIRD_PARTY_README
#解压并生成tomcat的程序目录
[root@tomcatA ~]# tar zxf apache-tomcat-9.0.107.tar.gz -C /usr/local/[root@tomcatA ~]# cd /usr/local/[root@tomcatA local]# lsapache-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]# lsbootstrap.jar       
commons-daemon-native.tar.gz  makebase.sh       
juli.jarcatalina.bat        
native.tar.gzcatalina.sh         
configtest.bat                
configtest.sh                 
wrapper.batcatalina-tasks.xml  daemon.sh                     
wrapper.shciphers.bat         
ciphers.sh          
digest.bat                    
digest.sh                     
commons-daemon.jar  makebase.bat                  
tomcat
setclasspath.bat  tomcat
setclasspath.sh   
shutdown.bat      
shutdown.sh       
startup.bat       
startup.sh[root@tomcatA bin]# ./startup.shUsing CATALINA_BASE:   /usr/local/tomcatUsing CATALINA_HOME:   /usr/local/tomcatUsing CATALINA_TMPDIR: /usr/local/tomcat/tempUsing JRE_HOME:        
/usrtool
tool
version.batversion.shUsing CLASSPATH:       
/usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jarUsing CATALINA_OPTS:Tomcat started.

[root@tomcat ~]# netstat -antlupe | grep java      

安装JAVA环境

java版本查看

查看java真正的环境目录

jre真正的运行环境

要把java的运行环境指定给Tomcat

安装tomcat:

解压并重命名

进入目录并启动它

启动成功后查看端口

测试:

在另一台主机上也要做

简单一点就直接复制了


编写启动程序

创建专用系统用户

useradd -r -s /sbin/nologin -M tomcat

统一目录权限

chown -R tomcat:tomcat /usr/local/tomcat

写入环境变量(Tomcat 专用)


文件:/usr/local/tomcat/conf/tomcat.conf
内容只有一行:

JAVA_HOME=/etc/alternatives/jre


生成 systemd 单元文件


文件:/lib/systemd/system/tomcat.service

[Unit]
Description=Apache Tomcat
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

启动并设为开机自启

systemctl daemon-reload
systemctl enable --now tomcat   # 立即启动 + 开机自启
systemctl status tomcat         # 查看运行状态

一键验证

ss -lntp | grep java            # 应看到 8080 端口
curl -I http://localhost:8080   # 返回 200 OK

内容中制定用户了,所以这里要建立用户

要给tomcat指定java的运行环境

报错情况:

此时是没有运行这个文件的权限

查看权限

加权限

测试:

2.2 结合反向代理实现tomcat部署

  1. 浏览器里看到的“网页应用”≈ Nginx + Tomcat 这对黄金搭档在干活,而 Nginx 负责反向代理 / 负载均衡,Tomcat 负责跑 Java 代码
    为了不丢登录态,还要解决 Session 一致性 问题。


  1. 什么是“反向代理”?


  • 正反向区别一句话:

    • 正向代理:帮 客户端 去访问外网(翻墙)。

    • 反向代理:帮 服务端 接收外网请求(统一入口)。

  • 为什么要反向代理 Tomcat?

    1. 端口统一:浏览器只认 80/443,Tomcat 默认 8080。

    2. 动静分离:Nginx 处理静态文件(css/js/png)速度是 Tomcat 的 10 倍。

    3. 安全:Tomcat 不再直接暴露,可放在内网。

  • 指令拆解

    nginx

    复制

    location ~ \.jsp$ {proxy_pass http://172.25.254.10:8080;   # 把请求原封不动转给 Tomcatproxy_set_header Host $host;            # 保留浏览器里的域名,否则 Tomcat 重定向会出错
    }

    浏览器发的是 Host: lee.timinglee.org,Tomcat 也收到同样的 Host,就不会跳错地址。


  1. 为什么要“负载均衡”?


  • 单台 Tomcat 的并发瓶颈:
    纯 Java 业务,QPS 大约几百~一两千。用户量一上来就卡死。

  • 思路:把同样的应用复制到多台机器,把压力 分摊,术语叫 Load Balance

  • Nginx 的 3 种常用调度算法

    1. 轮询(默认)——每人一次,最公平。

    2. ip_hash ——同一 IP 固定到一台,解决 会话保持(后面细说坑)。

    3. hash $cookie_JSESSIONID ——按 SessionID 选机器,比 ip_hash 更精准。


  1. HTTP 的无状态 & Session 机制


  • 无状态:HTTP 协议本身不带“记忆”。
    第一次请求登录成功,第二次刷新页面,Tomcat 压根不知道你是刚才那个人。

  • 解决思路

    1. 服务器给浏览器发一张“身份证”—— SessionID(随机字符串)。

    2. 浏览器以后每次请求都在 Cookie 里带上 JSESSIONID=xxx

    3. Tomcat 收到后,从自己 内存 里找对应的 SessionMap,取出用户信息。

  • 生命周期

    • 默认 30 min 没交互就失效(web.xml 可调)。

    • 关闭浏览器 Cookie 消失,再开就重新领身份证。


  1. 负载均衡后出现的新问题:Session 丢失


场景:

  • 浏览器第一次请求被分到 Tomcat-A,SessionID=1001 存在 A 的内存。

  • 第二次请求被分到 Tomcat-B,B 内存里没 1001 → 强制跳回登录页。

这就是“找不到 SessionID”的根本原因:HTTP 无状态 + 多台机器内存不共享


  1. 三种 Session 一致性方案对比


表格

复制

方案原理优点缺点适用
1. ip_hashNginx 按客户端 IP 固定到同一台机器零改动NAT 场景下严重倾斜;单点故障需重新登录内部后台、用户量小
2. Tomcat Cluster多台 Tomcat 组播同步 Session官方原生组播受网络限制;同步风暴小规模内网
3. MSM+MemcachedSession 序列化后存 Memcached,多台 Tomcat 共享无状态、高可用、扩展好需额外部署 Memcached;首次配置稍复杂生产最强

  1. MSM+Memcached 工作流程(图+文字)


复制

浏览器││ 1. 登录请求 → Nginx → Tomcat-A│                     ││                     └─ 2. 创建 SessionID=1001│                          同时 3. 序列化 Session 到 Memcached││ 4. 第二次请求 → Nginx → Tomcat-B│                     ││                     └─ 5. Tomcat-B 发现 Cookie:JSESSIONID=10016. 去 Memcached 取 Session → 继续业务
  • 如果 Tomcat-A 挂了,Tomcat-B/C/D 任何一台都能从 Memcached 拿到同一份 Session,用户无感知。


  1. 配置小结(回顾)


  1. 反向代理(单机)

    nginx

    复制

    location ~ \.jsp$ {proxy_pass http://172.25.254.10:8080;proxy_set_header Host $host;
    }
  2. 负载均衡(多机)

    nginx

    复制

    upstream tomcat {hash $cookie_JSESSIONID;      # 会话保持最稳server 172.25.254.10:8080;server 172.25.254.20:8080;
    }
  3. MSM 共享 Session

    • 把相关 jar 扔进 $CATALINA_HOME/lib

    • context.xml 指定 Memcached 节点

    • 重启 Tomcat 即可生效单机

    • 现在需要一个测试页面

      测试页面不能直接在root里要放到默认发布目录里

      直接下载nginx

      在配置文件里写下子配置命令 include 

错误情况:

访问超时

直接访问没问题

域名解析有误,之前实验的影响

测试:

之前的信息也会保留

这个代码,nginx不能写,是tomcat来写的

tomcat挂了,这个实验就不能用了


单机情况下,tomcat挂了,就不能用了

要解决这个问题,用多机来做

多机

测试:

会话绑定

缺点:如果同一个路由器过来的路由都会跑向一个路由器上了

cookie客户端生成的会话   session服务器生成的会话

会话:以用户的身份与服务器对话

此时的情况时,来一个服务器就重新对话

所以解决办法是生成sessionIP要与cookieIP一致,cookie值变了,就访问不同服务器

写cookie哈希

对键值进行哈希

测试:

ID是一样的就会访问同一个服务器上

只有挂了浏览器才会改变,此时ID也变了

前端还在做数据存储,但是后端的tomcat却挂了,前端是不知道的,该怎么办?

无论是10还是20,之前的数据该怎么保存?

三、Memcached

Memcached 只支持能序列化的数据类型,不支持持久化,基于Key-Value的内存缓存系统memcached 虽然没有像redis所具备的数据持久化功能,比如RDB和AOF都没有,但是可以通过做集群同步的方式, 让各memcached服务器的数据进行同步,从而实现数据的一致性,即保证各memcached的数据是一样 的,即使有任何一台 memcached 发生故障,只要集群中有一台 memcached 可用就不会出现数据丢 失,当其他memcached 重新加入到集群的时候,可以自动从有数据的memcached 当中自动获取数据并 提供服务。

Memcached 借助了操作系统的 libevent 工具做高效的读写。libevent是个程序库,它将Linux的epoll、 BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥高 性能。

memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能 Memcached 支持最大的内存存储对象为1M,超过1M的数据可以使用客户端压缩或拆分报包放到多个 key中,比较大的数据在进行读取的时候需要消耗的时间比较长,

memcached 最适合保存用户的 session实现session共享 Memcached存储数据时, Memcached会去申请1MB的内存, 把该块内存称为一个slab, 也称为一个page Memcached 支持多种开发语言,包括:JAVA,C,Python,PHP,C#,Ruby,Perl等

Memcached 官网: http://memcached.org/

它本身不支持持久化,只支持能序列化的数据类型

没有客户端,是个键值

[root@tomcat ~]# yum install memcached -y[root@tomcat ~]# vim /etc/sysconfig/memcachedPORT="11211"USER="memcached"MAXCONN="1024"CACHESIZE="64"OPTIONS="-l 0.0.0.0,::1"0      
980        
[root@tomcat ~]# systemctl enable --now memcached[root@tomcat ~]# netstat -antlupe | grep memcachetcp        
0 0.0.0.0:11211           
97815      
34711/memcached
[root@tomcat ~]# telnet localhost 11211Trying ::1...Connected to localhost.Escape character is '^]'.#增加
add leekey  0 60 4      
#0 是否压缩  60 过期时间  4 字长
testSTOREDadd leekey1 0 60 3leeSTORED#查看
get  leekeyVALUE leekey 0 4testget leekey1VALUE leekey1 0 3lee#改
set leekey 0 60 5test1STOREDget leekeyVALUE leekey 0 5test1ENDadd leekey1 0 60 4test#删除
delete leekeyDELETEDget leekeyEND
get leekey1VALUE leekey1 0 3lee#清空
flush_allOKget leekey1END

实验:

修改接口,打开全部 

再次查看端口信息

要把接口都打开

测试(长连接实验也用过):

这里的2是字长 :规定后面输入的字数只能是两个

查看刚刚储存的内容

修改储存的内容

删除并退出

企业一般不用


使用插件,让tomcat往memcached里存储,实际上,两者是没有关系的。

四、msm

[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.KryoTranscoderFactory"/>[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.KryoTranscoderFactory"/>

修改nginx配置

[root@Nginx ~]# vim /usr/local/nginx/conf.d/vhosts.confupstream 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;}

查看memcached的版本

要去找合适版本的插件

安装

要把插件放进tomcat库里

查看tomcat的插件存储位置

服务重启成功后IP会发生变化

failoverNodes:当一个服务器的tomcat出故障时,另一台会要找自己的memcached的,因为自己的里面也是有对端的数据的

重启服务

测试:

20tomcat挂了

这里会有之前数据的原因是,20往10的memcached里存的数据,20挂了,10会在memcached里读取数据

http://www.lryc.cn/news/614831.html

相关文章:

  • kettle插件-kettle MinIO插件,轻松解决文件上传到MinIO服务器
  • 解决本地连接服务器ollama的错误
  • 大语言模型提示工程与应用:大语言模型对抗性提示安全防御指南
  • LLVM编译器入门
  • Java基础-TCP通信单服务器接受多客户端
  • 关于开发语言的一些效率 从堆栈角度理解一部分c java go python
  • 软考 系统架构设计师系列知识点之杂项集萃(119)
  • 数据结构(9)——排序
  • QT第三讲- 机制、宏、类库模块
  • 数字图像处理基础——opencv库(Python)
  • 算法_python_牛客华为机试笔记_01
  • 【Python 高频 API 速学 ③】
  • RecyclerView 中 ViewHolder
  • TDengine IDMP 快速体验(1. 通过云服务)
  • 【CVPR2025】计算机视觉|PX:让模型训练“事半功倍”!
  • vscode/trae 的 settings.json 中配置 latex 的一些记录
  • 设备点检系统二维码的应用
  • 我用C++和零拷贝重构了文件服务器,性能飙升3倍,CPU占用降低80%
  • Amazon Linux 训练lora模型的方式
  • 《算法导论》第 14 章 - 数据结构的扩张
  • ruoyi关闭shiro校验,任何接口可以直接访问
  • C++-红黑树
  • [C/C++线程安全]_[中级]_[多线程如何使用共享锁提升性能]
  • Meta AI水印计划的致命缺陷——IEEE Spectrum深度文献精读
  • 第4章 程序段的反复执行4.2while语句P128练习题(题及答案)
  • ppt 生成视频的 ai 大模型全面解析
  • (talk)西安大模型开发者talk
  • vue+flask大模型写诗诗词推荐与可视化系统
  • 浏览器面试题及详细答案 88道(01-11)
  • 项目一系列-第4章 在线接口文档 代码模板改造