外置的Tomcat
SpringBoot内置Tomcat
Tomcat的启动
有了内嵌的tomcat,我们就不需要去启动tomcat了,可以在自己的项目中去new一个tomcat,spring-boot就是这样。
代码入口
org.springframework.context.support.AbstractApplicationContext#refresh
这个方法是spring启动的核心方法
其中着重需要注意的是onRefresh方法,这个方法在spring的单独环境是没有用的,但是在springboot-web中,它的实现容器是AnnotationConfigServletWebServerApplicationContext,它的父类
ServletWebServerApplicationContext重写了这个方法,这个方法实现了tomcat的启动org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
很简单,直接创建webServer,这里不一定是tomcatServer,如果你引入了其他的Server,则创建其他的
创建tomcat,下面这个代码就很简单了,直接new一个tomcat,然后设置一些属性,包装到webServer中。repository\org\springframework\boot\spring-boot\2.0.4.RELEASE\spring-boot-2.0.3.RELEASE.jar
默认配置
SpringBoot中如果使用内嵌Tomcat,那么内嵌Tomcat的默认配置在ServerProperties(org.springframework.boot.autoconfigure.web
)中
/**
* Tomcat properties.
*/
public static class Tomcat {/**
* Maximum amount of worker threads.最大的工作线程数,默认为200,只能最多有200个耗时(比如查数据库)操作同时进行,一般小型应用中,达不到200个并发耗时操作。
*/
private int maxThreads = 200;
/**
* Minimum amount of worker threads.最小工作线程数,默认为10,即初始化时会创建10个线程用于处理请求。
*/
private int minSpareThreads = 10;/**
* Maximum number of connections that the server accepts and processes at any
* given time. Once the limit has been reached, the operating system may still
* accept connections based on the "acceptCount" property. Tomcat在给定时间(同一时间)能接受的最大连接数。
*/
private int maxConnections = 10000;
/**
* Maximum queue length for incoming connection requests when all possible request
* processing threads are in use.当前连接数超过maxConnections时,还能接受的连接的数量(排队的数量)。
*/
private int acceptCount = 100;
}
内嵌Tomcat使用的默认协议为NIO,配置在TomcatServletWebServerFactory类中,如下:
public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory
implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {
private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
private static final Set<Class<?>> NO_CLASSES = Collections.emptySet();
/**
* The class name of default protocol used.协议的默认配置
*/
public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";
private File baseDirectory;
........
}
总结:
SpringBoot 内置的Tomcat采用 NIO 协议,配置的参数为server.tomcat.maxThreads 200
,server.tomcat.maxConnections 1000
,server.tomcat.acceptCount 100
。 理论上来讲同一时刻可以处理200个请求(200个线程处理200个耗时操作),但其实可以同时接受10000个请求连接,以及大于10000个连接时,还可以再等待100个连接。
Tomcat启动流程
SpringBoot启动流程
Tomcat优化
jvm运行参数
JAVA_OPTS="-Xms2048m -Xmx2048m -Xss512k"
-Xms:初始Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
-Xmx:Java heap最大值,使用的最大内存
上面两个值是分配JVM的最小和最大内存,取决于硬件物理内存的大小,建议均设为物理内存的一半。
-XX:PermSize:设定内存的永久保存区域
-XX:MaxPermSize:设定最大内存的永久保存区域
-XX:MaxNewSize:
-Xss 15120 这使得JBoss每增加一个线程(thread)就会立即消耗15M内存,而最佳值应该是128K,默认值好像是512k.
+XX:AggressiveHeap 会使得 Xms没有意义。这个参数让jvm忽略Xmx参数,疯狂地吃完一个G物理内存,再吃尽一个G的swap。
-Xss:每个线程的Stack大小
-verbose:gc 现实垃圾收集信息
-Xloggc:gc.log 指定垃圾收集日志文件
-Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一
-XX:+UseParNewGC :缩短minor收集的时间
-XX:+UseConcMarkSweepGC :缩短major收集的时间
提示:此选项在Heap Size 比较大而且Major收集时间较长的情况下使用更合适。
SpringBoot中的Tomcat
springboot只是内嵌了tomcat而已, 所以使用的内存其实就是springboot这个进程的内存,所以可以通过启动命令的时候 增加 -Xmx -Xms 这类的参数来设置内存的大小。
tomcat是没有单独配置内存大小一说的, 之前的catalina.sh里面设置的内存大小其实也只是针对这个启动进程进行配置。
另外一些tomcat的配置可以在server.tomcat下面进行配置,主要是配置tomcat容器的最大连接数这类的参数。
内置Tomcat参数
server:
tomcat:
accesslog:
enabled: false #打开tomcat访问日志
directory: logs # 访问日志所在的目录
accept-count: #允许HTTP请求缓存到请求队列的最大个数,默认不限制
max-connections: #最大连接数,默认不设置
max-http-post-size: #HTTP POST内容最大长度,默认不限制
max-threads: #最大工作线程数
#端口号
server.port=8081
#最大连接数
server.tomcat.max-connections=200
#最大线程数
server.tomcat.max-threads=300
#编码方式
server.tomcat.uri-encoding=UTF-8
#post提交数据最大大小,设置为0不限制
server.tomcat.max-http-post-size=0
这些参数最终在ServerProperties.Tomcat类中体现
Tomcat是一个静态内部类,其中包含了一下属性
- maxThreads 最大工作线程数
- minSpareThreads 最小工作线程数
- maxHttpPostSize HTTP POST内容最大长度
- internalProxies 受信任IP校验正则表达式
- protocolHeader 协议头,通常设置为X-Forwarded-Proto
- protocolHeaderHttpsValue 协议头的内容,判断是否使用了SSL,默认值是https
- portHeader 用于覆盖原始端口值的HTTP头的名称,默认为X-Forwarded-Port
- redirectContextRoot 对上下文根的请求是否应该通过附加/到路径来重定向
- useRelativeRedirects 设置通过调用sendRedirect生成的HTTP 1.1和后面的位置头是使用相对重定向还是使用绝对重定向
- remoteIpHeader 提取远程IP的HTTP头的名称。例如X-FORWARDED-FOR
- maxConnections 最大连接数,如果一旦连接数到达,剩下的连接将会保存到请求缓存队列里,也就是accept-count指定队列
- maxHttpHeaderSize HTTP消息头的最大值(以字节为单位)
- acceptCount 当所有可能的请求处理线程都在使用时,传入连接请求的最大队列长度
Tomcat拥有一个静态内部类Accesslog,主要用于配置Tomcat访问日志的参数信息
- enabled 是否启用访问日志
- pattern 访问日志的格式化模式,默认为common
- directory 创建日志文件的目录。可以是绝对的或相对于Tomcat的基目录,默认是logs
- prefix 日志文件名称前缀,默认为access_log
- suffix 日志文件名称后缀,默认为.log
- rotate 是否启用访问日志旋转,默认为true
- renameOnRotate 是否推迟将日期戳包含在文件名中直到旋转时间。
- fileDateFormat 日志文件名称中的日期格式,默认为.yyyy-MM-dd。
- requestAttributesEnabled 为请求使用的IP地址、主机名、协议和端口设置请求属性。
- buffered 是否缓冲输出,使其只定期刷新,默认为true
Tomcat还有名为Resource的静态内部类,主要用于配置静态资源缓存的生存周期
启动 jar 设置内存参数
nohup java -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -Xms1024m -Xmx1024m -Xmn256m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC -jar xx.jar >/dev/null 2>&1 &