后端调优基础——Tomcat调优

本文详细探讨了Tomcat的四种运行模式,重点讲解了NIO模式,并介绍了配置优化,包括禁用ajp协议、自定义线程池以及监控工具的使用。通过实例展示了如何修改server.xml以优化Tomcat的性能,包括调整Executor线程池和连接器配置。此外,还讨论了sendfile零拷贝技术和文件压缩,以及Tomcat的重要配置参数和压力测试方法。
摘要由CSDN通过智能技术生成

jdk8和Tomcat8.5是JDK和Tomcat的史诗级提升,直接把单车变跑车,所以如果你还是使用的jdk7和Tomcat8.5以后的版本,那可以考虑去线上换一下,但是不知道到时是架构师打死你还是你打死架构师

Tomcat的四种运行模式:

  • BIO:同步阻塞模式,Tomcat7及之前默认的模式,性能最差,Tomcat8.5后已抛弃
  • NIO:同步非阻塞模式,Tomcat8及之后默认的模式,性能高,现在的主流模式
  • AIO:异步非阻塞模式,由于纯异步,性能最高
  • APR:需要额外安装依赖库,从操作系统级别解决异步IO,大幅度的提高服务器的处理和响应性能,也是Tomcat运行高并发应用的首选模式,但是使用困难,依赖系统的底层网络包,团队没有C++大神和熟悉Linux底层的大神还是别拿出来秀了

主流是NIO模式,我们主要学习NIO模式的

配置优化

server status

通过配置可以看到Tomcat管理页server status,利用server status帮我们获取Tomcat的信息
我们需要修改一下配置文件,conf/tomcat-users.xml和
webapps/manager/META-INF/context.xml。
找到conf/tomcat-users.xml

<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<user username="tzb" password="123456" roles="manager-gui,admin-gui,manager-script,manager-jmx,manager-status"/>

找到
webapps/manager/META-INF/context.xml,将以下内容注释掉,我已经注释掉了,这样就能远程访问web manager了:

image.png

image.png

通过server status可以看到jvm的信息,还要很多的选项可供,例如应用程序列表、JVM信息、NIO模型等

image.png

禁用ajp协议

ajp协议是基于TCP协议的,Tomct使用ajp协议主要是为了连接http apache服务器的,http apache这个服务器已经被Ngnix完爆了,如果没有什么特殊癖好的话应该没人会用它了,但是这个配置会在程序中默认跑着十个线程,所以为了性能把这个没用的功能去除,如果不是2020年2月以后下载的Tomcat的话,是没有默认禁用的,所以需要手动禁掉

我的Tomcat是默认禁止的,我在配置中开启了ajp,我们看到这里跑了十个线程,跑了线程又用不到,浪费CUP的性能

image.png

在conf/server.xml中把这个配置注释了就禁止掉ajp了(如果你有特殊的癖好,想打开ajp,就把注释打开, 并且把secretRequired="true"修改为secretRequired="")

image.png

重启服务器,查看server status,ajp已经没有了

image.png

自定义Tomcat线程池

Tomcat需要给每一个请求创建线程,Tomcat默认的线程池最大线程数是200,核心线程数是10,如何并发高的场景,Tomcat就得不断的创建和销毁线程,所以就得自定义线程池提高核心线程数,这样可以帮助我们提高性能。但是如果不是是连接请求特别多的场景,最后别乱改,核心线程是需要占用内存的

先看看我们没修改前的状态,我使用Jvisualvm工具监控Tomcat的线程状态,我们看到这里默认是十个线程,由于我用的是Tomcat8.5所以运行模式默认是nio模式,线程的前缀是exec,记住这个名字后面用到的

image.png

修改server.xml文件,打开Executor的注释,我配置的参数是:最大线程数150,核心线程数15,线程池名称,每个线程的前缀。
为了区别,我把线程的前缀改为tzb-nb-,接着把默认的连接器配置注释掉,打开下面的连接器,让自定义的连接线程池生效

image.png

image.png

重启服务器,查看Jvisualvm,我们看到连接池已经生效了,整好十五个

image.png

Tomcat线程模型

我们主要讲Tomcat8后的NIO,因为NIO才是主流,Tomcat的线程有很多,主线程叫做main是负责启动和关闭

Tomcat的主要线程

看监控工具可以看到Tomcat的主要线程

Tomcat的主要线程

  • Acceptor

使用NIO的原生ServerSocketChannel的accept()方法监听客户的连接请求,但是这个ServerSocketChannel是设置阻塞的,所以当没有连接请求来时,线程会阻塞在accept方法上。ServerSocketChannel设置的TCP连接队列大小默认是100,TCP连接队列就是把当前连接信息存放到全连接队列中,队列中的连接信息等待ServerSocket.accpt()处理,Acceptor队列由acceptCount控制,但是Tomcat保持的通道数默认是10000,也就是ServerSocket.accpt()进去的通道Tomcat能保持10000个,由maxConnections控制。然后将ServerSocket.accpt()监听获取到的客户端通道SocketChanel设置为非阻塞,同时将SocketChanel和注册事件封装成一个PollerEvent对象扔进队列SynchronizedStack中,SynchronizedStack内部是数组,然后队列里的PollerEvent等待Poller线程来注册处理,Poller线程内部就是使用了NIO中的Selector多路复用器,PollerEvent对象主要是装载了SocketChanel和注册事件OP_REGISTER在Poller内部其实就是给Selector注册OP_READ,PollerEvent其实本身也是个线程。Poller线程是队列的消费者,Acceptor是生产者。这个Acceptor线程默认只有1个,但是可以在Tomcat中配置数量

 public void bind() throws Exception {
        if (!getUseInheritedChannel()) {
//Acceptor的ServerSocketChannel
            serverSock = ServerSocketChannel.open();
            socketProperties.setProperties(serverSock.socket());
            InetSocketAddress addr = (getAddress()!=null?
new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
            serverSock.socket().bind(addr,getAcceptCount())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值