首页 » Web前端 » responseheadsphp技巧_后端调优根本Tomcat调优

responseheadsphp技巧_后端调优根本Tomcat调优

duote123 2024-11-21 0

扫一扫用手机浏览

文章目录 [+]

<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

responseheadsphp技巧_后端调优根本Tomcat调优

image.png

responseheadsphp技巧_后端调优根本Tomcat调优
(图片来自网络侵删)

通过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());//getAcceptCount()默认是100 } else { //............................省略//设置为壅塞的连接监听通道 serverSock.configureBlocking(true); //............................省略

protected final void startAcceptorThreads() {//Acceptor的线程个数,这个是可以通过配置文件配置的 int count = getAcceptorThreadCount();//创建Acceptor线程 acceptors = new Acceptor[count]; for (int i = 0; i < count; i++) { acceptors[i] = createAcceptor(); String threadName = getName() + "-Acceptor-" + i; acceptors[i].setThreadName(threadName); Thread t = new Thread(acceptors[i], threadName); t.setPriority(getAcceptorThreadPriority()); t.setDaemon(getDaemon());//启动Acceptor线程 t.start(); } }

protected class Acceptor extends AbstractEndpoint.Acceptor { //............................省略 @Override public void run() { //............................省略 while (running) {//计数+1,达到最大值则等待,tomcat设定个最大连接数是10000,达到这个阈值后,就会谢绝连接要求,进行壅塞,这个是用AQS壅塞行列步队实现的 countUpOrAwaitConnection(); SocketChannel socket = null; try {//ServerSocketChannel开始监听连接 socket = serverSock.accept(); //............................省略 if (running && !paused) { if (!setSocketOptions(socket)) {//setSocketOptions设置socket的方法 closeSocket(socket); } //............................省略 private void closeSocket(SocketChannel socket) {//断开连接计数器将会减1 countDownConnection();

protected boolean setSocketOptions(SocketChannel socket) { try { //将监听到的SocketChannel 设置为非壅塞 socket.configureBlocking(false); Socket sock = socket.socket(); //............................省略//注册到ClientPoller的方法 getPoller0().register(channel); //............................省略 }

public void register(final NioChannel socket) { //............................省略 if ( r==null) //封装成PollerEvent,与OP_REGISTER注册事宜绑定 r = new PollerEvent(socket,ka,OP_REGISTER); else r.reset(socket,ka,OP_REGISTER);//添加到行列步队 addEvent(r); }

public static class PollerEvent implements Runnable { //............................省略 @Override public void run() {//注册事宜,我们看到注册事宜实在便是OP_READ读事宜 if (interestOps == OP_REGISTER) { try {//将事宜和通道注册到ClientPoller中的多路复用器中 socket.getIOChannel().register( socket.getPoller().getSelector(), SelectionKey.OP_READ, socketWrapper); ClientPoller

Tomcat8往后的NIO模式比Tomcat7以前刁悍便是由于这个ClientPoller,ClientPoller是实现了Runnable,ClientPoller线程内部有一个jdk原生的Selector工具,也便是NIO的多路复用器。
ClientPoller线程从行列步队SynchronizedQueue中取出PollerEvent逐一启动,启动后PollerEvent将SocketChanel和对应的事宜逐一注册注册到ClientPoller的Selector,Selector找出SocketChanel中就绪的SelectionKey,将SelectionKey和事宜类型交给事情线程Exec进行处理。
全体过程便是范例的NIO实现。
Tomcat默认启动Math.min(2,Runtime.getRuntime().availableProcessors())个ClientPoller线程,绝大部分的情形是2个ClientPoller,也便是两个Selector须要处理成千上万的事宜,非常繁忙

Poller的run方法部分代码

Poller的run方法部分代码

//processKey源码大致逻辑,省略详细代码 protected void processKey(SelectionKey sk, NioSocketWrapper attachment) { //............................省略 if ( close ) { //............................省略 } else if ( sk.isValid() && attachment != null ) { if (sk.isReadable() || sk.isWritable() ) { // 写事宜 if ( attachment.getSendfileData() != null ) { processSendfile(sk,attachment, false); } else { if (sk.isReadable()) { //读事宜 if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) { closeSocket = true; } } if (!closeSocket && sk.isWritable()) { // 写事宜 if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) { closeSocket = true; } } if (closeSocket) { ............................ // 关闭通道 } ..................................}NioBlockingSelector.BlockPoller

NioBlockingSelector紧张处理socketChanel的写操作,也便是servlet的回写过程,NioBlockingSelector有两个工具BlockPoller和Selector叫做sharedSelector。
BlockPoller中也有一个Selector工具,这个Selector紧张是在blockingSelector.write时如果涌现写失落败就把socketChanel注册到BlockPoller的Selector不在占用ClientPoller的韶光片,然后就利用CountDownLatch进行壅塞这是Tomcat默认的写操作过程,在BlockPoller的Selector注册的socketChanel往后的读写操作都是由这个Selector壅塞轮询。
同时NioBlockingSelector是NioSelectorPool中一个成员工具,NioSelectorPool中有两个成员工具NioBlockingSelector和一个Selector叫做SHARED_SELECTOR,SHARED_SELECTOR紧张在非默认的写过程中处理由ClientPoller轮询的socketChanel涌现写失落败时,为了节省ClientPoller宝贵的韶光片socketChanel写事宜会注册到SHARED_SELECTOR上,这个SHARED_SELECTOR是叫做辅Selector,值得一提的是NioSelectorPool的SHARED_SELECTOR、NioBlockingSelector的sharedSelector、BlockPoller的Selector都是同一工具,这个辅Selector轮询涌现写事宜失落败的socketChanel,由辅Selector卖力这些socketChanel往后的读写事宜,这样减少线程间的切换,同时还可减轻主Selector的包袱。

public class NioSelectorPool {//SHARED 默认是true protected static final boolean SHARED = Boolean.parseBoolean(System.getProperty("org.apache.tomcat.util.net.NioSelectorShared", "true")); protected NioBlockingSelector blockingSelector; protected volatile Selector SHARED_SELECTOR; //........................省略 public int write(ByteBuffer buf, NioChannel socket, Selector selector, long writeTimeout, boolean block) throws IOException { if ( SHARED && block ) {//block 和SHARED 是默认true,以是写事宜默认走这里 //壅塞写操作 return blockingSelector.write(buf,socket,writeTimeout); } //........................省略 if ( keycount > 0 ) { //only write if we were registered for a write//写操做,cnt -1为失落败 cnt = socket.write(buf); //write the data if (cnt > 0) { continue; }//非壅塞写 if (cnt==0 && (!block)) break; //don't block } if ( selector != null ) { //非壅塞写失落败后重新注册到SHARED_SELECTOR,不占用ClientPoller的韶光片 if (key==null) key = socket.getIOChannel().register(selector, SelectionKey.OP_WRITE); else key.interestOps(SelectionKey.OP_WRITE); } else if (writeTimeout<0) { //SHARED_SELECTOR轮询 keycount = selector.select(); } else { keycount = selector.select(writeTimeout); } }//.....................................................................省略

ublic class NioBlockingSelector { protected Selector sharedSelector; protected BlockPoller poller;//壅塞写 public int write(ByteBuffer buf, NioChannel socket, long writeTimeout) throws IOException { SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); try { while ( (!timedout) && buf.hasRemaining()) { if (keycount > 0) { //only write if we were registered for a write int cnt = socket.write(buf); //write the data written += cnt;//写操做,cnt -1为失落败 if (cnt > 0) { time = System.currentTimeMillis(); //reset our timeout timer continue; //we successfully wrote, try again without a selector } } try { if ( att.getWriteLatch()==null || att.getWriteLatch().getCount()==0) att.startWriteLatch(1);//失落败则重新注册写事宜到BlockPoller 中 poller.add(att,SelectionKey.OP_WRITE,reference);//利用CountDownLatch进行壅塞 if (writeTimeout < 0) { att.awaitWriteLatch(Long.MAX_VALUE,TimeUnit.MILLISECONDS); } else { att.awaitWriteLatch(writeTimeout,TimeUnit.MILLISECONDS); } }Exec

Exec是一个线程池很多博客叫它为Work,默认的线程名称是和server.xml中的同等,核心线程默认是10,最大线程数是200,可以通过我们上面的方法配置server.xml文件设置线程的数量,它紧张是获取ClientPoller轮询出来的socketChanel后,做相应的逻辑处理:前辈行三次握手,然后调用Http11Processor的service方法解析HTTP协议,将http协议解析成键值对放入request,终极调用CoyoteAdapter的service方法将request和response传入Tomcat的各种容器中实行servlet的业务逻辑。

image.png

//事情线程实行run处理socketChanel public boolean processSocket(SocketWrapperBase<S> socketWrapper, SocketEvent event, boolean dispatch) { try { if (socketWrapper == null) { return false; } //将Socket封装到这个工具,然后扔给事情线程实行 SocketProcessorBase<S> sc = processorCache.pop(); if (sc == null) { sc = createSocketProcessor(socketWrapper, event); } else { sc.reset(socketWrapper, event); } //事情线程,我们在配置文件中配置的Executor,不配默认是10个。
最大数200 Executor executor = getExecutor(); //事情线程实行事情 if (dispatch && executor != null) { executor.execute(sc); } else { sc.run(); }

//事情线程实行的东西,紧张是三次握手后开始解析HTTP,然后关闭socket,省略部分代码 protected class SocketProcessor extends SocketProcessorBase<NioChannel> { public SocketProcessor(SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) { super(socketWrapper, event); } @Override protected void doRun() {if (handshake == 0) {//三次握手已完成 SocketState state = SocketState.OPEN; // Process the request from this socket if (event == null) { state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ); } else { state = getHandler().process(socketWrapper, event); } if (state == SocketState.CLOSED) { close(socket, key); }..........................

//逻辑处理紧张是调用了这给ConnectionHandler处理socket的数据包 protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {//省略 ............................................... //处理socket数据包,将HTTP其解析成request 工具,传给Tomcat容器 @Override public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {//省略 ............................................... do {//省略 ............................................... state = processor.process(wrapper, status);//真正连续数据包的方法,这个processor是AbstractProcessorLight 类型的,但是process方法紧张是调用子类Http11Processor类实现的service进行处理//省略 ............................................... } }}

点进process方法,里面调用了service

public abstract class AbstractProcessorLight implements Processor { @Override public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)//省略 ............................................... throws IOException { } else if (status == SocketEvent.OPEN_READ) {//这里是调用Http11Processor 的service方法 state = service(socketWrapper); }//省略 ...............................................

Http11Processor 的service方法进行系列的解析各种

public class Http11Processor extends AbstractProcessor {//省略 ............................................... @Override public SocketState service(SocketWrapperBase<?> socketWrapper) throws IOException {//省略 ............................................... //经由一系列的解析和设置后,将http的各种信息都存放到request中调用CoyoteAdapter的service方法将request, response通报到Tomcat容器getAdapter().service(request, response);//省略 ............................................... }}

Tomcat线程模型组件类的构造图

Tomcat线程模型动态图

NioEndpoint组件

NioEndpoint是Tomcat的NIO关键的类,要理解tomcat的nio最紧张便是对NioEndpoint的理解

image.png

有空得自己去看看《Tomcat的内核设计阐发》

image.png

NioEndpoint它一共包含LimitLatch、Acceptor、Poller、SocketProcessor、Excutor5个部分。
LimitLatch是连接掌握器,它卖力掩护连接数的打算,nio模式下默认是10000,达到这个阈值后,就会谢绝连接要求。
Acceptor卖力吸收连接,默认是1个线程来实行,将要求的事宜注册到事宜列表。
有Poller来卖力轮询,Poller线程数量是cpu的核数Math.min(2,Runtime.getRuntime().availableProcessors())。
由Poller姑息绪的事宜天生SocketProcessor同时交给Excutor去实行。
Excutor线程池的大小便是我们在Connector节点配置的maxThreads的值。
在Excutor的线程中,会完成从socket中读取http request,解析成HttpServletRequest工具,分派到相应的servlet并完成逻辑,然后将response通过socket发回client。
在从socket中读数据和往socket中写数据的过程,并没有像范例的非壅塞的NIO的那样,注册OP_READ或OP_WRITE事宜到主Selector,而是直接通过socket完成读写,这时是壅塞完成的,但是在timeout掌握上,利用了NIO的Selector机制,但是这个Selector并不是Poller线程掩护的主Selector,而是BlockPoller线程中掩护的Selector,称之为辅Selector

NioEndpoint Nio的时序图

Tomcat文件传输sendfile零拷贝:

在普通的输入输出流进行读写时,实际上是进行了多次高下文切换,运用读取数据时,先在内核态将数据从磁盘读取到内核缓存,再切换到用户态将数据从内核缓存读取到用户缓存,在用户态对数据进行加工,然后再从用户态切换回内核态,将用户缓存数据拷贝到内核缓存中,然后读到socket中再到网卡

sendfile本色是linux系统中一项优化技能,用以发送文件和网络通信时,减少用户态空间与磁盘倒换数据,而直接在内核级做数据拷贝,在Tomcat中是可以利用sendfile对一些静态数据如:图片、文件等进行传输,这个sendfile是在Tomcat是默认打开的,可以有效的提高Tomcat的传输性能

零拷贝

compression文件压缩:

compression可以对传输文件进行压缩有效办理文件传输的带宽问题,在Tomcat不支持图片压缩,由于要进行上层的用户态数据加工以是与sendfile互斥,Tomcat默认关闭,开启的话Tomcat会调用Filter利用jdk解压缩流进行解压缩

//源码中compression支持的压缩格式中没有图片 private String compressibleMimeType = "text/html,text/xml,text/plain,text/css," + "text/javascript,application/javascript,application/json,application/xml";Accept-Encoding 和Content-Encoding

Accept-Encoding 和Content-Encoding是HTTP中用来对采取哪种编码格式传输正文进行协定的一敌人部字段。
浏览器发送要求时,会在Request-heads携带Accept-Encoding会解释自己支持的编码列表,做事端在吸收到要求后,从中挑选出一种用来对相应信息进行编码,并通过Response-heads携带Content-Encoding来解释做事端选择的编码信息,浏览器在拿到相应正文后,依据Content-Encoding进行解压。
绝大部分是gzip格式

Tomcat主要配置参数server.xml

自定义线程池我们上面讲过了,现在有了一定的根本更好先容了

Executor标签是专门配置Exec线程池的,专门用于处理多路复用器通报进来的socketChanel,我们上面先容过了

<Executor name="tomcatThreadPool" namePrefix="tzb-nb-" maxThreads="1000" minSpareThreads="30" maxIdleTime="60000" maxQueueSize="1000000" className="org.apache.catalina.core.StandardThreadExecutor"/>

name:线程池名称,用于 Connector中指定。
namePrefix:所创建的每个线程的名称前缀。
maxThreads:池中最大线程数。
minSpareThreads:核心池线程数。
maxIdleTime:线程空闲韶光,超过该韶光后,非核心线程会被销毁,默认值为6000(1分钟),单位毫秒。
maxQueueSize:在被实行前最大线程排队数目,任务数超出会实行谢绝策略,默认为Int的最大值 className:线程池实现类,未指定情形下,默认实现类为org.apache.catalina.core.StandardThreadExecutor。
如果想利用自定义线程池首先须要实现 org.apache.catalina.Executor接口。
Connector用于配置Tomcat运行模式、Acceptor、CilentPoller、sendfile、是否开启文件压缩

<Connector port="8080" protocol="HTTP/1.1" maxThreads="1000" minSpareThreads="100" acceptorThreadCount="2" acceptCount="1000" maxConnections="1000" connectionTimeout="20000" maxHttpHeaderSize="8192" compression="on" compressionMinSize="2048" redirectPort="8443" URIEncoding="UTF-8" />

我只列出几个故意思的

port:代表Tomcat监听端口,也便是网站的访问端口,默认为8080,可以根据须要改成其他。
protocol:运行模式,可选类型有四种,分别为BIO,NIO,AIO和APR。
protocol="org.apache.coyote.http11.Http11NioProtocol" //NIO protocol="org.apache.coyote.http11.Http11Nio2Protocol" //AIO protocol="org.apache.coyote.http11.Http11AprProtocol" //ARPacceptCount:便是Acceptor线程事情时通道的长度也便是前面说的SynchronizedStack,当要求PollerEvent超出行列步队时要求就会被谢绝,默认是100。
一样平常是设置的跟 maxThreads一样或一半,此值设置的过大会导致排队的要求超时而未被处理。
以是这个值该当是紧张根据运用的访问峰值与均匀值来权衡配置。
acceptorThreadCount:Acceptor线程的数量,默认是1,如果在多核CPU架构下,此值可以设置为2,官方不建议设定超过2个的值。
maxConnections:tomcat最大连接数也便是上面说的LimitLatch。
NIO默认是10000,超出则Acceptor线程就被壅塞了,即不再行列步队中获取已经建立的连接。
但是它并不阻挡新的连接的建立,新的连接的建立过程不是Acceptor掌握的,Acceptor仅仅是从行列步队中获取新建立的连接。
以是当连接数已经超过maxConnections后,仍旧是可以建立新的连接的,存放在上述acceptCount大小的行列步队中,这个行列步队里面的连接没有被Acceptor获取,就处于连接建立了但是不被处理的状态。
当连接数低于maxConnections之后,Acceptor线程就不再壅塞connectionTimeout:当要求已经被接管,但未被处理,也便是等待中的超时时间。
单位为毫秒,默认值为60000。
executor:便是把executor标签的内容引过来,不要它的话可以把executor的内容复制到这里URIEncoding:URL编码字符集。
pollerThreadCount:ClientPoller的线程数,默认为2。
官方不建议设置大于2的值,由于锁的竞争会导致性能低落,事实上一个线程也足够快速。
useSendfile:是否开启sendfile特性,默认为true。
对付web运用而言,常日project中还会包含一定数量的静态资源,比如图片、CSS、js、html等,sendfile在一定程度上可以提高性能。
compression:是否开启压缩,这个属性与useSendfile互斥,useSendfile开启了,这个认关闭,compression是默认关闭的compressionMinSize:如果compression="on",则启用此项。
被压缩前数据的最小值,也便是超过这个值后才被压缩。
如果没有指定,这个属性默认为“2048”(2K),单位为byte。
实战:

image.png

我们看到Acceptor线程线程是3个、Client线程是5个,exec线程是15个和我上图的配置同等

image.png

catalina.sh

利用JAVA_OPTS配置JVM参数

//例如:JAVA_OPTS="-Dfile.encoding=UTF-8 -server -Xms2048m -Xmx2048m -XX:NewSize=512m -XX:MaxNewSize=1024m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -XX:+DisableExplicitGC"一样平常说来,您该当利用物理内存的 80% 作为堆大小。
解释:以上两个参数关系到tomcat承受的访问性能,但也要根据做事器实际内存情形设定。
有人建议Xms和Xmx的值取成一样比较好,说是可以加快内存回收速率。
Xms和Xmx这两个值的大小一样平常根据须要进行配置。
初始化堆的大小实行了虚拟机在启动时向系统申请的内存的大小。
一样平常而言,这个参数不主要。
但是有的运用程序在大负载的情形下会急剧地占用更多的内存,此时这个参数便是显得很主要,如果虚拟机启动时配置利用的内存比较小而在这种情形下有许多工具进行初始化,虚拟机就必须重复地增加内存来知足利用。
由于这种缘故原由,我们一样平常把-Xms和-Xmx设为相同大,而堆的最大值受限于系统利用的物理内存。
一样平常利用数据量较大的运用程序会利用持久工具,内存利用有可能迅速地增长。
当运用程序须要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致运用做事崩溃。
因此一样平常建议堆的最大值配置为可用内存的最大值的80%。
其余须要考虑的是Java供应的垃圾回收机制。
虚拟机的堆大小决定了虚拟机花费在网络垃圾上的韶光和频度。
网络垃圾能够接管的速率和运用有关,该当通过剖析实际的垃圾网络的韶光和频率来调度。
如果堆的大小很大,那么完备垃圾网络就会很慢,但是频度会降落。
如果您把堆的大小和内存的须要同等,完备网络就很快,但是会更加频繁。
调度堆大小的的目的是最小化垃圾网络的韶光,以在特定的韶光内最大化处理客户的要求。
在基准测试的时候,为确保最好的性能,要把堆的大小设大,确保垃圾网络不在全体基准测试的过程中涌现。
如果系统花费很多的韶光网络垃圾,请减小堆大小。
一次完备的垃圾网络该当不超过 3-5 秒。
如果垃圾网络成为瓶颈,那么须要指定代的大小,检讨垃圾网络的精密输出,研究 垃圾网络参数对性能的影响。
一样平常说来,您该当利用物理内存的 80% 作为堆大小。
当增加处理器时,记得增加内存,由于分配能够并行进行,而垃圾网络不是并行的。
Tomcat压力测试

利用jmeter可以进行对程序进行压力测试,根据用户的并发,调度Tomcat的线程数量

image.png

我利用一千个线程,一次并发一千,循环十次

image.png

紧张看吞吐量,根据吞吐量逐步调试Tomcat的线程设置

image.png

学习更多JAVA知识与技巧,关注与私信博主(学习)

相关文章

介绍百度码,技术革新背后的智慧之光

随着科技的飞速发展,互联网技术已经成为我们生活中不可或缺的一部分。而在这个信息爆炸的时代,如何快速、准确地获取信息,成为了人们关注...

Web前端 2025-01-03 阅读1 评论0

介绍皮箱密码,开启神秘之门的钥匙

皮箱,作为日常生活中常见的收纳工具,承载着我们的珍贵物品。面对紧闭的皮箱,许多人却束手无策。如何才能轻松打开皮箱呢?本文将为您揭秘...

Web前端 2025-01-03 阅读1 评论0

介绍盗号器,网络安全的隐忧与应对步骤

随着互联网的快速发展,网络安全问题日益突出。盗号器作为一种非法工具,对网民的个人信息安全构成了严重威胁。本文将深入剖析盗号器的原理...

Web前端 2025-01-03 阅读1 评论0