Actualmente me encontré con un problema en nuestro servidor Drools.
Recibimos solicitudes bastante grandes a nuestra granja de servidores drools que genera un OutOfMemoryError . Esas solicitudes grandes no deben procesarse (son errores), y si una solicitud demora más de 5 segundos, debe cancelarse.
He intentado solucionar esto con una regla DRL de tiempo de espera personalizada que se explica aquí :
rule "Stop the rule engine after 5s" timer ( int: 5s ) salience 0 when then System.err.println("*** Stop the rule engine after 5s ***"); drools.halt(); end Pero esta regla nunca se tiene en cuenta. Así que probé otra solución alternativa: poner mi ksession.fireAllRules(); en un hilo, y si tarda más de 5 segundos, detenga la baba con ksession.halt(); ; Me gusta esto:
KieSessionConfiguration conf = kieServices.newKieSessionConfiguration(); final KieSession ksession = kcontainer.newKieSession(conf); Thread droolsThread = new Thread(new Runnable() { public void run() { ksession.fireAllRules(); } }, "drools"); long tStart = System.currentTimeMillis(); droolsThread.start(); /*wait until the end of the Thread or 5 seconds max*/ while (System.currentTimeMillis() - tStart < 5000 && droolsThread.isAlive()) Thread.sleep(100); /*if alive for more than 5 seconds stop it*/ if (droolsThread.isAlive()) { System.err.println("timeout killing drools"); ksession.halt(); ksession.dispose(); } En este segundo escenario, cuando se llama a drools con ksession.fireAllRules(); , comienza a ejecutar la solicitud y, si es enorme, arroja la Exception: java.lang.OutOfMemoryError :
[apache-tomcat-9.0.39]: timeout killing drools [apache-tomcat-9.0.39]: Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "Catalina-utility-1" java.lang.OutOfMemoryError: Java heap spaceNo sé qué hacer para evitar que esas grandes solicitudes consuman toda la memoria del servidor. ¿Es posible detener una solicitud larga que se está ejecutando actualmente en drools?
Estaba en el camino correcto, pero necesita iniciar la ejecución de la regla usando fireUntilHalt (en lugar de fireAllRules): https://docs.drools.org/7.40.0.Final/kie-api-javadoc/org/kie/api /runtime/rule/StatefulRuleSession.html#fireUntilHalt--
Entonces podrá detenerlo mediante el método de detención .
También recomendaría investigar por qué está viendo este patrón de "comerse toda la memoria del servidor". Tal vez habrá oportunidad de optimizar sus reglas..
Podría usar la siguiente API en una StatefulRuleSession:
fireAllRules(int max) Dispara Partidos en la Agenda hasta el número máximo dado de Partidos, antes de devolver el control a la aplicación.
Al consumir memoria, puede perfilar el uso de la memoria (a nivel de Java) para ver qué está pasando. Las aplicaciones basadas en reglas generalmente usan mucha memoria al hacer un intercambio de tiempo de procesamiento de memoria usando algoritmos derivados de RETE