java - Neo4j Extensión no administrada y GuardTimeoutException
jersey cypher (2)
Las pequeñas transacciones lo hacen ir más lento ya que cada uno tiene que ser enjuagado en el disco. Por lo general, tiene sentido agregar hasta 50k nodos en un tx, lo que debería tomar menos de un segundo.
Para su filtro de protección, es solo un filtro de servlet, por lo que también puede verificar el código fuente de Neo4j donde está instalado y al inicio de su extensión, instálelo usted mismo, pero exceda los puntos finales por los que desea realizar el lote.
En: org.neo4j.server.AbstractNeoServer
línea 488
Filter filter = new GuardingRequestFilter( guard,
getConfiguration().getInt( Configurator.WEBSERVER_LIMIT_EXECUTION_TIME_PROPERTY_KEY ) );
webServer.addFilter( filter, "/*" );
Puede usar el inicializador de extensión para agregar su filtro personalizado como se muestra aquí:
tienes que agregar un archivo como este que contiene tu nombre de clase de inicializador:
Tengo una gran necesidad de algunos consejos sobre un problema que me estoy encontrando con una extensión no administrada de Neo4j que estoy creando en Java. He creado una muestra de código muy simple que resalta mi problema. La premisa básica es que me gustaría establecer el
org.neo4j.server.webserver.limit.executiontime
para el servidor neo4j a una cantidad razonable de tiempo para las consultas de los usuarios (digamos 2 minutos) que entran a través de Cypher, otros puntos finales, etc. Pero también tengo algunos trabajos por lotes que necesito ejecutar a través de esta extensión no administrada, y por lo tanto Intenté dividirlos en varias transacciones <2 minutos. El problema que estoy viendo es que, aunque cada una de mis transacciones es <2 minutos, una vez que mi proceso se ha estado ejecutando durante 2 minutos, obtengo una excepción GuardTimeoutException.
Aquí está la muestra. En esta muestra, tenga en cuenta que he limitado el tiempo a 2000 milisegundos, por lo que no me lleva todo el día depurar. (¡pero se está poniendo muy cerca!)
Punto final
/**
* Sample endpoint.
@GET
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public Response test(@Context GraphDatabaseService service) {
TestFile.test(service);
return Response.ok().build();
}
Lógica
public static void test(final GraphDatabaseService service) {
for (int i = 0; i < 100000; i++) {
try (Transaction tx = service.beginTx();) {
final Node n = service.createNode();
n.addLabel(testLabel);
tx.success();
tx.close();
}
System.out.println("Added node");
}
}
Veo que cada transacción lleva solo una fracción de segundo, ya que cargo aproximadamente 200 nodos antes de que se agote el tiempo de espera. Sin embargo, a exactamente 2 segundos de alcanzar el punto final, obtengo lo siguiente:
org.neo4j.kernel.guard.GuardTimeoutException: timeout occured (overtime=1)
at org.neo4j.kernel.guard.Guard$Timeout.check(Guard.java:132)
at org.neo4j.kernel.guard.Guard.check(Guard.java:43)
at org.neo4j.kernel.InternalAbstractGraphDatabase$5.createNode(InternalAbstractGraphDatabase.java:794)
at org.neo4j.kernel.impl.api.state.OldTxStateBridgeImpl.nodeCreate(OldTxStateBridgeImpl.java:120)
at org.neo4j.kernel.impl.api.state.TxStateImpl.nodeDoCreate(TxStateImpl.java:366)
at org.neo4j.kernel.impl.api.StateHandlingStatementOperations.nodeCreate(StateHandlingStatementOperations.java:99)
at org.neo4j.kernel.impl.api.ConstraintEnforcingEntityOperations.nodeCreate(ConstraintEnforcingEntityOperations.java:390)
at org.neo4j.kernel.impl.api.LockingStatementOperations.nodeCreate(LockingStatementOperations.java:207)
at org.neo4j.kernel.impl.api.OperationsFacade.nodeCreate(OperationsFacade.java:506)
at org.neo4j.kernel.InternalAbstractGraphDatabase.createNode(InternalAbstractGraphDatabase.java:1120)
at **TestFile.test(TestFile.java:15)
at **test(Jobs.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205)
at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
at org.neo4j.server.rest.transactional.TransactionalRequestDispatcher.dispatch(TransactionalRequestDispatcher.java:139)
at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:698)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1506)
at org.neo4j.server.guard.GuardingRequestFilter.doFilter(GuardingRequestFilter.java:68)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1477)
at org.neo4j.server.guard.GuardingRequestFilter.doFilter(GuardingRequestFilter.java:68)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1477)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:503)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:211)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1096)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:432)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:175)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1030)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136)
at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:52)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:445)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:268)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:229)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.run(AbstractConnection.java:358)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:601)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:532)
at java.lang.Thread.run(Thread.java:744)
Como puede ver, he intentado con tx.success (), tx.close (), cualquier cosa que se me ocurra para hacer que todas las transacciones se mueran cuando se hayan completado. ¡Cualquier consejo muy apreciado!
actualización -------------
Michael - He seguido los pasos que sugirió - Tengo una nueva clase de Java que amplía SPIPluginLifecycle y también he agregado el nuevo archivo de configuración en / src / main / resources / META-INF / services. Puedo ver que este archivo termina en el archivo jar que se incluye en / plugins dentro de META-INF / services. Sin embargo, no veo que se llame a esta clase de inicialización. Aquí está la clase y los registros que veo en el arranque.
public class GraphInitializer implements SPIPluginLifecycle {
private WebServer webServer;
@Override
public Collection<Injectable<?>> start(final GraphDatabaseService graphDatabaseService, final Configuration config) {
throw new IllegalAccessError();
}
@Override
public void stop() {
}
@Override
public Collection<Injectable<?>> start(final NeoServer neoServer) {
System.out.println("K starting!");
webServer = getWebServer(neoServer);
final Database database = neoServer.getDatabase();
final GraphDatabaseAPI graphDatabaseAPI = database.getGraph();
final Guard guard = graphDatabaseAPI.getDependencyResolver().resolveDependency(Guard.class);
final Filter filter = new GuardingRequestFilter(guard, 3000);
webServer.addFilter(filter, "/*" );
return null;
}
private WebServer getWebServer(final NeoServer neoServer) {
if (neoServer instanceof AbstractNeoServer) {
return ((AbstractNeoServer) neoServer).getWebServer();
}
throw new IllegalArgumentException("expected AbstractNeoServer");
}
Registros:
2014-10-06 16:14:23.009+0000 INFO [API] Mounted discovery module at [/]
2014-10-06 16:14:23.014+0000 INFO [API] Mounted REST API at [/db/data/]
2014-10-06 16:14:23.017+0000 INFO [API] Mounted management API at [/db/manage/]
2014-10-06 16:14:23.017+0000 INFO [API] Mounted third-party JAX-RS package [***] at [/kristen]
2014-10-06 16:14:23.017+0000 INFO [API] Mounted webadmin at [/webadmin]
2014-10-06 16:14:23.017+0000 INFO [API] Mounted Neo4j Browser at [/browser]
2014-10-06 16:14:23.070+0000 INFO [API] Mounting static content at [/webadmin] from [webadmin-html]
2014-10-06 16:14:23.124+0000 INFO [API] Mounting static content at [/browser] from [browser]
12:14:23.126 [main] WARN o.e.j.server.handler.ContextHandler - o.e.j.s.ServletContextHandler@1cb1c025{/,null,null} contextPath ends with /
12:14:23.127 [main] WARN o.e.j.server.handler.ContextHandler - Empty contextPath
12:14:23.131 [main] INFO org.eclipse.jetty.server.Server - jetty-9.0.5.v20130815
12:14:23.155 [main] INFO o.e.j.server.handler.ContextHandler - Started o.e.j.s.h.MovedContextHandler@5de15910{/,null,AVAILABLE}
12:14:23.245 [main] INFO o.e.j.w.StandardDescriptorProcessor - NO JSP Support for /webadmin, did not find org.apache.jasper.servlet.JspServlet
12:14:23.255 [main] INFO o.e.j.server.handler.ContextHandler - Started o.e.j.w.WebAppContext@4b45c74e{/webadmin,jar:file:/usr/local/Cellar/neo4j/2.1.3/libexec/system/lib/neo4j-server-2.1.3-static-web.jar!/webadmin-html,AVAILABLE}
12:14:23.668 [main] INFO o.e.j.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@2917eb65{/kristen,null,AVAILABLE}
12:14:23.817 [main] INFO o.e.j.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@54589209{/db/manage,null,AVAILABLE}
12:14:24.003 [main] INFO o.e.j.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@68a1f8e7{/db/data,null,AVAILABLE}
12:14:24.021 [main] INFO o.e.j.w.StandardDescriptorProcessor - NO JSP Support for /browser, did not find org.apache.jasper.servlet.JspServlet
12:14:24.022 [main] INFO o.e.j.server.handler.ContextHandler - Started o.e.j.w.WebAppContext@438e0daa{/browser,jar:file:/usr/local/Cellar/neo4j/2.1.3/libexec/system/lib/neo4j-browser-2.1.3.jar!/browser,AVAILABLE}
12:14:24.103 [main] INFO o.e.j.server.handler.ContextHandler - Started o.e.j.s.ServletContextHandler@1cb1c025{/,null,AVAILABLE}
12:14:24.115 [main] INFO o.e.jetty.server.ServerConnector - Started ServerConnector@75b61dd7{HTTP/1.1}{localhost:7474}
12:14:24.503 [main] INFO o.e.jetty.server.ServerConnector - Started ServerConnector@6464d61f{SSL-HTTP/1.1}{localhost:7473}
2014-10-06 16:14:24.503+0000 INFO [API] Server started on: http://localhost:7474/
2014-10-06 16:14:24.504+0000 INFO [API] Remote interface ready and available at [http://localhost:7474/]
Esperaba una nueva entrada de línea o algo así; también mis cambios para agregar un tiempo de espera no funcionan, así que estoy seguro de que estos cambios no han tenido efecto. ¿Hay algo adicional que deba agregar a neo4j-server.properties, neo4j.properties, etc.? Ya agregué con éxito la línea que configura la extensión no administrada.
¡gracias!
Solución Publicado por Michael Hunger funcionó a la perfección, con algunos de mis propios puntos de aprendizaje en el camino.
- Tuve que actualizar la propiedad org.neo4j.server.thirdparty_jaxrs_classes en neo4j-server.properties a un directorio más raíz, ya que no había puesto mi inicializador en el mismo directorio que mis archivos api java.
- El método start () tenía que devolver una colección vacía.
- Pude usar varios filtros diferentes para especificar límites de tiempo para diferentes puntos finales.
Código final a continuación:
@Override
public Collection<Injectable<?>> start(final NeoServer neoServer) {
webServer = getWebServer(neoServer);
final Database database = neoServer.getDatabase();
final GraphDatabaseAPI graphDatabaseAPI = database.getGraph();
final Guard guard = graphDatabaseAPI.getDependencyResolver().resolveDependency(Guard.class);
final Filter filter = new GuardingRequestFilter(guard, 600);
webServer.addFilter(filter, "/*" );
final Filter filter2 = new GuardingRequestFilter(guard, 3000);
webServer.addFilter(filter2, "*/batch" );
return Collections.emptyList();
}