- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
目录 。
以 springboot:2.3.12.RELEASE 中内嵌的 tomcat-embed-core:9.0.46 为例,进行分析 。
spring-boot-autoconfigure
: 2.3.12.RELEASE spring-boot
: 2.3.12.RELEASE spring-context
: 5.2.15.RELEASE spring-webmvc
: 5.2.15.RELEASE tomcat-embed-core
:9.0.46 tomcat-embed-jasper
:9.0.46 我们在使用 springboot 开发 web 项目时,大多数时候采用的是内置的 Tomcat (当然也可配置支持内置的 jett y),内置 Tomcat 有什么好处呢?
针对目前的容器优化,可以从以下几点考虑:
首先,线程数是一个重点,每一次HTTP请求到达Web服务器,Web服务器都会创建一个线程来处理该请求,该参数决定了应用服务同时可以处理多少个HTTP请求。 比较重要的有两个:1) 初始线程数; 2) 最大线程数.
- 初始线程数:保障启动的时候,如果有大量用户访问,能够很稳定的接受请求。
- 最大线程数:用来保证系统的稳定性。
超时时间:用来保障连接数不容易被压垮。 如果大批量的请求过来,延迟比较高,很容易把线程数用光,这时就需要提高超时时间。 这种情况在生产中是比较常见的 ,一旦网络不稳定,宁愿丢包也不能把服务器压垮.
默认 10 最小备用线程数,tomcat启动时的初始化的线程数.
默认 200 Tomcat可创建的最大的线程数,每一个线程处理一个请求; 超过这个请求数后,客户端请求只能排队,等有线程释放才能处理。 建议:这个配置数可以在服务器CUP核心数的 200~250 倍之间 。
默认 100 当调用Web服务的HTTP请求数达到tomcat的最大线程数时,还有新的HTTP请求到来,这时tomcat会将该请求放在等待队列中 这个acceptCount就是指能够接受的最大等待数 如果等待队列也被放满了,这个时候再来新的请求就会被tomcat拒绝(connection refused).
这个参数是指在同一时间,tomcat能够接受的最大连接数。(最大线程数+排队数) 一般这个值要大于 (max-threads)+(accept-count).
1 默认值: 60S or 20S 2 参数定义: 与客户端建立连接后,Tomcat 等待客户端请求的时间。 如果客户端没有请求进来,等待一段时间后断开连接,释放线程。 3 备注说明: Tomcat 中 等效于 : socket.soTimeout (SO_TIMEOUT) => 即: 为 socket 调用 read() 等待读取的时间 4 入口类
Tomcat 在关闭连接(Connector)之前,等待另一个请求的时间 。
- HTTP 1.0
http协议的早期是,每开启一个http链接,是要进行一次socket,也就是新启动一个TCP链接.
- HTTP 1.1
1 特性:长连接 (现主流浏览器的默认协议) 2 使用keep-alive可以改善这种状态,即在一次TCP连接中可以持续发送多份数据而不会断开连接。通过使用keep-alive机制,可以减少tcp连接建立次数。 3 如果浏览器支持keepalive的话,那么请求头中会有: Connection: Keep-Alive 4 对于keepalive的部分,主要集中在Connection属性当中,这个属性可以设置两个值:
- close (告诉WEB服务器或者代理服务器,在完成本次请求的响应后,断开连接,不要等待本次连接的后续请求了)。
- keepalive (告诉WEB服务器或者代理服务器,在完成本次请求的响应后,保持连接,等待本次连接的后续请求)。
5 keep-alive与TIME_WAIT的关系?- 使用http keep-alive,可以减少服务端TIME_WAIT数量(因为由服务端httpd守护进程主动关闭连接)。道理很简单,相较而言,启用keep-alive,建立的tcp连接更少了,自然要被关闭的tcp连接也相应更少了。
- 什么是TIME_WAIT呢?
- 通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态。
- 客户端主动关闭连接时,会发送最后一个ack后,然后会进入TIME_WAIT状态,再停留2个MSL时间,进入CLOSED状态。
- 那么这个TIME_WAIT到底有什么作用呢?主要原因:
- a)可靠地实现TCP全双工连接的终止
- b)允许老的重复分节在网络中消逝
6 截止目前,我们讨论的是 http 1.1 request/response header 的 keep-alive 选项;而 tcp协议 也有keepalive的概念。
http keep-alive与tcp keep-alive,不是同一回事,意图不一样。
http keep-alive是为了让tcp活得更久一点,以便在同一个连接上传送多个http,提高socket的效率。
而tcp keep-alive是TCP的一种检测TCP连接状况的保鲜机制。
tcp keep-alive保鲜定时器,支持三个系统内核配置参数:
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 15 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes
keepalive是TCP保鲜定时器,当网络两端建立了TCP连接之后,闲置idle(双方没有任何数据流发送往来)了tcp_keepalive_time后,服务器内核就会尝试向客户端发送侦测包,来判断TCP连接状况(有可能客户端崩溃、强制关闭了应用、主机不可达等等)。如果没有收到对方的回答(ack包),则会在 tcp_keepalive_intvl后再次尝试发送侦测包,直到收到对对方的ack,如果一直没有收到对方的ack,一共会尝试 tcp_keepalive_probes次,每次的间隔时间在这里分别是15s, 30s, 45s, 60s, 75s。如果尝试tcp_keepalive_probes,依然没有收到对方的ack包,则会丢弃该TCP连接。TCP连接默认闲置时间是2小时,一般设置为30分钟足够了。
总结一下,实际上tcp keep-alive是一个协议级别的心跳检测实现,当超过规定的时间,tcp就断开,而这边是讨论的http的keepalive,描述的http高层多次tcp链接共享,根本不是一个网络层级的东西,一定注意不要混淆。
-> org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
@ConditionalOnClass({Tomcat.class, UpgradeProtocol.class})
public static class TomcatWebServerFactoryCustomizerConfiguration { [*]
@Bean
public TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment, ServerProperties serverProperties){
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
}
}
-> org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer
+ 关系: public class TomcatWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory>, Ordered { /** ... **/ }
+ 属性:
private final Environment environment;
private final org.springframework.boot.autoconfigure.web.ServerProperties serverProperties; [*]
+ 方法:
public void customize(ConfigurableTomcatWebServerFactory factory) {
ServerProperties properties = this.serverProperties;
ServerProperties.Tomcat tomcatProperties = properties.getTomcat();
--> Tomcat { // 内部类
private final Threads threads = new Threads();
...
private int maxConnections;
private int acceptCount;
...
private Duration connectionTimeout;
...
private Charset uriEncoding;
--> Threads { // 内部类
private int max = 200;
private int minSpare = 10;
}
}
PropertyMapper propertyMapper = PropertyMapper.get();
ServerProperties.Tomcat.Threads threadProperties = tomcatProperties.getThreads();
...
propertyMapper.from(threadProperties::getMax).when(this::isPositive).to((maxThreads) -> {
this.customizeMaxThreads(factory, threadProperties.getMax());
});
...
propertyMapper.from(threadProperties::getMinSpare).when(this::isPositive).to((minSpareThreads) -> {
this.customizeMinThreads(factory, minSpareThreads);
});
...
propertyMapper.from(tomcatProperties::getMaxHttpFormPostSize).asInt(DataSize::toBytes).when((maxHttpFormPostSize) -> {
return maxHttpFormPostSize != 0;
}).to((maxHttpFormPostSize) -> {
this.customizeMaxHttpFormPostSize(factory, maxHttpFormPostSize);
});
...
propertyMapper.from(tomcatProperties::getAccesslog).when(ServerProperties.Tomcat.Accesslog::isEnabled).to((enabled) -> {
this.customizeAccessLog(factory);
});
...
propertyMapper.from(tomcatProperties::getUriEncoding).whenNonNull().to(factory::setUriEncoding);
...
propertyMapper.from(tomcatProperties::getConnectionTimeout).whenNonNull().to((connectionTimeout) -> {
this.customizeConnectionTimeout(factory, connectionTimeout);
});
...
propertyMapper.from(tomcatProperties::getMaxConnections).when(this::isPositive).to((maxConnections) -> {
this.customizeMaxConnections(factory, maxConnections);
});
...
propertyMapper.from(tomcatProperties::getAcceptCount).when(this::isPositive).to((acceptCount) -> {
this.customizeAcceptCount(factory, acceptCount);
});
}
private void customizeAcceptCount(ConfigurableTomcatWebServerFactory factory, int acceptCount) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer[]{(connector) -> {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) {
AbstractProtocol<?> protocol = (AbstractProtocol)handler;
protocol.setAcceptCount(acceptCount);
}
}});
}
...
private void customizeMaxConnections(ConfigurableTomcatWebServerFactory factory, int maxConnections) {
factory.addConnectorCustomizers(new TomcatConnectorCustomizer[]{(connector) -> {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) {
AbstractProtocol<?> protocol = (AbstractProtocol)handler;
protocol.setMaxConnections(maxConnections);
}
}});
}
...
最后此篇关于[WebServer]Tomcat调优之SpringBoot内嵌Tomcat源码分析的文章就讲到这里了,如果你想了解更多关于[WebServer]Tomcat调优之SpringBoot内嵌Tomcat源码分析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
ACO.Visualization项目 本项目演示蚁群算法求解旅行商问题的可视化过程,包括路径上的信息素浓度、蚁群的运动过程等。项目相关的代码:https://github.com/anycad/A
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我需要用Sql数据库制作并包含的PHP票务系统源码用户客户端和管理员。我需要个人 CMS 的这个来源。谢谢你帮助我。 最佳答案 我在不同的情况下使用了 osticket。 这里: http://ost
我的场景:我想在日志文件中写入发生异常的部分代码(例如,发生异常的行前 5 行和行后 5 行 - 或者至少是该方法的所有代码)。 我的想法是用 C# 代码反编译 pdb 文件,并从该反编译文件中找到一
RocketMQ设定了延迟级别可以让消息延迟消费,延迟消息会使用 SCHEDULE_TOPIC_XXXX 这个主题,每个延迟等级对应一个消息队列,并且与普通消息一样,会保存每个消息队列的消费进度
先附上Hystrix源码图 在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和
此篇博客学习的api如标题,分别是: current_url 获取当前页面的url; page_source 获取当前页面的源码; title 获取当前页面的titl
? 1 2
1、前言 作为一个数据库爱好者,自己动手写过简单的sql解析器以及存储引擎,但感觉还是不够过瘾。<<事务处理-概念与技术>>诚然讲的非常透彻,但只能提纲挈领,不能让你
gory"> 目录 运行时信号量机制 semaphore 前言 作用是什么 几个主要的方法 如何实现
自己写的一个评论系统源码分享给大家,包括有表情,还有评论机制。用户名是随机的 针对某一篇文章进行评论 function subcomment() {
一、概述 StringBuilder是一个可变的字符串序列,这个类被设计去兼容StringBuffer类的API,但不保证线程安全性,是StringBuffer单线程情况下的一个替代实现。在可能的情
一、概述 System是用的非常多的一个final类。它不能被实例化。System类提供了标准的输入输出和错误输出流;访问外部定义的属性和环境变量;加载文件和库的方法;以及高效的拷贝数组中一部分元素
在JDK中,String的使用频率和被研究的程度都非常高,所以接下来我只说一些比较重要的内容。 一、String类的概述 String类的声明如下: public final class Str
一、概述 Class的实例代表着正在运行的Java应用程序的类和接口。枚举是一种类,而直接是一种接口。每一个数组也属于一个类,这个类b被反射为具有相同元素类型和维数的所有数组共享的类对象。八大基本树
一、概述 Compiler这个类被用于支持Java到本地代码编译器和相关服务。在设计上,这个类啥也不做,他充当JIT编译器实现的占位符。 放JVM虚拟机首次启动时,他确定系统属性java.comp
一、概述 StringBuffer是一个线程安全的、可变的字符序列,跟String类似,但它能被修改。StringBuffer在多线程环境下可以很安全地被使用,因为它的方法都是通过synchroni
一、概述 Enum是所有Jav中枚举类的基类。详细的介绍在Java语言规范中有说明。 值得注意的是,java.util.EnumSet和java.util.EnumMap是Enum的两个高效实现,
一、概述 此线程指的是执行程序中的线程。 Java虚拟机允许应用程序同时执行多个执行线程。 每个线程都有优先权。 具有较高优先级的线程优先于优先级较低的线程执行。 每个线程可能也可能不会被标记为守
一、抽象类Number 类继承关系 这里面的原子类、BigDecimal后面都会详细介绍。 属性和抽象方法 二、概述 所有的属性,最小-128,最大127,SIZE和BYTES代码比
我是一名优秀的程序员,十分优秀!