Um problema comum para tarefas demoradas no WebLogic é o famoso Stuck Thread. Para simular esse problema é só criar um projeto Web com uma servlet com o seguinte código: (Atenção!!! Não faça isso em casa. Isso é feito por profissionais treinados :D)
package br.com.thiagovespa.stuckthread.web.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LongRunningServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { for(int i=0;i<30;i++) { // 15min try { System.out.println("Estou executando: " + i); Thread.sleep(30*1000); //0.5 segundo } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
Thread e System.out no código (como eu disse.. não faça isso em casa e nem no trabalho :)).
Coloque o seguinte conteúdo no web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>StuckThreadWebProject</display-name> <servlet> <description></description> <display-name>LongRunningServlet</display-name> <servlet-name>LongRunningServlet</servlet-name> <servlet-class>br.com.thiagovespa.stuckthread.web.servlet.LongRunningServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LongRunningServlet</servlet-name> <url-pattern>/LongRunningServlet</url-pattern> </servlet-mapping> </web-app>
Ao acessar essa servlet no browser, vai fazer com que o WebLogic gere o seguinte erro após uns 10 minutos:
<Sep 5, 2012 3:51:13 PM BRT> <Error> <WebLogicServer> <BEA-000337> <[STUCK] ExecuteThread: '9' for queue: 'weblogic.kernel.Default (self-tuning)' has been busy for "636" seconds working on the request "Workmanager: default, Version: 0, Scheduled=true, Started=true, Started time: 636207 ms [ GET /StuckThreadWebProject/LongRunningServlet HTTP/1.1 Connection: keep-alive User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8,pt-BR;q=0.6,pt;q=0.4 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 ]", which is more than the configured time (StuckThreadMaxTime) of "600" seconds. Stack trace: java.lang.Thread.sleep(Native Method) br.com.thiagovespa.stuckthread.web.servlet.LongRunningServlet.doGet(LongRunningServlet.java:30) javax.servlet.http.HttpServlet.service(HttpServlet.java:707) javax.servlet.http.HttpServlet.service(HttpServlet.java:820) weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:301) weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26) weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) oracle.security.jps.ee.http.JpsAbsFilter$1.run(JpsAbsFilter.java:119) java.security.AccessController.doPrivileged(Native Method) oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:315) oracle.security.jps.ee.util.JpsPlatformUtil.runJaasMode(JpsPlatformUtil.java:442) oracle.security.jps.ee.http.JpsAbsFilter.runJaasMode(JpsAbsFilter.java:103) oracle.security.jps.ee.http.JpsAbsFilter.doFilter(JpsAbsFilter.java:171) oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:71) weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) oracle.dms.servlet.DMSServletFilter.doFilter(DMSServletFilter.java:139) weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3730) weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3696) weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120) weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2273) weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2179) weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1490)
Se você reparar no código de erro, existe um trecho-chave para a gente resolver o problema: "working on the request "Workmanager: default". Em alguns casos, temos operações que podem demorar muito mais que 10 minutos. Nesse caso, temos que utilizar um Workmanager que ignore as nossas Struck Threads.
No seu projeto, altere o arquivo weblogic.xml para o seguinte conteúdo:
<?xml version="1.0" encoding="UTF-8"?><wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.3/weblogic-web-app.xsd"> <wls:weblogic-version>10.3.6</wls:weblogic-version> <wls:context-root>StuckThreadWebProject</wls:context-root> <wls:work-manager> <wls:name>wm/NoStuckWorkManager</wls:name> <wls:ignore-stuck-threads>true</wls:ignore-stuck-threads> </wls:work-manager> <wls:wl-dispatch-policy>wm/NoStuckWorkManager</wls:wl-dispatch-policy> </wls:weblogic-web-app>
E no seu web.xml, associe o WorkManager à Servlet desejada:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>StuckThreadWebProject</display-name> <servlet> <description></description> <display-name>LongRunningServlet</display-name> <servlet-name>LongRunningServlet</servlet-name> <servlet-class>br.com.thiagovespa.stuckthread.web.servlet.LongRunningServlet</servlet-class> <init-param> <param-name>wl-dispatch-policy</param-name> <param-value>wm/NoStuckWorkManager</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>LongRunningServlet</servlet-name> <url-pattern>/LongRunningServlet</url-pattern> </servlet-mapping> </web-app>
O mesmo problema pode ocorrer com outros recursos como WebServices, criei um WebService para simular o problema. O código com a solução você pode pegar aqui (Projeto Eclipse). Para WebService você só precisa alterar o weblogic.xml com o seguinte conteúdo:
<?xml version="1.0" encoding="UTF-8"?><wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.3/weblogic-web-app.xsd"> <wls:weblogic-version>10.3.6</wls:weblogic-version> <wls:context-root>StuckThreadWebProject</wls:context-root> <wls:work-manager> <wls:name>wm/NoStuckWorkManager</wls:name> <wls:ignore-stuck-threads>true</wls:ignore-stuck-threads> </wls:work-manager> <wls:wl-dispatch-policy>wm/NoStuckWorkManager</wls:wl-dispatch-policy> </wls:weblogic-web-app>
Ao invés de ignorar as Stuck Threads, uma solução melhor é re-especificar o tempo máximo para que o problema ocorra, dessa forma se ocorrer realmente algum problema, você irá saber:
<?xml version="1.0" encoding="UTF-8"?><wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.3/weblogic-web-app.xsd"> <wls:weblogic-version>10.3.6</wls:weblogic-version> <wls:context-root>StuckThreadWebProject</wls:context-root> <wls:work-manager> <wls:name>wm/NoStuckWorkManager</wls:name> <wls:response-time-request-class> <wls:name>ResponseTime</wls:name> <wls:goal-ms>12000000</wls:goal-ms> </wls:response-time-request-class> </wls:work-manager> <wls:wl-dispatch-policy>wm/NoStuckWorkManager</wls:wl-dispatch-policy> </wls:weblogic-web-app>
Você também pode configurar um Work Manager Global. Para isso, devemos acessar o console do WebLogic, e em Environment e selecione a opção Work Manager. Clique em New, selecione Work Manager e clique em Next:
Especifique um nome e clique em Next. Selecione os targets e clique em Finish. Selecione o Work Manager criado, marque a opção Ignore Stuck Threads e clique em Save.
Reinicie o servidor e agora você pode referenciá-lo na sua aplicação.
Bom dia! venho buscar um help, fiz a instalação no debian da versão weblogic server 12c. Sendo que executo o mesmo está rodando na porta 5556, porém ao rodar no browser não está carregando.. executo o seguinte comando http://localhost:5556/console.. Alguma dica ?
Preciso do resultado da seguinte saída para poder te ajudar: netstat -tlpn | grep 5556
Thiago,
Excelente Post!
Obrigado pela ajuda!
Uma dúvida, caso tenhamos um grande número de Stuck Thread, acabado derrubando o Weblogic?!
A melhor forma de evitar que o Weblogic caia é definindo um timeout menor?