一、 核心定位:Servlet 容器

  1. 不是通用 Web 服务器:虽然 Tomcat 内置了 HTTP 连接器能直接处理 HTTP 请求,但其核心职责是执行 Java Servlet、JSP (JavaServer Pages) 和 WebSocket 等 Java EE(现 Jakarta EE)规范。对于高并发的静态文件服务、复杂的反向代理规则,它不如 Nginx 专业和高效。

  2. 应用服务器的轻量级代表:相比 IBM WebSphere、Oracle WebLogic 等全功能 Java EE 应用服务器,Tomcat 更轻量、启动快、配置简单,是 Spring Boot 等现代框架的默认嵌入式服务器选择。

二、 Tomcat 的高性能架构与连接器

Tomcat 的性能核心在于其 连接器​ 组件。它负责实现 HTTP协议,接收网络请求,并将请求交给后端的Servlet容器(Catalina)处理。

Tomcat 支持三种主要的I/O模型(通过配置 Connectorprotocol属性选择):

1. BIO (阻塞式I/O) - 传统模型

  • 原理:每个请求分配一个独立的处理线程。线程在等待数据(如网络I/O、数据库查询)时会被阻塞。

  • 配置protocol="HTTP/1.1"(Tomcat 8 及以前默认)

  • 特点:编程模型简单,但线程创建和上下文切换开销大,不适合高并发长连接场景。已过时

2. NIO (非阻塞式I/O) - 推荐默认

  • 原理:基于 Java NIO 库,使用一个或少量线程(Poller)通过 Selector管理所有连接。只有当连接准备好进行读写时,才会从线程池中分配一个工作线程来处理请求体读取和业务逻辑。

  • 配置protocol="org.apache.coyote.http11.Http11NioProtocol"

  • 特点能有效应对高并发连接,尤其适合大量连接但请求不频繁(如长轮询、WebSocket)的场景。自Tomcat 8起成为默认连接器。

3. NIO2 (异步I/O)

  • 原理:基于 Java NIO.2 (AIO),使用回调机制,理论上比 NIO 更高效。

  • 配置protocol="org.apache.coyote.http11.Http11Nio2Protocol"

  • 特点:在特定场景下(如大量文件操作)可能表现更好,但在 Linux 系统上优势不明显,因为 Linux 的 AIO 实现并不完善。社区使用和优化程度不及 NIO。

4. APR (Apache Portable Runtime)

  • 原理:使用 JNI 调用本地(C语言)的 Apache 运行时库,利用了操作系统级别的优化(如 epoll)。

  • 配置protocol="org.apache.coyote.http11.Http11AprProtocol"

  • 特点:性能通常最好,特别是处理静态资源。需要额外安装本地库,部署复杂度高,且与 Java 生态的整合调试不如纯 Java 方案方便。

结论:对于绝大多数生产环境,使用默认的 NIO 连接器​ 即可获得最佳平衡的性能和可维护性。

三、Tomcat安装部署

下载安装包

# 环境确定
[root@RS1 ~]# systemctl disable --now httpd
Removed "/etc/systemd/system/multi-user.target.wants/httpd.service".
[root@RS2 ~]# systemctl disable --now httpd
Removed "/etc/systemd/system/multi-user.target.wants/httpd.service".
 
# 下载安装包
[root@RS1 ~]# wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.115/bin/apache-tomcat-9.0.115.tar.gz
[root@RS2 ~]# wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.115/bin/apache-tomcat-9.0.115.tar.gz

部署tomcat

[root@RS1 ~]# yum install java-1.8.0-openjdk.x86_64 -y
[root@RS1 ~]# tar zxf apache-tomcat-9.0.115.tar.gz  -C /usr/local
[root@RS1 ~]# cd /usr/local/
[root@RS1 local]# ls
apache-tomcat-9.0.115  etc    include  lib64    sbin   src
bin                    games  lib      libexec  share
[root@RS1 local]# mv apache-tomcat-9.0.115/ tomcat
[root@RS1 local]# cd tomcat/
[root@RS1 tomcat]# ls
bin           CONTRIBUTING.md  logs       RELEASE-NOTES  webapps
BUILDING.txt  lib              NOTICE     RUNNING.txt    work
conf          LICENSE          README.md  temp
 
[root@RS1 tomcat]# cd /usr/local/tomcat/bin/
[root@RS1 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.
[root@RS1 bin]# netstat -antlupe | grep 8080
tcp6       0      0 :::8080                 :::*                    LISTEN      0          57753      12479/java

制作tomcat的启动脚本

[root@RS1 bin]# vim /usr/local/tomcat/conf/tomcat.conf
JAVA_HOME=/etc/alternatives/jre
[root@RS1 bin]# 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
 
[root@RS1 bin]# useradd  -s /sbin/nologin -M tomcat
[root@RS1 bin]# chown  tomcat.tomcat /usr/local/tomcat/ -R
[root@RS1 bin]# systemctl daemon-reload
[root@RS1 bin]# systemctl enable --now tomcat
Created symlink /etc/systemd/system/multi-user.target.wants/tomcat.service → /usr/lib/systemd/system/tomcat.service.
[root@RS1 bin]# netstat -antlupe | grep java
tcp6       0      0 :::8080                 :::*                    LISTEN      1000       60540      13427/java
tcp6       0      0 127.0.0.1:8005          :::*                    LISTEN      1000       60282      13427/java

二、Nginx与tomcat的整合

 利用nginx反向代理功能,实现图中的代理功能,将用户请求全部转发至指定的同一个tomcat主机

 利用nginx指令proxy_pass 可以向后端服务器转发请求报文,并且在转发时会保留客户端的请求报文中的

单体架构

[root@Nginx ~]# cd /usr/local/nginx/conf/conf.d/
[root@Nginx conf.d]# vim vhosts.conf
server {
    listen 80;
    server_name app.timinglee.org;
    location ~* \.jsp$ {
        proxy_pass http://172.25.254.10:8080;
    }
}
 
[root@RS1 ~]# cp test.jsp  /usr/local/tomcat/webapps/ROOT/
[root@RS2 ~]# cp test.jsp  /usr/local/tomcat/webapps/ROOT/
[root@Nginx conf.d]# systemctl restart nginx.service
 
#在windows中设定app.timinglee.org的解析
#在浏览器中访问 app.timinglee.org/test.jsp

tomcat负载均衡

[root@Nginx conf.d]# vim vhosts.conf
upstream tomcat {
    hash $cookie_JSESSIONID;
    server 172.25.254.10:8080;
    server 172.25.254.20:8080;
}
server {
    listen  80;
    server_name app.timinglee.org;
    location ~* \.jsp$ {
        proxy_pass http://tomcat;
    }
}

三、tomcat+memcache实现session会话零丢失

tomcat加载模块

[root@RS1 ~]# unzip jar.zip
[root@RS1 ~]# cd jar/
[root@RS1 jar]# cp * /usr/local/tomcat/
[root@RS1 jar]# scp * root@172.25.254.20:/usr/local/tomcat/lib/

安装memcache

[root@RS1 jar]# dnf install memcached
[root@RS2 ~]# dnf install memcached -y
 
[root@RS1 ~]# vim /etc/sysconfig/memcached
[root@RS2 ~]# vim /etc/sysconfig/memcached
 
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 0.0.0.0,::1"
 
[root@RS1+2 ~]# netstat -antluple | grep memcached
tcp        0      0 0.0.0.0:11211           0.0.0.0:*               LISTEN      988        142615     35756/memcached
tcp6       0      0 ::1:11211               :::*                    LISTEN      988        142616     35756/memcached

配置tomcat

[root@RS1 ]#  vim /usr/local/tomcat/conf/context.xml
 
<Context>
 
    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
 
    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
   <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"
    />
 
</Context>
 
[root@RS2 ]#  vim /usr/local/tomcat/conf/context.xml
 
<Context>
 
    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
 
    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
   <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"
    />
 
</Context>
[root@RS1 ~]#  systemctl restart tomcat.service
[root@RS2 ~]#  systemctl restart tomcat.service

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐