tomcat 性能调优


tomcat 性能调优

              

                           

***************

tomcat 调优

                             

ServerProperties:server 配置,直接在配置文件(application.yml)中设置

@ConfigurationProperties(
    prefix = "server",
    ignoreUnknownFields = true
)
public class ServerProperties {
    private Integer port;
    private InetAddress address;
    @NestedConfigurationProperty
    private final ErrorProperties error = new ErrorProperties();
    private ServerProperties.ForwardHeadersStrategy forwardHeadersStrategy;
    private String serverHeader;
    private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8L);
    private Shutdown shutdown;
    @NestedConfigurationProperty
    private Ssl ssl;
    @NestedConfigurationProperty
    private final Compression compression;
    @NestedConfigurationProperty
    private final Http2 http2;
    private final ServerProperties.Servlet servlet;
    private final ServerProperties.Reactive reactive;
    private final ServerProperties.Tomcat tomcat;
    private final ServerProperties.Jetty jetty;
    private final ServerProperties.Netty netty;
    private final ServerProperties.Undertow undertow;

*********
内部类:Tomcat

    public static class Tomcat {
        private final ServerProperties.Tomcat.Accesslog accesslog = new ServerProperties.Tomcat.Accesslog();
        private final ServerProperties.Tomcat.Threads threads = new ServerProperties.Tomcat.Threads();
        private File basedir;
        @DurationUnit(ChronoUnit.SECONDS)
        private Duration backgroundProcessorDelay = Duration.ofSeconds(10L);
        private DataSize maxHttpFormPostSize = DataSize.ofMegabytes(2L);
        private DataSize maxSwallowSize = DataSize.ofMegabytes(2L);
        private Boolean redirectContextRoot = true;
        private boolean useRelativeRedirects;
        private Charset uriEncoding;
        private int maxConnections;
        private int acceptCount;
        private int processorCache;
        private Duration keepAliveTimeout;
        private int maxKeepAliveRequests;
        private List<String> additionalTldSkipPatterns;
        private List<Character> relaxedPathChars;
        private List<Character> relaxedQueryChars;
        private Duration connectionTimeout;
        private boolean rejectIllegalHeader;
        private final ServerProperties.Tomcat.Resource resource;
        private final ServerProperties.Tomcat.Mbeanregistry mbeanregistry;
        private final ServerProperties.Tomcat.Remoteip remoteip;

        public Tomcat() {
            this.uriEncoding = StandardCharsets.UTF_8;
            this.maxConnections = 8192;
            this.acceptCount = 100;
            this.processorCache = 200;
            this.maxKeepAliveRequests = 100;
            this.additionalTldSkipPatterns = new ArrayList();
            this.relaxedPathChars = new ArrayList();
            this.relaxedQueryChars = new ArrayList();
            this.rejectIllegalHeader = true;
            this.resource = new ServerProperties.Tomcat.Resource();
            this.mbeanregistry = new ServerProperties.Tomcat.Mbeanregistry();
            this.remoteip = new ServerProperties.Tomcat.Remoteip();
        }

            

application.yml:server 默认配置

server:
  tomcat:
    max-connections: 8192
    accept-count: 100
    processor-cache: 200
    max-http-form-post-size: 2MB
    max-swallow-size: 2MB
    max-keep-alive-requests: 100
    keep-alive-timeout: 2000
    connection-timeout: 2000
    threads:
      max: 200
      min-spare: 10


# server.tomcat.max-connections:服务器最大连接数,默认为8192
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
服务器任意时间可接收并处理的最大连接数,当接到的请求数超过该值时,
服务器仍然会接受acceptCount个连接请求,但是不会处理

# server.tomcat.accept-count:服务器请求等待队列,默认为100
Maximum queue length for incoming connection requests when all possible 
request processing threads are in use
最大的请求等待队列数

# server.tomcat.processor-cache:最大缓存的processor数,默认为200
Maximum number of idle processors that will be retained in the cache and reused 
with a subsequent request. When set to -1 the cache will be unlimited with a 
theoretical maximum size equal to the maximum number of connections
缓存中最大缓存的空闲processor数,这些processor可用来处理后续的请求
设置为-1表示缓存数不设限,理论上等于最大连接数


# server.tomcat.max-http-form-post-size:post表单请求体的最大值,默认为2MB
Maximum size of the form content in any HTTP post request

# server.tomcat.max-swallow-size:请求体最大大小,默认为2MB,
                                  如果请求体(如上传文件时)超过2MB,可调大该参数
Maximum amount of request body to swallow


# server.tomcat.max-keep-alive-requests:一个keep-alive连接最多处理的请求数,达到该数后,关闭连接
Maximum number of HTTP requests that can be pipelined before the connection is 
closed. When set to 0 or 1, keep-alive and pipelining are disabled. When set to 
-1, an unlimited number of pipelined or keep-alive requests are allowed
一个连接最多处理的http请求数,当达到该数值后,就关闭该连接;
当设置0或者1,keep-alive和pipeline功能就关闭;
当设置为-1,pipelined、keep-alive请求不设限

# server.tomcat.keep-alive-timeout:长连接处理完一条请求,等待下一条请求的最长时间,超过该时间,连接关闭
Time to wait for another HTTP request before the connection is closed. When not 
set the connectionTimeout is used. When set to -1 there will be no timeout
长连接(keep-alive connection)接受另一个请求的最长等待时间,超过该时间,连接关闭;
设置为-1,连接没有超时时间,长时间有效

# server.tomcat.connection-timeout:连接在一次请求中等待接收数据的最长时间,超过该时间,连接关闭
Amount of time the connector will wait, after accepting a connection, for 
the request URI line to be presented
连接建立后,服务端等待获取数据的最长时间,超过该时间,连接关闭


# server.tomcat.threads.max:tomcat最大工作线程数,默认为200
Maximum amount of worker threads

# server.tomcat.threads.min-spare:tomcat最小工作线程数,默认为10
Minimum amount of worker threads

            

                                  

Connector:连接配置,可在TomcatServletWebServeraFactory自定义

public class Connector extends LifecycleMBeanBase {
    private static final Log log = LogFactory.getLog(Connector.class);
    public static final boolean RECYCLE_FACADES = Boolean.parseBoolean(System.getProperty("org.apache.catalina.connector.RECYCLE_FACADES", "false"));
    public static final String INTERNAL_EXECUTOR_NAME = "Internal";
    protected Service service;
    protected boolean allowTrace;
    protected long asyncTimeout;
    protected boolean enableLookups;
    protected boolean xpoweredBy;
    protected String proxyName;
    protected int proxyPort;
    protected boolean discardFacades;
    protected int redirectPort;
    protected String scheme;
    protected boolean secure;
    protected static final StringManager sm = StringManager.getManager(Connector.class);
    private int maxCookieCount;        //cookie最长长度,默认为200
    protected int maxParameterCount;   //parameter最长长度,默认为10000
    protected int maxPostSize;         //请求体最大大小,默认为2097152(2M)
    protected int maxSavePostSize;     //post表单最大大小,默认为4KB
    protected String parseBodyMethods;
    protected HashSet<String> parseBodyMethodsSet;
    protected boolean useIPVHosts;
    protected final String protocolHandlerClassName;
    protected final ProtocolHandler protocolHandler;  //连接协议,通过协议设置i/o方式(nio、nio2等)
    protected Adapter adapter;
    private Charset uriCharset;
    private EncodedSolidusHandling encodedSolidusHandling;
    protected boolean useBodyEncodingForURI;

    public Connector() {
        this("HTTP/1.1");
    }

                   

TomcatServletWebServerFactory自定义connector属性

@Configuration
public class WebConfig {

    @Bean
    public ServletWebServerFactory initServletWebServerFactory(){
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.addConnectorCustomizers(connector -> {
            connector.setMaxCookieCount(200);
            connector.setMaxPostSize(4*1024*1024);
            connector.setMaxSavePostSize(4*1024*1024);
            connector.setMaxParameterCount(10000);
        });

        factory.setProtocol(Http11Nio2Protocol.class.getName());
        return factory;
    }
}

               

自定义配置后启动日志

2021-12-30 09:57:31.796  INFO 1068 --- [           main] com.example.dmeo.DmeoApplication         : Starting DmeoApplication using Java 16 on hudeMacBook-Pro.local with PID 1068 (/Users/huli/IdeaProjects/springboot hello/target/classes started by huli in /Users/huli/IdeaProjects/springboot hello)
2021-12-30 09:57:31.799  INFO 1068 --- [           main] com.example.dmeo.DmeoApplication         : No active profile set, falling back to default profiles: default
2021-12-30 09:57:32.503  INFO 1068 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-12-30 09:57:32.511  INFO 1068 --- [           main] o.a.coyote.http11.Http11Nio2Protocol     : Initializing ProtocolHandler ["http-nio2-8080"]
2021-12-30 09:57:32.512  INFO 1068 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-12-30 09:57:32.512  INFO 1068 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2021-12-30 09:57:32.571  INFO 1068 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-12-30 09:57:32.572  INFO 1068 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 737 ms
2021-12-30 09:57:32.766  INFO 1068 --- [           main] o.a.coyote.http11.Http11Nio2Protocol     : Starting ProtocolHandler ["http-nio2-8080"]
# 协议为:Http1Nio2Protocol,自定义配置生效

2021-12-30 09:57:32.785  INFO 1068 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-12-30 09:57:32.793  INFO 1068 --- [           main] com.example.dmeo.DmeoApplication         : Started DmeoApplication in 1.295 seconds (JVM running for 6.829)

                  

                        

***************

jvm 调优

                     

常用参数:调整tomcat内存

-Xms20m:初始堆空间大小
-Xmx20m:堆空间最大值
-Xmn10m:新生代堆空间大小
-Xss128k:栈空间大小

-XX:InitialHeapSize=20m:初始堆空间大小
-XX:SurvivorRatio=8:新生代eden、survivor比例,默认为8
-XX:PretenureSizeThreshold=10m:对象大小超过10m直接进入老年代
-XX:MaxtenuringThreshold=2:垃圾回收2次后,新生代对象如果还存活,未被回收,进入老年代

                

垃圾收集器:调整tomcat使用的垃圾收集器

单线程垃圾收集器:垃圾回收时,只有一条垃圾回收线程,用户线程停止
并行垃圾收集器:垃圾回收时,有多条垃圾回收线程,用户线程停止,注重吞吐量
并发垃圾收集器:垃圾回收时,用户线程、垃圾回收线程可以同时工作,注重低停顿


# 垃圾收集器参数
-XX:+UseSerialGC:使用serial + serial old组合
-XX:+UseParallelGC:使用parallel scavange + parallel old组合
-XX:+UseG1GC:使用G1垃圾收集器
-XX:+UseZGC:使用ZGC垃圾收集器(ZGC从java15开始正式使用)
说明:parnew垃圾收集器载java10中移除、CMS垃圾收集器在java14中移除


# parallel垃圾收集器参数
-XX:GCTimeRatio=99:垃圾回收时间比率,控制吞吐量
-XX:MaxGCPauseMillis=10:最大停顿时间(毫秒),实际停顿时间可能会超过该值
-XX:+UseAdaptiveSizePolicy:自动调节虚拟机参数(如新生代eden/survivor比值、内存区域大小、对象进入老年代的年龄等)
-XX:ParallelGCThreads=4:并发垃圾回收线程数

            

                    

***************

应用性能优化建议

                 

如果流量较大,应当与web服务器(如nginx)集成,将流量分摊到多台服务器上,降低单台服务器的压力;
如果业务数据量较大,单表存储性能较低,可考虑使用分库分表分摊数据读写压力;
使用线程池(如druid等)管理数据库连接;
数据量较大的情况下,非业务数据考虑使用nosql存储,如mongoDB、es等;
请求量比较大,对数据一致性要求不高的情况下,可考虑使用缓存,如redis缓存;

降低客户端与服务端通信次数,如可考虑将循环单次操作转换为批量操作;
降低请求响应的数据量,不要传递无效数据,减少带宽压力;

会话(session)中不要存储大对象,降低内存开销;
如果session需要存储的数据量很大,可考虑将session外置(默认直接存储在内存),使用redis存储;
考虑降低session的有效期,减少session管理成本;

合理定义对象的作用域,让对象及时回收;
static类型的集合谨慎使用,避免发生内存泄漏;

对日志合理分级:debug日志尽量详细、info日志尽量简单减少输出、warn/error日志方便问题定位
日志内容输出:生产环境输出info及以上级别日志

                  

           

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值