2015-05-06 23 views
7

Próbuję przekonwertować kod Java kodu Neo4J na 2.2+, kod uruchamia wbudowany serwer Neo4J z interfejsem WWW.Zamiennik dla przestarzałego `WrappingNeoServerBootstrapper`

// configure embedded DB, 
// but this doesn't start a server at port 12345 ? 
final GraphDatabaseService db = new GraphDatabaseFactory() 
    .newEmbeddedDatabaseBuilder("/path/to/db") 
    .setConfig(ServerSettings.webserver_address, "localhost") 
    .setConfig(ServerSettings.webserver_port, 12345) 
    .newGraphDatabase(); 

// add shutdown hook 
Runtime.getRuntime().addShutdownHook(new Thread(){ 
    @Override public void run() { 
     graphDb.shutdown(); 
    } 
}); 

przestarzałej kod, który uruchamia serwer brzmi:

final GraphDatabaseAPI api = (GraphDatabaseAPI)db; 

final ServerConfigurator c = new ServerConfigurator(api); 
c.configuration().addProperty(
    Configurator.WEBSERVER_ADDRESS_PROPERTY_KEY, "localhost"); 
c.configuration().addProperty(
    Configurator.WEBSERVER_PORT_PROPERTY_KEY, 12345); 

new WrappingNeoServerBootstrapper(api, c).start(); 

Pozostawienie tego się nie uruchamia serwer. Nie jest dla mnie jasne, jak uruchomić serwer osadzony bez używania nieużywanych metod. jakieś pomysły?

UPDATE:

Więc rzeczywiście poprawna odpowiedź wydaje: zmienić architekturę.

Nie należy już używać wbudowanego serwera, zamiast korzystać z serwera i RESTful API. W przypadku bitów, które wymagają interfejsu API języka Java, można napisać rozszerzenie niezarządzane (patrz docs).

Oto prosty przykład takiego rozszerzenia https://github.com/histograph/neo4j-plugin

Dzięki!

Odpowiedz

3

UPDATE stycznia 2016

W komentarzach, można zauważyć, że niektóre rzeczy o neo4j się zmieniają. Reszta tej odpowiedzi wydaje mi się nadal aktualna, ale jeśli jesteś podróżnikiem w czasie, który przyjdzie na to stanowisko w połowie 2016 roku, sprawdź, czy nowy protokół binarny neo4j (AFAIK, zwany "bolt") jest dostępny.

/ENDUPDATE

Złą wiadomością jest to, że opakowanie neo boostrapper serwer jest przestarzała i nie sądzę, istnieje sposób to zrobić bez użycia przestarzałe metody. Tak więc prostą odpowiedzią na twoje pytanie jest "nie".

Może rok temu szukałem tego samego, co ty, ale pozwól mi podzielić się czymś, czego nauczyłem się w międzyczasie, co może zmienić twoje pytanie.

Tak więc, gdy używasz wbudowanego serwera, masz pewne zalety, takie jak możliwość korzystania z interfejsu API java, ale masz kilka poważnych wad. Umieszczenie DB w tej samej przestrzeni pamięci co twoja aplikacja oznacza, że ​​musisz żonglować pamięcią między tymi dwoma. Oznacza to, że nie można zaktualizować aplikacji bez zatrzymywania bazy danych.

Gdy korzystasz z serwera, wiele rzeczy jest lepszych od możliwości uruchamiania szyfrowania bez przechodzenia przez warstwę aplikacji, korzystania z usług RESTful i tak dalej.

Problem z WrappingNeoServerBootstrapper (i prawdopodobnie jest dobry, że jest przestarzały) jest taki, że ma wady obu podejść. Oczywiście, otrzymujesz usługi REST i szyfrowanie, ale wciąż pozostajesz w tej samej przestrzeni pamięci, co aplikacja.

Architektonicznie, dzięki neo4j odkryliśmy, że zazwyczaj chcemy korzystać z zewnętrznego oddzielnego serwera, a następnie komunikować się z nim za pośrednictwem usług REST. Myślę, że neo4j pracuje nad protokołem binarnym (ala JDBC, ale oczywiście nie to samo), aby być może więcej interfejsu API Java mogło zostać otwarte, a wydajność poprawiłaby się.W międzyczasie wszystkie dobre biblioteki dla neo4j, w tym dane źródłowe i inne, mogą już rozmawiać z punktem końcowym HTTP, więc jakiekolwiek funkcje, które dostarczają, mogą być generalnie wykonywane na oddzielnym serwerze. Aby zapewnić łatwość obsługi aplikacji i modyfikację samego neo4j, prawie zawsze lepiej jest uruchamiać oddzielny serwer.

Zauważ, że to zalecenie naśladuje to, co widzisz z niemal każdego innego rodzaju bazy danych (mongo, wyrocznia, cokolwiek). Niektóre oferują wbudowane opcje dla małych/wyspecjalizowanych aplikacji, ale prawie wszystkie z nich zakładają, że uruchomisz oddzielny proces serwera i chcesz, aby Twoja aplikacja z nim rozmawiała. A więc nie chodzi tu wcale o wykresy, tylko o dobry projekt aplikacji, ewolucyjność i łatwość konserwacji.

Z tych względów jest OK, że WrappingNeoServerBootstrapper jest przestarzałe (i prawdopodobnie nie wróci). Moje doświadczenie sugeruje, że nie jest to coś, co i tak powinno się robić.

+0

Dzięki, pomyślałem, że mogło być tak, ale dokumentacja nie jest jasna! – wires

+1

Tak, myślę, że dokumentacja mówi tylko, że jest przestarzała, nie wiele więcej. Nie wiem dokładnie, dlaczego go lekceważyli, ale moja odpowiedź jest powodem, dla którego myślę. Nie spodziewałbym się zastąpienia, ale mam nadzieję na niedługo binarny protokół alfa JDBC, który sprawiłby, że potrzeba tej funkcji jeszcze mniej. – FrobberOfBits

+0

To niefortunne. Obsługa testów Neo4j opiera się na wbudowanych bazach danych. Gdybym mógł zbudować tymczasową bazę danych bez tej wbudowanej bazy danych, zaoszczędziłoby to dużo czasu i zasobów podczas jednoczesnego równoległego prowadzenia pojedynczych testów jednostkowych. Jednak wady związane z wyborem wbudowanej bazy danych oznaczają, że nie mogę mieć zarówno narzędzia do debugowania przeglądarki, jak i wbudowanych pomocników testowej bazy danych podczas uruchamiania testów. Zamiast tego będę musiał wyodrębnić nowy kontener dokera za każdym razem, gdy chcę mieć bazę danych i zarządzać tym wszystkim sam. –

2

Zawsze można to zrobić w drugą stronę. Zamiast przechodzenia instancji z GraphDatabaseService utworzony na serwerze spróbuj najpierw uruchomić serwer i pobierania instancji utworzonego przez nią :) sprawdzone z 3.0.6

String homeDir = "./"; 
    String configFile = "./conf/neo4j.conf"; 
    ServerBootstrapper serverBootstrapper = new CommunityBootstrapper(); 
    int i = serverBootstrapper.start(new File(homeDir), Optional.of(new File(configFile)), Pair.of("dbms.connector.http.address","0.0.0.0:7575")); 
    NeoServer neoServer = serverBootstrapper.getServer(); 
    GraphDatabaseService graph = neoServer.getDatabase().getGraph(); 
    System.out.println(graph); 
1

Czajah, Cześć, Twój obejście 3.0.6 działa również w produkcji tryb wbudowany (starszy paxos HA) 3.1.0 - dziękuję.

Źródło

projekt github (Maven, Tomcat 8 WAR) w https://github.com/obrienlabs/nbi-neo4j-embedded-aws-war

Endpoints

Dodaj węzeł do osadzonego wykresu db http://neo4j.ca-central-1.elasticbeanstalk.com/FrontController?action=graph

przeglądarka jest na porcie 7575

Dzięki kilku modyfikacjom udało mi się owinąć HighlyAv ailableGraphDatabase z EnterpriseBootstrapper.

Istnieje kilka niekrytycznych wyjątków związanych z raportowaniem JMX w debug.log prawdopodobnie związanych z moją wersją tomcat 8.0.28, ale graficzna baza danych uruchomiona w Tomcat jest w porządku.

2016-12-21 16:20:00.574+0000 INFO Bolt enabled on 0.0.0.0:7688. 
    2016-12-21 16:20:09.554+0000 INFO Attempting to join cluster of [127.0.0.1:5001] 
    2016-12-21 16:20:11.566+0000 INFO Creating new cluster with name [neo4j.ha]... 
    2016-12-21 16:20:11.607+0000 INFO Instance 1 (this server) entered the cluster 
    2016-12-21 16:20:12.164+0000 INFO I am 1, moving to master 
    2016-12-21 16:20:12.293+0000 INFO Instance 1 (this server) was elected as coordinator 
    2016-12-21 16:20:12.462+0000 INFO I am 1, successfully moved to master 
    2016-12-21 16:20:12.513+0000 INFO Instance 1 (this server) is available as master at ha://127.0.0.1:6001?serverId=1 with StoreId{creationTime=1482199697648, randomId=7800059877674392627, storeVersion=15531981201765894, upgradeTime=1482199697648, upgradeId=1} 
    2016-12-21 16:20:14.495+0000 INFO Database available for write transactions 
    2016-12-21 16:20:31.917+0000 INFO Mounted REST API at: /db/manage 
    2016-12-21 16:20:53.264+0000 INFO Remote interface available at http://localhost:7575/ 
    register: [email protected] 


public class ExtendedHighlyAvailableGraphDatabaseFactory extends HighlyAvailableGraphDatabaseFactory { 
    private Log log = LogFactory.getLog(ExtendedHighlyAvailableGraphDatabaseFactory.class); 
    private HaMonitor haMonitor; 

      @Override 
      public GraphDatabaseService newDatabase(final Map<String, String> config) { 
       EnterpriseBootstrapper serverBootstrapper = new EnterpriseBootstrapper(); 
       List<Pair> pairs = new ArrayList<>(); 
       for(Entry<String, String> entry : config.entrySet()) { 
        pairs.add(Pair.of(entry.getKey(), entry.getValue())); 
       } 
       Pair pairArray[] = new Pair[pairs.size()]; 
       // will resolve to /dir/data/databases/graph.db 
       serverBootstrapper.start(storeDir, Optional.empty(), pairs.toArray(pairArray)); 
       GraphDatabaseService graph = serverBootstrapper.getServer().getDatabase().getGraph(); 
       // set the paxos HA listener only when dbms.mode=HA 
       if(graph instanceof HighlyAvailableGraphDatabase) { 
        haMonitor.setDb((HighlyAvailableGraphDatabase) graph); 
        HighAvailabilityMemberStateMachine memberStateMachine = 
          ((HighlyAvailableGraphDatabase)graph).getDependencyResolver() 
           .resolveDependency(HighAvailabilityMemberStateMachine.class); 
        if (memberStateMachine != null) { 
         memberStateMachine.addHighAvailabilityMemberListener(haMonitor); 
         log.info("register: " + haMonitor); 
        } 
       } 
       return graph; 
       } }; 
    } 

Wiosna config

<util:map id="config"> 
    <entry key="ha.server_id" value="1"/> 
    <entry key="ha.initial_hosts" value="127.0.0.1:5001"/> 
    <entry key="dbms.mode" value="HA"/> 
    <entry key="browser.allow_outgoing_connection" value="true" /> 
    <entry key="unsupported.dbms.ephemerall" value="false" /> 
    <entry key="dbms.connector.http.address" value="0.0.0.0:7575" /> 
    <entry key="dbms.connector.bolt.address" value="0.0.0.0:7688" /> 
    <entry key="dbms.connector.http.enabled" value="true" /> 
    <entry key="dbms.connector.bolt.enabled" value="true" /> 
    <entry key="dbms.connector.http.type" value="HTTP" /> 
    <entry key="dbms.connector.bolt.type" value="BOLT" /> 
    <entry key="dbms.connector.http.tls_level" value="DISABLED" /> 
    <entry key="dbms.connector.bolt.tls_level" value="DISABLED" /> 
    <entry key="dbms.security.auth_enabled" value="true"/> 
    <entry key="dbms.logs.debug.level" value="DEBUG"/> 
    <entry key="dbms.logs.http.enabled" value="true" /> 
    <entry key="dbms.logs.query.enabled" value="true"/> 
    <entry key="dbms.shell.enabled" value="true"/> 
    </util:map> 

    <bean id="haMonitor" class="org.obrienlabs.nbi.graph.service.HaMonitor"/> 
    <bean id="graphDbFactory" class="org.obrienlabs.nbi.graph.service.ExtendedHighlyAvailableGraphDatabaseFactory"> 
     <constructor-arg ref="haMonitor" /> 
    </bean> 
    <bean id="graphDbBuilder" 
     factory-bean="graphDbFactory" 
     factory-method="newEmbeddedDatabaseBuilder"> 
     <constructor-arg value="/ec2-user"/> 
    </bean> 
    <bean id="graphDbBuilderFinal" 
     factory-bean="graphDbBuilder" 
     factory-method="setConfig"> 
     <constructor-arg ref="config"/> 
    </bean> 
    <!-- HighlyAvailableGraphDatabase wrapped by an EnterpriseBootstrapper NeoServer created in this constructor --> 
    <bean id="graphDatabaseService" 
     factory-bean="graphDbBuilderFinal" 
     factory-method="newGraphDatabase" 
     destroy-method="shutdown" /> 

Transakcje przejść

2016-12-21 20:51:07.478+0000 INFO [o.n.k.i.s.c.CountsTracker] About to rotate counts store at transaction 9 to [/ec2-user/data/databases/graph.db/neostore.counts.db.b], from [/ec2-user/data/databases/graph.db/neostore.counts.db.a]. 
2016-12-21 20:51:07.480+0000 INFO [o.n.k.i.s.c.CountsTracker] Successfully rotated counts store at transaction 9 to [/ec2-user/data/databases/graph.db/neostore.counts.db.b], from [/ec2-user/data/databases/graph.db/neostore.counts.db.a]. 
2016-12-21 20:51:07.483+0000 INFO [o.n.k.i.t.l.c.CheckPointerImpl] Check Pointing triggered by scheduler for time threshold [9]: Store flush completed 

ustawienia z MBean w JConsole są

2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] Kernel version: 3.1.0,16a782b42d76ca37db72958eb2565cf6aa671a29 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] Neo4j Kernel properties: 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.query.enabled=true 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.security.auth_enabled=true 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.tls_level=DISABLED 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.shell.enabled=true 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] ha.server_id=1 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.http.enabled=true 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] ha.initial_hosts=127.0.0.1:5001 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.allow_format_migration=false 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.address=0.0.0.0:7575 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.enabled=true 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.tls_level=DISABLED 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.enabled=true 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.mode=HA 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.labels=56 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.type=BOLT 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.directories.neo4j_home=/ec2-user 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.ephemerall=false 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] browser.allow_outgoing_connection=true 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.logs.debug.level=DEBUG 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.http.type=HTTP 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.strings=120 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.block_size.array_properties=120 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] unsupported.dbms.edition=enterprise 
2016-12-23 13:28:12.708+0000 INFO [o.n.k.i.DiagnosticsManager] dbms.connector.bolt.address=0.0.0.0:7688 

7575 (serwer pomost) i 7688 (śruba) porty są otwarte

obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 7575 
tcp46  0  0 *.7575     *.*     LISTEN  131072 131072 49013  0 
tcp4  0  0 127.0.0.1.7575   127.0.0.1.60685  TIME_WAIT 407296 146988 49013  0 
tcp6  0  0 ::1.7575    ::1.60699    TIME_WAIT 407284 146808 49013  0 
tcp6  0  0 ::1.7575    ::1.60700    TIME_WAIT 407284 146808 49013  0 
obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 7688 
tcp6  0  0 ::1.7688    ::1.60704    ESTABLISHED 406582 146808 49013  0 
tcp6  0  0 ::1.60704    ::1.7688    ESTABLISHED 398196 146808 48165  0 
tcp6  0  0 ::1.7688    ::1.60702    ESTABLISHED 406570 146808 49013  0 
tcp6  0  0 ::1.60702    ::1.7688    ESTABLISHED 398185 146808 48165  0 
tcp6  0  0 ::1.7688    ::1.60701    ESTABLISHED 407255 146808 49013  0 
tcp6  0  0 ::1.60701    ::1.7688    ESTABLISHED 407628 146808 48165  0 
tcp46  0  0 *.7688     *.*     LISTEN  131072 131072 49013  0 
obrienlabs-mbp15:_deployment michaelobrien$ netstat -vatn | grep 8080 
tcp4  0  0 127.0.0.1.8080   127.0.0.1.60584  FIN_WAIT_2 408104 146988 49013  0 
tcp4  994  0 127.0.0.1.60584  127.0.0.1.8080   CLOSE_WAIT 408128 146988 42992  0 
tcp46  0  0 *.8080     *.*     LISTEN  131072 131072 49013  0 
udp4  0  0 *.*     *.*        196724 9216 38080  0 

/ec2-user/logs/http.log

2016-12-23 02:53:21.505+0000 INFO [REQUEST] [AsyncLog @ 2016-12-23 02:53:21.505+0000] 0:0:0:0:0:0:0:1 - [Thu Dec 22 21:53:21 EST 2016] "/browser/views/frame-cypher.html?null" 200 22972 "http://localhost:7575/browser/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14" 2 

query.log

2016-12-23 13:33:39.059+0000 INFO 175 ms: bolt-session bolt neo4j neo4j-javascript/[object Object]  client/0:0:0:0:0:0:0:1:64019 server/0:0:0:0:0:0:0:1:7688> neo4j - MATCH (a)-[r]->(b) WHERE id(a) IN {node_ids} 
AND id(b) IN {new_node_ids} 
RETURN r; - {node_ids: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], new_node_ids: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]} - {} 

Zastrzeżenie: Wierzę właściwa architektura obejmuje klastrowego zestaw śrubą trybie serwera obsługującego Serwery Neo4j używające klastra przyczynowego w protokole tratwy. Ten nieudokumentowany/wewnętrzny interfejs API jest używany jako tymczasowe obejście, aby uzyskać przeglądarkę neo4j na osadzonym serwerze Neo4j w wersji 3.1.0, ponieważ działała ona pod WrappingNeoServerBootstrapper w wersji 2.3. Wykorzystanie wbudowanego serwera dla szybszych przejazdów było przypadkiem użycia - wydajność musi zostać ponownie oceniona, aby sprawdzić, czy architektura oparta na śrubach jest bardziej optymalna dla interfejsu API traversal. /Michael

1

Z Neo4J 3.1.1 i podejście czajah „s, tryb«osadzone»naprawdę można uruchomić w porządku (brak połączeń przestarzałe), wraz z przewagą manipulowania danymi wykres z tej samej instancji JVM.

Poniższy przykładowy kod wymaga artefaktów zależności neo4j i neo4j-server z grupy org.neo4j. Plik konfiguracyjny serwera jest pomijany, podczas gdy działający folder pamięci i odpowiednie opcje konfiguracyjne są określone tak, aby neo4j console i neo4j-shell (które stają się przestarzałe na rzecz cypher-shell) mogą być użyte przeciwko instancji "osadzonej".

import org.neo4j.graphdb.GraphDatabaseService; 
import org.neo4j.helpers.collection.Pair; 
import org.neo4j.server.CommunityBootstrapper; 
import org.neo4j.server.NeoServer; 
import org.neo4j.server.ServerBootstrapper; 

import java.io.File; 
import java.io.IOException; 
import java.util.Optional; 

public class RunNeoRun { 
    public static void main(String[] args) throws IOException { 
     // Wherever the Neo4J storage location is. 
     File storeDir = new File("/tmp/tmp4j"); 

     ServerBootstrapper serverBootstrapper = new CommunityBootstrapper(); 
     serverBootstrapper.start(
      storeDir, 
      Optional.empty(), // omit configfile, properties follow 
      Pair.of("dbms.connector.http.address","127.0.0.1:7474"), 
      Pair.of("dbms.connector.http.enabled", "true"), 
      Pair.of("dbms.connector.bolt.enabled", "true"), 

      // allow the shell connections via port 1337 (default) 
      Pair.of("dbms.shell.enabled", "true"), 
      Pair.of("dbms.shell.host", "127.0.0.1"), 
      Pair.of("dbms.shell.port", "1337") 
     ); 
     // ^^ serverBootstrapper.start() also registered shutdown hook! 

     NeoServer neoServer = serverBootstrapper.getServer(); 
     GraphDatabaseService gdb = neoServer.getDatabase().getGraph(); 

     /* Some transactional code */ 
     try(Transaction tx = gdb.beginTx()) { 
      gdb.getAllNodes().forEach(
       n -> System.out.println(n) 
      ); 
      tx.success(); 
     } 

     System.out.println("Press ENTER to quit."); 
     System.in.read(); 

     System.exit(0); 
    } 
} 
Powiązane problemy