外置的Tomcat

SpringBoot内置Tomcat

Tomcat的启动

有了内嵌的tomcat,我们就不需要去启动tomcat了,可以在自己的项目中去new一个tomcat,spring-boot就是这样。

代码入口

org.springframework.context.support.AbstractApplicationContext#refresh
这个方法是spring启动的核心方法
image.png
image.png
其中着重需要注意的是onRefresh方法,这个方法在spring的单独环境是没有用的,但是在springboot-web中,它的实现容器是AnnotationConfigServletWebServerApplicationContext,它的父类
ServletWebServerApplicationContext重写了这个方法,这个方法实现了tomcat的启动
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh很简单,直接创建webServer,这里不一定是tomcatServer,如果你引入了其他的Server,则创建其他的
image.png
image.png
创建tomcat,下面这个代码就很简单了,直接new一个tomcat,然后设置一些属性,包装到webServer中。
image.png
repository\org\springframework\boot\spring-boot\2.0.4.RELEASE\spring-boot-2.0.3.RELEASE.jar
image.png
image.png

默认配置

SpringBoot中如果使用内嵌Tomcat,那么内嵌Tomcat的默认配置在ServerProperties(org.springframework.boot.autoconfigure.web)中
image.png
image.png
image.png

  1. /**
  2. * Tomcat properties.
  3. */
  4. public static class Tomcat {/**
  5. * Maximum amount of worker threads.最大的工作线程数,默认为200,只能最多有200个耗时(比如查数据库)操作同时进行,一般小型应用中,达不到200个并发耗时操作。
  6. */
  7. private int maxThreads = 200;
  8. /**
  9. * Minimum amount of worker threads.最小工作线程数,默认为10,即初始化时会创建10个线程用于处理请求。
  10. */
  11. private int minSpareThreads = 10;/**
  12. * Maximum number of connections that the server accepts and processes at any
  13. * given time. Once the limit has been reached, the operating system may still
  14. * accept connections based on the "acceptCount" property.      Tomcat在给定时间(同一时间)能接受的最大连接数。
  15. */
  16. private int maxConnections = 10000;
  17. /**
  18. * Maximum queue length for incoming connection requests when all possible request
  19. * processing threads are in use.当前连接数超过maxConnections时,还能接受的连接的数量(排队的数量)。
  20. */
  21. private int acceptCount = 100;
  22. }

内嵌Tomcat使用的默认协议为NIO,配置在TomcatServletWebServerFactory类中,如下:

  1. public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory
  2. implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {
  3. private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
  4. private static final Set<Class<?>> NO_CLASSES = Collections.emptySet();
  5. /**
  6. * The class name of default protocol used.协议的默认配置
  7. */
  8. public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";
  9. private File baseDirectory;
  10. ........
  11. }

总结:
SpringBoot 内置的Tomcat采用 NIO 协议,配置的参数为server.tomcat.maxThreads 200server.tomcat.maxConnections 1000server.tomcat.acceptCount 100。 理论上来讲同一时刻可以处理200个请求(200个线程处理200个耗时操作),但其实可以同时接受10000个请求连接,以及大于10000个连接时,还可以再等待100个连接。

Tomcat启动流程

SpringBoot启动流程

Tomcat优化

jvm运行参数

  1. JAVA_OPTS="-Xms2048m -Xmx2048m -Xss512k"
  2. -Xms:初始Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
  3. -XmxJava heap最大值,使用的最大内存
  4. 上面两个值是分配JVM的最小和最大内存,取决于硬件物理内存的大小,建议均设为物理内存的一半。
  5. -XX:PermSize:设定内存的永久保存区域
  6. -XX:MaxPermSize:设定最大内存的永久保存区域
  7. -XX:MaxNewSize:
  8. -Xss 15120 这使得JBoss每增加一个线程(thread)就会立即消耗15M内存,而最佳值应该是128K,默认值好像是512k.
  9. +XX:AggressiveHeap 会使得 Xms没有意义。这个参数让jvm忽略Xmx参数,疯狂地吃完一个G物理内存,再吃尽一个Gswap
  10. -Xss:每个线程的Stack大小
  11. -verbose:gc 现实垃圾收集信息
  12. -Xloggc:gc.log 指定垃圾收集日志文件
  13. -Xmnyoung generationheap大小,一般设置为Xmx34分之一
  14. -XX:+UseParNewGC :缩短minor收集的时间
  15. -XX:+UseConcMarkSweepGC :缩短major收集的时间
  16. 提示:此选项在Heap Size 比较大而且Major收集时间较长的情况下使用更合适。

SpringBoot中的Tomcat

springboot只是内嵌了tomcat而已, 所以使用的内存其实就是springboot这个进程的内存,所以可以通过启动命令的时候 增加 -Xmx -Xms 这类的参数来设置内存的大小。
tomcat是没有单独配置内存大小一说的, 之前的catalina.sh里面设置的内存大小其实也只是针对这个启动进程进行配置。
另外一些tomcat的配置可以在server.tomcat下面进行配置,主要是配置tomcat容器的最大连接数这类的参数。

内置Tomcat参数

  1. server:
  2. tomcat:
  3. accesslog:
  4. enabled: false #打开tomcat访问日志
  5. directory: logs # 访问日志所在的目录
  6. accept-count: #允许HTTP请求缓存到请求队列的最大个数,默认不限制
  7. max-connections: #最大连接数,默认不设置
  8. max-http-post-size: #HTTP POST内容最大长度,默认不限制
  9. max-threads: #最大工作线程数
  1. #端口号
  2. server.port=8081
  3. #最大连接数
  4. server.tomcat.max-connections=200
  5. #最大线程数
  6. server.tomcat.max-threads=300
  7. #编码方式
  8. server.tomcat.uri-encoding=UTF-8
  9. #post提交数据最大大小,设置为0不限制
  10. 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 &

参考资料