Estou desenvolvendo uma aplicação para aguentar várias requisições ao mesmo tempo.
A aplicação começa por uma servlet, que recebe alguns parâmetros por GET e guarda os parâmetros em um arquivo. Sendo que quando coloquei esta servlet para teste, recebendo 1000 requisições de um outro computador dá erro, quando o loop chega mais ou menos em 970 requisições o tomcat me responde um status 500, erro interno no servidor.
Alguém saberia o que está acontecendo? O tomcat não aguenta o tranco? Se não aguenta, alguém saberia recomendar algum outro servidor open-source?
Ou seria melhor usar um arquivo jsp em vez de uma servlet no tomcat?
1000 requisições, não aquenta?
28 Respostas
o tomcat aguenta, mas o teu servlet aguenta?
você que tem que montar um ambiente que suporte essas 1000 requisições
não é simplesmente cuspir código em um servlet que vai aguentar 1 milhão de requisições/seg
já fizemos testes aqui com struts com mais de 30 mil requisições de crud (cerca de 10/seg) e aguentou (claro, tivemos que aumentar um pouco da memória da jvm)
como montar este ambiente?
A minha servlet é bem simples, recebe uns parâmetros por get, e grava em um arquivo os parâmetros, abre e fecha o arquivo e usa o log4j para fazer uns logs. Coisa bem simples.
Você abre, altera, e fecha o mesmo arquivo a cada requisição? Provavelmente esse é o gargalo, mas o certo mesmo é arranjar uma ferramenta pra fazer o profiling da sua aplicação.
Vou colocar o código da Servlet para vcs darem uma olhada.
Abaixo é o código da Servlet:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import control.Catcher;
public class MainServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
File fileProperties = new File("/usr/local/apache-tomcat-6.0.16/webapps/AppWeb/WEB-INF/config/conf.properties");
FileInputStream fileInputStream = new FileInputStream(fileProperties);
Properties properties = new Properties();
properties.load(fileInputStream);
OpenFile.PATH_TXT = properties.getProperty("PATH_TXT");
OpenFile.PATH_LOG = properties.getProperty("PATH_LOG");
OpenFile.LAYOUT_LOG = properties.getProperty("LAYOUT_LOG");
OpenFile.PREFIX_FILE_LOG = properties.getProperty("PREFIX_FILE_LOG");
fileInputStream.close();
OpenFilecatcher = new OpenFile(request.getRemoteAddr(), request.getQueryString());
OpenFile.saveGetInDisk();
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<p>REQUEST SUCESS</p>");
out.println("</body>");
out.println("</html>");
}
}
Abaixo a classe que servlet abre:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.FileOutputStream;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import util.BrazilCalendar;
public class OpenFile{
private String query;
private String ip;
private File file;
private BrazilCalendar brazilCalendar;
private static final Logger LOGGER = Logger.getLogger(Catcher.class);
public static String PATH_TXT ;
public static String PATH_LOG ;
public static String LAYOUT_LOG = "%d{yyyy-M-dd HH:mm:ss} [%t] %p %c %x - %m%n";
public static String PREFIX_FILE_LOG ;
public OpenFile(){
super();
BasicConfigurator.configure();
PatternLayout patternLayout = new PatternLayout(Catcher.LAYOUT_LOG);
Catcher.LOGGER.setLevel(Level.INFO);
try {
this.brazilCalendar = new BrazilCalendar();
FileAppender fileAppender = new FileAppender(patternLayout, Catcher.PATH_LOG + Catcher.PREFIX_FILE_LOG + this.brazilCalendar.getFullDateForSystem("") + ".log");
OpenFile.LOGGER.addAppender(fileAppender);
OpenFile.LOGGER.info("------- NEW PROCESS -------");
OpenFile.LOGGER.debug("TIME START: " + this.brazilCalendar.getFullDateForSystemWithHour("-"));
} catch (IOException e) {
OpenFile.LOGGER.info("------- NEW PROCESS -------");
OpenFile.LOGGER.error("CANNOT OPEN FILE LOG");
OpenFileOpenFile.LOGGER.error(e.getMessage());
OpenFile.LOGGER.info("------- END PROCESS -------");
}
}
public OpenFile(String query){
this();
this.setQuery(query);
}
public OpenFile(String ip, String query){
this(query);
this.setIp(ip);
}
/**
* @return the query
*/
public String getQuery() {
return query;
}
/**
* @param query the query to set
*/
public void setQuery(String query) {
this.query = query;
OpenFile.LOGGER.info("SET QUERY: " + this.query);
}
/**
* @return the Ip
*/
public String getIp() {
return plexIp;
}
/**
* @param Ip the Ip to set
*/
public void setIp(StringIp) {
this.ip = Ip;
OpenFile.LOGGER.info("SET IP: " + this.Ip);
}
public void saveMoQueueInDisk(){
BrazilCalendar brazilCalendar = new BrazilCalendar();
String fileName = "get" + brazilCalendar.getFullDateForSystem("") + ".txt";
this.file = new File(OpenFile.PATH_TXT + fileName);
if(!this.file.exists()){
try {
this.file.createNewFile();
OpenFile.LOGGER.info("FILE CREATED");
} catch (IOException e) {
OpenFile.LOGGER.error("CANNOT CREATE FILE");
}
}
try { FileOutputStream fileOutputStream = new FileOutputStream(this.file, true);
OpenFile.LOGGER.info("FILE OPEN: " + fileOutputStream.toString());
String forFile = brazilCalendar.getFullDateForSystemWithHour("-") + " " + this.ip + " " + this.query + "\n";
fileOutputStream.write(forFile.getBytes());
fileOutputStream.flush();
fileOutputStream.close();
OpenFile.LOGGER.info("FILE CLOSED: " + fileOutputStream.toString());
Catcher.LOGGER.info("DATA SAVED");
} catch (FileNotFoundException e) {
OpenFile.LOGGER.error("MESSAGE: " + e.getMessage());
OpenFile.LOGGER.error("CAUSE: " + e.getCause());
} catch (IOException e) {
OpenFile.LOGGER.error("MESSAGE: " + e.getMessage());
OpenFile.LOGGER.error("CAUSE: " + e.getCause());
} finally{
OpenFile.LOGGER.debug("END TIME: " + this.brazilCalendar.getFullDateForSystemWithHour("-"));
OpenFile.LOGGER.info("------- END PROCESS -------");
}
}
}
Bom dia Jedi,
Provavelmente seu Tomcat deve estar com os parêmetros default de configuração.
Além de aumentar os parâmetros de memória da JVM como foi dito pelo amigo a pouco, se vc pretende simular um ambiente com o Tomcat recebendo uma carga dessa, poderia pensar tb em por um Apache na frente ;D
Caso você não queira perder muito tempo integrando um Apache HTTP Server e um Tomcat, dê uma olhada aqui:
http://tomcat.apache.org/tomcat-6.0-doc/config/http.html
Acredito que ajude 
IO é uma das operações mais caras, uma idéia seria criar um buffer para estas escritas em arquivo, assim não iria bloquear a requisição.
como posso aumentar a memória da jvm? E sim está tudo default…
E vou mudar de IO para buffer…muito obrigado pela dica…
Deixe seus properties em memória. (economiza IO)
Utilize uma maneira melhor de escrever esse arquivo(de preferencia não escreva em arquivo a cada requisição).
Se for utilizar arquivos mesmo, utilize NIO.
Transfira o máximo de dados possíveis para a memória(cache) para aumentar a sua performance
.
Tente diminuir ao máximo a criação de objetos por requisição.
Teria como criar um conexão com um arquivo uma única vez?
Por exemplo, a primeira requisição foi feita, o arquivo foi aberto e ai deixá-se a conexão em memória, para que as próximas requisições possoam usar a mesma conexão, depois de um certo tempo da conexão não sendo usada fechá-se a mesma.
de IO para buffer, mas mesmo assim está dando erro.
Acho que o problema é a configuração do tomcat, como posso configurá-lo para um ambiente de produção? aonde encontro algum tutorial de configuração?
Aproveitando…
onde aqui no GUJ ocorreu esses testes?
existe algum post?
normalmente eu configuro a Jvm aumentando a memória, mas como disse o Leozin, minha aplicação 'código"
deve está preparada p isso? como?
abraços
Seu tomcat está configurado pra receber quantas conexões ?
[]'s
Aonde posso ver esta informação?
Aqui:
http://tomcat.apache.org/tomcat-6.0-doc/config/http.html
Vc configura essas propriedades no arquivo server.xml.
Algo +/- assim:
<!-- A HTTP/1.1 Connector on port 8080 -->
<Connector port="8080" ...
maxThreads="250" ...
acceptCount="100" ... />
[]'s
Só para informar, tirei a parte do código que grava os dados em um arquivo e mesmo assim quando chega na requisição 950 dá erro…
E como estão aquelas configurações que eu falei ?
na server.xml está assim:
<Connector port="8080" executor="tomcatThreadPool" protocol="HTTP/1.1"
connectionTimeout="20000" maxThreads="150"
acceptorThreadCount="2" redirectPort="8443" socket.directBuffer="false"/>
Tenta aumentar esse maxthreads aí e fazer o teste novamente.
Agora o server.xml está assim:
<Connector port="8080" executor="tomcatThreadPool" protocol="HTTP/1.1"
connectionTimeout="20000" maxThreads="1000"
acceptorThreadCount="2" redirectPort="8443" socket.directBuffer="false"/>
Deu um aumento nas requisições que ele passou a aceitar, mas muito pouco, foi de 950 para 976 :?
E vou colocar também os erros que eu achei no log:
- no catalina.out
Feb 19, 2008 1:29:33 PM org.apache.coyote.http11.Http11Protocol init
SEVERE: Error initializing endpoint
java.net.BindException: Address already in use:8080
at org.apache.tomcat.util.net.JIoEndpoint.init(JIoEndpoint.java:501)
at org.apache.coyote.http11.Http11Protocol.init(Http11Protocol.java:176)
at org.apache.catalina.connector.Connector.initialize(Connector.java:1058)
at org.apache.catalina.core.StandardService.initialize(StandardService.java:677)
at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:795)
at org.apache.catalina.startup.Catalina.load(Catalina.java:530)
at org.apache.catalina.startup.Catalina.load(Catalina.java:550)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:260)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)
Feb 19, 2008 1:29:33 PM org.apache.catalina.startup.Catalina load
SEVERE: Catalina.start
LifecycleException: Protocol handler initialization failed: java.net.BindException: Address already in use:8080
at org.apache.catalina.connector.Connector.initialize(Connector.java:1060)
at org.apache.catalina.core.StandardService.initialize(StandardService.java:677)
at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:795)
at org.apache.catalina.startup.Catalina.load(Catalina.java:530)
at org.apache.catalina.startup.Catalina.load(Catalina.java:550)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:260)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)
Feb 19, 2008 1:29:33 PM org.apache.catalina.startup.Catalina load
SEVERE: Catalina.start
LifecycleException: Protocol handler initialization failed: java.net.BindException: Address already in use:8080
at org.apache.catalina.connector.Connector.initialize(Connector.java:1060)
at org.apache.catalina.core.StandardService.initialize(StandardService.java:677)
at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:795)
at org.apache.catalina.startup.Catalina.load(Catalina.java:530)
at org.apache.catalina.startup.Catalina.load(Catalina.java:550)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:260)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:412)
Feb 19, 2008 1:29:33 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 2560 ms
Feb 19, 2008 1:29:34 PM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Feb 19, 2008 1:29:34 PM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.16
Feb 19, 2008 1:29:41 PM org.apache.catalina.core.StandardContext addApplicationListener
INFO: The listener "listeners.ContextListener" is already configured for this context. The duplicate definition has been ignored.
Feb 19, 2008 1:29:41 PM org.apache.catalina.core.StandardContext addApplicationListener
INFO: The listener "listeners.SessionListener" is already configured for this context. The duplicate definition has been ignored.
Feb 19, 2008 1:29:41 PM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Feb 19, 2008 1:29:43 PM org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
Feb 19, 2008 1:29:43 PM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/303 config=null
Feb 19, 2008 1:29:43 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 15431 ms
Feb 19, 2008 1:29:44 PM org.apache.catalina.core.StandardContext addApplicationListener
INFO: The listener "listeners.ContextListener" is already configured for this context. The duplicate definition has been ignored.
Feb 19, 2008 1:29:44 PM org.apache.catalina.core.StandardContext addApplicationListener
INFO: The listener "listeners.SessionListener" is already configured for this context. The duplicate definition has been ignored.
Feb 19, 2008 1:29:44 PM org.apache.coyote.http11.Http11Protocol start
SEVERE: Error starting endpoint
java.net.BindException: Address already in use:8080
at org.apache.tomcat.util.net.JIoEndpoint.init(JIoEndpoint.java:501)
at org.apache.tomcat.util.net.JIoEndpoint.start(JIoEndpoint.java:515)
at org.apache.coyote.http11.Http11Protocol.start(Http11Protocol.java:203)
at org.apache.catalina.connector.Connector.start(Connector.java:1131)
at org.apache.catalina.core.StandardService.start(StandardService.java:531)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
e no localhost.2008-02-19.log:
Feb 19, 2008 1:28:29 PM org.apache.catalina.core.StandardHostValve custom
SEVERE: Exception Processing ErrorPage[exceptionType=java.lang.Exception, location=/WEB-INF/jsp/errors/servleterror.jsp]
org.apache.jasper.JasperException: File "/WEB-INF/jsp/errors/servleterror.jsp" not found
at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:51)
at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:409)
at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:116)
at org.apache.jasper.compiler.JspUtil.getInputStream(JspUtil.java:847)
at org.apache.jasper.xmlparser.XMLEncodingDetector.getEncoding(XMLEncodingDetector.java:108)
at org.apache.jasper.compiler.ParserController.determineSyntaxAndEncoding(ParserController.java:309)
at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:173)
at org.apache.jasper.compiler.ParserController.parse(ParserController.java:103)
at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:153)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:314)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:294)
at org.apache.jasper.compiler.Compiler.compile(Compiler.java:281)
at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:566)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:317)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:39)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:438)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:424)
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:271)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
Feb 19, 2008 1:28:37 PM org.apache.catalina.core.StandardWrapperValve invoke
INFO: Servlet probe is currently unavailable
Feb 19, 2008 1:28:37 PM org.apache.catalina.core.ApplicationDispatcher invoke
WARNING: Servlet probe is currently unavailable
Feb 19, 2008 1:28:42 PM org.apache.catalina.core.StandardWrapperValve invoke
INFO: Servlet probe is currently unavailable
Feb 19, 2008 1:28:42 PM org.apache.catalina.core.ApplicationDispatcher invoke
WARNING: Servlet probe is currently unavailable
Feb 19, 2008 1:29:02 PM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextDestroyed()
Feb 19, 2008 1:29:02 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextDestroyed()
Feb 19, 2008 1:29:41 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
Feb 19, 2008 1:29:41 PM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
Feb 19, 2008 1:29:44 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
Feb 19, 2008 1:29:44 PM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
Feb 19, 2008 1:29:45 PM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextDestroyed()
Feb 19, 2008 1:29:45 PM org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextDestroyed()
Feb 19, 2008 1:29:48 PM org.apache.catalina.core.ApplicationContext log
INFO: Loading WebApplicationContext for Spring FrameworkServlet 'probe'
(END)
Esse erro ele dá quando tem alguem já ouvindo nessa porta. Geralmente é o tomcat mesmo que vc fechou e a porta ñ foi liberada.
Pra resolver esse problema, vc pode usar um programa chamado TCPView (se for windows). Com esse programa dá pra vc fechar
o processo e liberar a porta que está bloqueada - 8080.
Vou mudar a porta do tomcat para ver se erro pode ser isso.
E fiz mais um teste sendo que o resultado deu igual aos outros só fo aceito 972 requisições de 1000 e fiz mais requisição, depois das 1000, só que pelo browser e recebi este erro:
java.io.FileNotFoundException: $CATALINA_HOME/webapps/App/WEB-INF/config/conf.properties (Too many open files)
java.io.FileInputStream.open(Native Method)
java.io.FileInputStream.<init>(FileInputStream.java:106)
servlet.MainServlet.doGet(MainServlet.java:20)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
Será que uns dos motivos dos erros pode estar sendo criado pelo Log4J? Estava vendo alguns artigos na internet e vi que tem como “juntar” o Log4J com o tomcat, alguém saberia fazer essa junção?
Deixe seus properties em memória. (economiza IO)Utilize uma maneira melhor de escrever esse arquivo(de preferencia não escreva em arquivo a cada requisição).
Se for utilizar arquivos mesmo, utilize NIO.
Transfira o máximo de dados possíveis para a memória(cache) para aumentar a sua performance
.Tente diminuir ao máximo a criação de objetos por requisição.
Faça o que o nbluis disse algums posts atrás.
A cada requisição vc abre esse properties aí. Isso ae tá matando.
Funcionou as 1000 requisições… 
Fiz todas as configurções do tomcat faladas anteriormente e coloquei a servlete para abrir uma única vez 2 arquivos diferente, deixando essa parte em memória.
Só que quando chega a 1600 requisiçõe o tomcat passa a ficar lento e fica processsando praticamente uma requisição por segundo ou até mais tempo.
Teria como aumentar ainda mais este desempenho?
Abaixo segue como ficou a configuração da server.xml:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="2000" maxThreads="10000" acceptCount="5000"
acceptorThreadCount="2" redirectPort="8443" socket.directBuffer="false"/>
Tem os limites da máquina também né. Talvez se vc aumentar a memória, mas é mta coisa simultânea, paga-se o preço do escalonamento dessas threads aí.
Use um profiler para descobrir os gargalos, não é uma tarefa fácil. Dê uma pesquisada em mais parâmetros de configuração.
O tomcat tem para ele 1Gb de memória…
Agora estamos colocando na máquina tb o apache para que ele fique integrado com o tomcat, ficando assim o apache para requisições web e o tomcat para aplicações somente.
E como seria fazer um cluster com o tomcat, tem alguma idéia?
Vc tbm pode aproveitar que já vai ter o apache na “frente”, e colocar ele pra distribuir as requisições e fazer o load-balance.