Tomcat基础升华学习

01 What is Tomcat

1.1 Tomcat官网

官网 :https://tomcat.apache.org

1.2 Understand

为什么说Tomcat是Servlet之类技术的实现?
在我们的理解中,Tomcat可以称为Web容器或者Servlet容器
不妨通过手写一个Tomcat来推导一下

1.2.1 创建Tomcat类

Java是一门面向对象的开发语言

//这就是我们写的Tomcat
class MyTomcat{
....
}
1.2.2 Web容器

在这里插入图片描述
在这里插入图片描述
使用命令查看相关指标

01 查看tomcat进程pid
ps -ef | grep tomcat
02 查看进程的信息
cat /pro/pid/status
03 查看进程的cpu和内存
top -p pid

使用工具查看相关指标

jconsole、jvisualvm、arthas、psi-probe等

1.1 优化思路

1.1.1 conf/server.xml核心组件

Server
官网描述 :Server interface which is rarely customized by users. 【pass】
Service
官网描述 :The Service element is rarely customized by users. 【pass】
Connector
官网描述 :Creating a customized connector is a significant effort. 【 need 】
Engine
官网描述 :The Engine interface may be implemented to supply custom Engines, though this is uncommon.
【pass】
Host
官网描述 :Users rarely create custom Hosts because the StandardHost implementation provides significant
additional functionality. 【pass】
Context
官网描述 :The Context interface may be implemented to create custom Contexts, but this is rarely the case
because the StandardContext provides significant additional functionality. 【 maybe 】
Context既然代表的是web应用,是和我们比较接近的,这块我们考虑对其适当的优化
conclusion:Connector and Context

1.1.2 conf/server.xml非核心组件

官网 :https://tomcat.apache.org/tomcat-8.0-doc/config/index.html
Listener
Listener(即监听器)定义的组件,可以在特定事件发生时执行特定的操作;被监听的事件通常是Tomcat的启动和停止。

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--监听内存溢出-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

Global Resources
GlobalNamingResources元素定义了全局资源,通过配置可以看出,该配置是通过读取$TOMCAT_HOME/
conf/tomcat-users.xml实现的。
The GlobalNamingResources element defines the global JNDI resources for the [Server]
(https://tomcat.apache.org/tomcat-8.0-doc/config/server.html)

<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>

Valve

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />

Realm
Realm,可以把它理解成“域”;Realm提供了一种用户密码与web应用的映射关系,从而达到角色安全管理的作用。在本例
中,Realm的配置使用name为UserDatabase的资源实现。而该资源在Server元素中使用GlobalNamingResources配置
A Realm element represents a “database” of usernames, passwords, and roles (similar to
Unix groups) assigned to those users.

<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
1.1.3 conf/web.xml

全局的web.xml文件有些标签用不到的,可以删除掉。

1.1.4 JVM层面

因为Tomcat运行起来本身就是一个Java进程,所以这块可以参照JVM部分的优化思路。

1.2 配置优化

1.2.1 减少web.xml/server.xml中标签

最终观察tomcat启动日志[时间/内容],线程开销,内存大小,GC等
DefaultServlet
官网 :User Guide->Default Servlet
The default servlet is the servlet which serves static resources as well as serves the directory listings (if
directory listings are enabled)

<servlet><servlet-name>default</servlet-name><servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class><init-param><param-name>debug</param-name><param-value>0</param-value></init-param><init-param><param-name>listings</param-name><param-value>false</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>default</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

JspServlet

<servlet><servlet-name>jsp</servlet-name><servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class><init-param><param-name>fork</param-name><param-value>false</param-value></init-param><init-param><param-name>xpoweredBy</param-name><param-value>false</param-value></init-param><load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>jsp</servlet-name><url-pattern>*.jsp</url-pattern><url-pattern>*.jspx</url-pattern>
</servlet-mapping>

welcome-list-file

<welcome-file-list><welcome-file>index.html</welcome-file><welcome-file>index.htm</welcome-file><welcome-file>index.jsp</welcome-file>
</welcome-file-list>

mime-mapping移除响应的内容
支持的下载打开类型

<mime-mapping><extension>123</extension><mime-type>application/vnd.lotus-1-2-3</mime-type>
</mime-mapping>
<mime-mapping><extension>3dml</extension><mime-type>text/vnd.in3d.3dml</mime-type>
</mime-mapping>

session-config
默认jsp页面有session,就是在于这个配置

<session-config><session-timeout>30</session-timeout>
</session-config>
1.2.2 调整优化server.xml中标签
1.2.2.1 Connector标签

protocol属性

<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

对于protocol=“HTTP/1.1”,查看源码
构造函数

public Connector(String protocol) {
setProtocol(protocol);
}

setProtocol(protocol)因为配置文件中传入的是HTTP/1.1
并且这里没有使用APR

else {if ("HTTP/1.1".equals(protocol)) {setProtocolHandlerClassName("org.apache.coyote.http11.Http11NioProtocol");} else if ("AJP/1.3".equals(protocol)) {setProtocolHandlerClassName("org.apache.coyote.ajp.AjpNioProtocol");} else if (protocol != null) {setProtocolHandlerClassName(protocol);}
}

发现这里调用的是Http11NioProtocol,也就是说明tomcat8.0.x中默认使用的是NIO
使用同样的方式看tomcat7和tomcat8.5,你会发现tomcat7默认使用的是BIO,tomcat8.5默认使用的是NIO
针对BIO和NIO的方式进行压测
(1)BIO
来到tomcat官网Configuration/HTTP/protocol

org.apache.coyote.http11.Http11Protocol - blocking Java connector
org.apache.coyote.http11.Http11NioProtocol - non blocking Java NIO connector
org.apache.coyote.http11.Http11Nio2Protocol - non blocking Java NIO2 connector
org.apache.coyote.http11.Http11AprProtocol - the APR/native connector.

(2)NIO
tomcat8.0中默认使用的是NIO
(3)APR
调用本地方法库进行IO操作
executor属性
最佳线程数公式 😦(线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量

The Executor represents a thread pool that can be shared between components in Tomcat.
Historically there has been a thread pool per connector created but this allows you to
share a thread pool, between (primarily) connector but also other components when those get
configured to support executors

默认的可以查看StandardExecutor类
设置一些属性
官网:https://tomcat.apache.org/tomcat-8.0-doc/config/http.html
(1)acceptCount:达到最大连接数之后,等待队列中还能放多少连接,超过即拒绝,配置太大也没有意义

The maximum queue length for incoming connection requests when all possible request
processing threads are in use. Any requests received when the queue is full will be
refused. The default value is 100.

(2)maxConnections
达到这个值之后,将继续接受连接,但是不处理,能继续接受多少根据acceptCount的值
BIO:maxThreads
NIO/NIO2:10000 ——— AbstractEndpoint.maxConnections
APR:8192

The maximum number of connections that the server will accept and process at any given
time. When this number has been reached, the server will accept, but not process, one
further connection. This additional connection be blocked until the number of connections
being processed falls below maxConnections at which point the server will start accepting
and processing new connections again. Note that once the limit has been reached, the
operating system may still accept connections based on the acceptCount setting. The default
value varies by connector type. For BIO the default is the value of maxThreads unless an
Executor is used in which case the default will be the value of maxThreads from the
executor. For NIO and NIO2 the default is 10000. For APR/native, the default is 8192.
Note that for APR/native on Windows, the configured value will be reduced to the highest
multiple of 1024 that is less than or equal to maxConnections. This is done for performance
reasons.
If set to a value of -1, the maxConnections feature is disabled and connections are not
counted.

(3)maxThreads:最大工作线程数,也就是用来处理request请求的,默认是200,如果自己配了executor,并且和
Connector有关联了,则之前默认的200就会被忽略,取决于CPU的配置。监控中就可以看到所有的工作线程是什么
状态,通过监控就能知道开启多少个线程合适.

The maximum number of request processing threads to be created by this Connector, which
therefore determines the maximum number of simultaneous requests that can be handled. If
not specified, this attribute is set to 200. If an executor is associated with this
connector, this attribute is ignored as the connector will execute tasks using the executor
rather than an internal thread pool. Note that if an executor is configured any value set
for this attribute will be recorded correctly but it will be reported (e.g. via JMX) as -1
to make clear that it is not used.

(4)minSpareThreads
最小空闲线程数

The minimum number of threads always kept running. This includes both active and idle
threads. If not specified, the default of 10 is used. If an executor is associated with
this connector, this attribute is ignored as the connector will execute tasks using the
executor rather than an internal thread pool. Note that if an executor is configured any
value set for this attribute will be recorded correctly but it will be reported (e.g. via
JMX) as -1 to make clear that it is not used.

可以实践一下,Connector配合自定义的线程池

<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>

其实这块最好的方式是结合BIO来看,因为BIO是一个request对应一个线程
值太低,并发请求多了之后,多余的则进入等待状态。
值太高,启动Tomcat将花费更多的时间。
比如可以改成250。
enableLookups
设置为false
删掉AJP的Connector

1.2.2.2 Host标签

autoDeploy :Tomcat运行时,要用一个线程拿出来进行检查,生产环境之下一定要改成false

This flag value indicates if Tomcat should check periodically for new or updated web
applications while Tomcat is running. If true, Tomcat periodically checks the appBase and
xmlBase directories and deploys any new web applications or context XML descriptors found.
Updated web applications or context XML descriptors will trigger a reload of the web
application. The flag's value defaults to true. See Automatic Application Deployment for
more information.
1.2.2.3 Context标签

reloadable:false
reloadable:如果这个属性设为true,tomcat服务器在运行状态下会监视在WEB-INF/classes和WEB-INF/lib目录下
class文件的改动,如果监测到有class文件被更新的,服务器会自动重新加载Web应用。
在开发阶段将reloadable属性设为true,有助于调试servlet和其它的class文件,但这样用加重服务器运行负荷,建议
在Web应用的发存阶段将reloadable设为false。

Set to true if you want Catalina to monitor classes in /WEB-INF/classes/ and /WEB-INF/lib
for changes, and automatically reload the web application if a change is detected. This
feature is very useful during application development, but it requires significant runtime
overhead and is not recommended for use on deployed production applications. That's why the
default setting for this attribute is false. You can use the Manager web application,
however, to trigger reloads of deployed applications on demand.

1.3 启动速度优化

删除没用的web应用
因为tomcat启动每次都会部署这些应用
关闭WebSocket
websocket-api.jar和tomcat-websocket.jar
随机数优化
设置JVM参数:-Djava.security.egd=file:/dev/./urandom
多个线程启动Web应用

<Host startStopThreads="0">
</Host>

1.4 其他方面的优化

Connector
配置压缩属性compression=“500”,文件大于500bytes才会压缩
数据库优化
减少对数据库访问等待的时间,可以从数据库的层面进行优化,或者加缓存等等各种方案。
开启浏览器缓存,nginx静态资源部署

1.5 常见问题排查

1.5.1 CPU使用率过高

可能原因
GC频繁或者创建了很多业务线程
排查
哪些线程比较消耗CPU,或者多线程上下文频繁切换
解决思路
top -H -p pid 查看某个Java进程各个线程使用CPU的情况,找到哪个线程占用CPU比较高
jstack pid 打印出线程信息,定位到上述的线程名称

1.5.2 拒绝连接

java.net.BindException: Address already in use: JVM_Bind
端口被占用,可以使用netstat -an 查看端口占用情况,关闭对应的进程或者tomcat换端口
java.net.ConnectException: Connection refused: connect
ping一下服务端的IP,可能服务端机器有问题
java.net.SocketException: Too many open files
可能在高并发的情况下,创建的Socket过多,文件句柄不够用了,可以关闭无用的句柄,如果都有用,可以增加文件
句柄数:ulimit -n 10000

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/343909.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI智能分析网关V4:太阳能+4G智慧水库远程可视化智能监管方案

一、背景需求分析 由于水库位置分散的原因&#xff0c;水库视频监控建设在立杆、布线等方面都存在一定的难度&#xff0c;且需要人力、物力的前期投入和后期维护。目前水库的监管存在一定的问题&#xff0c;管理人员工作强度大但管理质量并不高&#xff0c;人为巡检无法实时发…

Maven_下载_安装_配置

文章参考&#xff1a;https://zhuanlan.zhihu.com/p/615382243 Maven简介 Maven 是 Apache 软件基金会的一个开源项目,是一个优秀的项目构建工具,它用来帮助开发者管理项目中的 jar,以及 jar 之间的依赖关系、完成项目的编译、测试、打包和发布等工作。 maven优点&#xff1a;…

Linux中关于echo命令详解

echo的作用 echo用于输出字符或字符串或者回显。 echo的参数说明 -n不换行输出内容-e解析转义字符-E不使用解析转义字符 使用 "-e" 参数拓展参数 \b删除前一个字符\c最后不加上换行号\f换页\n换行并将光标移动到行首\r光标移动到行首切不换行,如果\r后面还有字符,…

AI绘画软件Stable Diffusion模型/Lora/VAE文件存放位置

型下载说明&#xff08;下载模型后输入对应参数即可生成&#xff09; 建议直接去civitai.com找模型&#xff0c;如果无法找到可以在幕后模型区找也可以去&#xff0c; 下载好后放入对应的文件夹。进入127.0.0.1:7680 左上角刷新即可看到新的模型。 模型种类 大模型 大模型特…

【设计模式-04】Factory工厂模式

简要描述 简单工厂静态工厂工厂方法 FactoryMethod 产品维度扩展 抽象工厂 产品一族进行扩展Spring IOC 一、工厂的定义 任何可以产生对象的方法或类&#xff0c;都可以称之为工厂单例也是一种工厂不可咬文嚼字&#xff0c;死扣概念为什么有了new之后&#xff0c;还要有工厂&am…

深度学习在工地安全帽识别技术的应用与展望

当我们谈论“工地安全帽识别”时&#xff0c;实际上我们在探讨的是如何利用深度学习图像识别技术来提高建筑工地的安全性。这一技术的应用可以显著提高工地安全管理的效率和有效性&#xff0c;是现代建筑工程管理中不可或缺的一部分。以测评的北京富维图像的工地安全帽识别为例…

error: undefined reference to ‘cv::imread(std::__ndk1::basic_string<char

使用android studio编译项目时&#xff0c;由于用到了 cv::imread&#xff08;&#xff09;函数&#xff0c;编译时却报错找不到该函数的定义。 cv::imread一般是在highgui.hpp中定义&#xff0c;因此我加上了该头文件&#xff1a; #include “opencv2/highgui/highgui.hpp” 但…

基于博弈树的开源五子棋AI教程[3 极大极小搜索]

基于博弈树的开源五子棋AI教程[3 极大极小搜索] 引子极大极小搜索原理alpha-beta剪枝负极大搜索尾记 引子 极大极小搜索是博弈树搜索中最常用的算法&#xff0c;广泛应用于各类零和游戏中&#xff0c;例如象棋&#xff0c;围棋等棋类游戏。算法思想也是合乎人类的思考逻辑的&a…

视频转码:掌握mp4视频格式转FLV视频的技巧,视频批量剪辑方法

在多媒体时代&#xff0c;视频格式的转换成为一种常见的需求。把MP4格式转换为FLV格式&#xff0c;FLV格式的视频文件通常具有较小的文件大小&#xff0c;同时保持了较好的视频质量。批量剪辑视频的方法能大大提高工作效率。下面来看云炫AI智剪如何进行MP4到FLV的转码&#xff…

数据科学竞赛平台推荐

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

TS2307: Cannot find module ‘./App.vue‘ or its corresponding type declarations.

目录 1. 问题描述2. 解决方案一&#xff1a;VSCode Volar&#xff08;官方推荐&#xff09;3. 解决方案二&#xff1a;WebStorm 2023.2 &#xff08;官方推荐&#xff09;4. 解决方案三&#xff1a;禁用严格类型检查选项&#xff08;不推荐&#xff09;5. 解决方案四&#xff…

【Python机器学习】深度学习——调参

先用MLPClassifier应用到two_moons数据集上&#xff1a; from sklearn.neural_network import MLPClassifier from sklearn.datasets import make_moons from sklearn.model_selection import train_test_split import mglearn import matplotlib.pyplot as pltplt.rcParams[f…