云计算百科
云计算领域专业知识百科平台

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

一. web

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

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

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

  • 因此,只要最终是通过浏览器访问的,几乎都可以说“由 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、三大核心技术到底各干什么?

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

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

    css

    复制

    input[type=text] {
    border-radius: 8px;
    box-shadow: 0 0 10px #00f;
    }

  • JavaScript(肌肉)
    让页面“动起来”:

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

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

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

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


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

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

  • 填 8 个字段 → 点【提交】

  • 浏览器整页 POST 给服务器

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

  • 返回一个全新 HTML 页面

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

  • 缺点:

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

    • 体验差(用户想骂人)


    1.5、异步交互:Ajax 的魔法

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

  • 流程对比:

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

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

  • 关键词:

    • Ajax(Asynchronous JavaScript And XML)

    • 现在多用 JSON 代替 XML

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


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

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

  • mvn package 打成 war → 扔到 Tomcat 的 webapps。

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

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

  • 用户填完账号密码,JS 用 Ajax POST /login。

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

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

  • 二 tomcat

    #安装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

    #解压并生成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
    juli.jar
    catalina.bat
    native.tar.gz
    catalina.sh
    configtest.bat
    configtest.sh
    wrapper.bat
    catalina-tasks.xml daemon.sh
    wrapper.sh
    ciphers.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.sh
    Using CATALINA_BASE: /usr/local/tomcat
    Using CATALINA_HOME: /usr/local/tomcat
    Using CATALINA_TMPDIR: /usr/local/tomcat/temp
    Using JRE_HOME:
    /usr
    tool
    tool
    version.bat
    version.sh
    Using CLASSPATH:
    /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
    Using 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部署

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


  • 什么是“反向代理”?


    • 正反向区别一句话:

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

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

    • 为什么要反向代理 Tomcat?

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

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

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

    • 指令拆解

      nginx

      复制

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

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


  • 为什么要“负载均衡”?


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

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

    • Nginx 的 3 种常用调度算法

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

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

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


  • HTTP 的无状态 & Session 机制


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

    • 解决思路:

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

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

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

    • 生命周期

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

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


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


  • 场景:

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

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

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


  • 三种 Session 一致性方案对比


  • 表格

    复制

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

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


  • 复制

    浏览器

    │ 1. 登录请求 → Nginx → Tomcat-A
    │ │
    │ └─ 2. 创建 SessionID=1001
    │ 同时 3. 序列化 Session 到 Memcached

    │ 4. 第二次请求 → Nginx → Tomcat-B
    │ │
    │ └─ 5. Tomcat-B 发现 Cookie:JSESSIONID=1001
    6. 去 Memcached 取 Session → 继续业务

    • 如果 Tomcat-A 挂了,Tomcat-B/C/D 任何一台都能从 Memcached 拿到同一份 Session,用户无感知。


  • 配置小结(回顾)


  • 反向代理(单机)

    nginx

    复制

    location ~ \\.jsp$ {
    proxy_pass http://172.25.254.10:8080;
    proxy_set_header Host $host;
    }

  • 负载均衡(多机)

    nginx

    复制

    upstream tomcat {
    hash $cookie_JSESSIONID; # 会话保持最稳
    server 172.25.254.10:8080;
    server 172.25.254.20:8080;
    }

  • 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/memcached
    PORT="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 memcache
    tcp
    0 0.0.0.0:11211
    97815
    34711/memcached

    [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

    实验:

    修改接口,打开全部 

    再次查看端口信息

    要把接口都打开

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

    这里的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.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配置

    [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;
    }

    查看memcached的版本

    要去找合适版本的插件

    安装

    要把插件放进tomcat库里

    查看tomcat的插件存储位置

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

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

    重启服务

    测试:

    20tomcat挂了

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

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 企业级web应用服务器TOMCAT入门详解
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!