2017-11-28 20 views
1

アプリケーションを2台のリモートサーバGremlinserver/Janusserverに接続したいのですが、どちらも同じCassandraデータベースを持っています。 そしてこのように私は高い可用性を持っています。セッションレスのGremlinドライバを使ってGremlinサーバに接続する方法

<dependency> 
    <groupId>org.janusgraph</groupId> 
    <artifactId>janusgraph-core</artifactId> 
    <version>0.2.0</version> 
</dependency> 
<dependency> 
    <groupId>org.apache.tinkerpop</groupId> 
    <artifactId>gremlin-driver</artifactId> 
    <version>3.2.6</version> 
</dependency> 

ファイルgremlin.yaml:私のサービスクラスで

hosts: [127.0.0.1,192.168.2.57] 
port: 8182 
serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true }} 

私は、いくつかのメソッドを持っているクライアントオブジェクトを介して接続され、それぞれが:

public class GremlinServiceConcrete implements GremlinService { 
... 
.. 
public Set<Long> getImpactedComponentsIds (...) throws GremlinServiceException { 
.. 
     Cluster cluster = gremlinCluster.getCluster(); 
     Client client = null; 
     Set<Long> impactedIds = Sets.newHashSet(); 
     try { 
      client = cluster.connect(); 
      binding = Maps.newLinkedHashMap(); 
.. 

そしてGremlinClusterクラスでは、私は運転手に電話する

public class GremlinCluster { 

    public static final int MIN_CONNECTION_POOL_SIZE = 2; 
    public static final int MAX_CONNECTION_POOL_SIZE = 20; 
    public static final int MAX_CONTENT_LENGTH = 65536000; 

    private static Logger logger = LoggerFactory.getLogger(GremlinCluster.class); 

    private String server; 
    private Integer port; 

    private Cluster cluster; 

    public GremlinCluster(String server, Integer port) throws FileNotFoundException { 
     this.server = Objects.requireNonNull(server); 
     this.port = Objects.requireNonNull(port); 
     this.cluster = init(); 
    } 

    private Cluster init() throws FileNotFoundException { 
     GryoMapper.Builder kryo = GryoMapper.build().addRegistry(JanusGraphIoRegistry.getInstance()); 
     MessageSerializer serializer = new GryoMessageSerializerV1d0(kryo); 
     Cluster cluster = Cluster.build(new File("conf/driver-gremlin.yaml")).port(port) 
       .serializer(serializer) 
       .minConnectionPoolSize(MIN_CONNECTION_POOL_SIZE) 
       .maxConnectionPoolSize(MAX_CONNECTION_POOL_SIZE) 
       .maxContentLength(MAX_CONTENT_LENGTH).create(); 

     logger.debug(String.format("New cluster connected at %s:%s", server, port)); 
     return cluster; 
    } 

    public Cluster getCluster() { 
     return cluster; 
    } 

    public void destroy() { 
     try { 
      cluster.close(); 
     } catch (Exception e) { 
      logger.debug("Error closing cluster connection: " + e.toString()); 
     } 
    } 

} 

アプリケーションは、1つのサーバーに接続するだけで正常に動作します。 サーバーに接続すると非常に遅くなります。サーバーを停止してもフェールオーバーが正しく実行されない場合 サーバーがセッションモードで接続されている可能性があります。 Tinkerpopのドキュメントでは、2つのモードのコードの違いについては説明していません。

修正: 遅れは、Eclipseのデバッグモードによるものです。 アプリケーションは両方のgremlinserversに要求を送信しますが、クラスタリング機能のこの部分は正常に機能します。

サーバーがシャットダウンすると、正しく動作しません。アプリケーションは、要求を別のサーバーに送信します。停止したサーバが起動した場合、gremlinサーバはそれを検出せず、再接続しません。 gremlinserverから

出力:

<bean id="gremlinCluster" class="[Fully qualified name].GremlinCluster" scope="singleton" destroy-method="destroy"> 
    <constructor-arg name="server"><value>${GremlinServerHost}</value></constructor-arg> 
    <constructor-arg name="port"><value>${GremlinServerPort}</value></constructor-arg> 
</bean> 

、プロパティファイルで: enter image description here

GremlinClusterスプリングビーン(豆-services.xmlの)です。

GremlinServerHost=[Fully qualified name]/config/gremlin.yaml 
GremlinServerPort=8182 

そしてGremlinClusterクラスで:

import java.util.Objects; 

import org.apache.tinkerpop.gremlin.driver.Cluster; 
import org.apache.tinkerpop.gremlin.driver.MessageSerializer; 
import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0; 
import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoMapper; 
import org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import java.io.File; 
import java.io.FileNotFoundException; 

public class GremlinCluster { 

    public static final int MIN_CONNECTION_POOL_SIZE = 2; 
    public static final int MAX_CONNECTION_POOL_SIZE = 20; 
    public static final int MAX_CONTENT_LENGTH = 65536000; 

    private static Logger logger = LoggerFactory.getLogger(GremlinCluster.class); 

    private String server; 
    private Integer port; 

    private Cluster cluster; 

    public GremlinCluster(String server, Integer port) throws FileNotFoundException { 
     this.server = Objects.requireNonNull(server); 
     this.port = Objects.requireNonNull(port); 
     this.cluster = init(); 
    } 

    private Cluster init() throws FileNotFoundException { 
     GryoMapper.Builder kryo = GryoMapper.build().addRegistry(JanusGraphIoRegistry.getInstance()); 
     MessageSerializer serializer = new GryoMessageSerializerV1d0(kryo); 
     Cluster cluster = Cluster.build(new File(server)).port(port) 
       .serializer(serializer) 
       .minConnectionPoolSize(MIN_CONNECTION_POOL_SIZE) 
       .maxConnectionPoolSize(MAX_CONNECTION_POOL_SIZE) 
       .maxContentLength(MAX_CONTENT_LENGTH).create(); 

     logger.debug(String.format("New cluster connected at %s:%s", server, port)); 
     return cluster; 
    } 

    public Cluster getCluster() { 
     return cluster; 
    } 

    public void destroy() { 
     try { 
      cluster.close(); 
     } catch (Exception e) { 
      logger.debug("Error closing cluster connection: " + e.toString()); 
     } 
    } 

} 

とクエリ(GremlinServiceConcrete)を行う方法の例:

@Override 
    public Long getNeighborsCount(List<Long> componentIds) throws GremlinServiceException { 
     // Check argument is right 
     if (componentIds == null || componentIds.isEmpty()) { 
      throw new GremlinServiceException("Cannot compute neighbors count with an empty list as argument"); 
     } 

     Cluster cluster = gremlinCluster.getCluster(); 
     Client client = null; 
     try { 
      client = cluster.connect(); 
      String gremlin = "g.V(componentIds).both().dedup().count()"; 
      Map<String, Object> parameters = Maps.newHashMap(); 
      parameters.put("componentIds", componentIds); 

      if (logger.isDebugEnabled()) logger.debug("Submiting query [ " + gremlin + " ] with binding [ " + parameters + "]"); 

      ResultSet resultSet = client.submit(gremlin, parameters); 
      Result result = resultSet.one(); 
      return result.getLong(); 

     } catch (Exception e) { 
      throw new GremlinServiceException("Error retrieving how many neighbors do vertices " + componentIds + " have: " + e.getMessage(), e); 

     } finally { 
      if (client != null) try { client.close(); } catch (Exception e) { /* NPE because connection was not initialized yet */ } 
     } 
    } 

グレムリン-server.yaml:

host: 127.0.0.1 
port: 8182 
scriptEvaluationTimeout: 600000 
channelizer: org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer 
graphs: { 
    graph: conf/janusgraph-cassandra.properties 
} 
plugins: 
    - janusgraph.imports 
scriptEngines: { 
    gremlin-groovy: { 
    imports: [java.lang.Math,org.janusgraph.core.schema.Mapping], 
    staticImports: [java.lang.Math.PI], 
    scripts: [scripts/empty-sample.groovy]}} 
serializers: 
    - { 
     className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, 
     config: { 
     bufferSize: 819200, 
     ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] 
     } 
    } 
    - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoLiteMessageSerializerV1d0, config: {ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }} 
    - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true }} 
    - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistryV1d0] }} 
    - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }} 
    - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistryV1d0] }} 
processors: 
    - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }} 
    - { className: org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor, config: { cacheExpirationTime: 600000, cacheMaxSize: 1000 }} 
metrics: { 
    consoleReporter: {enabled: true, interval: 180000}, 
    csvReporter: {enabled: true, interval: 180000, fileName: /tmp/gremlin-server-metrics.csv}, 
    jmxReporter: {enabled: true}, 
    slf4jReporter: {enabled: true, interval: 180000}, 
    gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST}, 
    graphiteReporter: {enabled: false, interval: 180000}} 
maxInitialLineLength: 4096 
maxHeaderSize: 8192 
maxChunkSize: 4096000 
maxContentLength: 65536000 
maxAccumulationBufferComponents: 1024 
resultIterationBatchSize: 64 
writeBufferLowWaterMark: 32768 
writeBufferHighWaterMark: 655360 

janusgraph-cassa ndra.properties:私が正しく理解していれば、あなたはグレムリンサーバーがダウンした場合、要求は排他的にサーバーへのルーティングを開始するが、そのダウンしたサーバーがオンラインに戻ったときにクライアントが認識しない

gremlin.graph=org.janusgraph.core.JanusGraphFactory 
storage.backend=cassandrathrift 
storage.hostname=192.168.2.57,192.168.2.70,192.168.2.77 
cache.db-cache = true 
cache.db-cache-clean-wait = 20 
cache.db-cache-time = 180000 
cache.db-cache-size = 0.5 
#storage.cassandra.replication-strategy-class=org.apache.cassandra.locator.NetworkTopologyStrategy 
#storage.cassandra.replication-strategy-options=dc1,2,dc2,1 
storage.cassandra.read-consistency-level=QUORUM 
storage.cassandra.write-consistency-level=QUORUM 
ids.authority.conflict-avoidance-mode=GLOBAL_AUTO 
+0

[connect method](https://github.com/apache/tinkerpop/blob/master/gremlin-driver/src/main/java/org/apache/)でセッション接続を使用していないと思います。 tinkerpop/gremlin/driver/Cluster.java#L77-L90)と[connect(sessionId)メソッド](https://github.com/apache/tinkerpop/blob/master/gremlin-driver/src/main/java/)を比較します。 org/apache/tinkerpop/gremlin/driver/Cluster.java#L106-L125)を使用しています。もちろん、あなたが使用しているTPのバージョンと一致するコードを見ています。 – David

+0

私はセッションレス通信を使いたいです。 – lubican

+0

Gremlin Serverのインスタンスには相互の知識はありませんが、アプリケーションでTinkerPopドライバをどのように設定したかに応じて、ドライバがデッドサーバを検出した場合には、使用可能な他のサーバーに要求を送信するだけです。バックグラウンドでは、デッドサーバーに再接続しようとし続けます。オンラインに戻った場合は、要求を送信するサーバーのプールにそれが含まれます。 – lubican

答えて

1

を言っていますそれが戻ってきているので、すべての要求が、時間全体にとどまっていた1台のサーバーに流れ続けます。それが正しいとすれば、Gremlin Server 3.3.0で問題を再現することはできません(ただし、3.2.xでは別の動作が疑わしいとは思いませんが、実際に起こった変更はわかりません3.2.xでは発生していなかった3.3.0のドライバ)。

あなたのコードでは、どのようにテストしているかは完全にはわかりません。私のテストでは、私はこれを行うにはグレムリンコンソールを使用:私は、サーバーを殺したところ

gremlin> cluster = Cluster.build().addContactPoint("192.168.1.7").addContactPoint("192.168.1.6").create() 
==>/192.168.1.7:8182, localhost/127.0.0.1:8182 
gremlin> client = cluster.connect() 
==>[email protected]0e5 
gremlin> (0..<100000).collect{client.submit("1+1").all().get()}.toList();[] 
java.util.concurrent.ExecutionException: java.nio.channels.ClosedChannelException 
Type ':help' or ':h' for help. 
Display stack trace? [yN]n 
gremlin> (0..<100000).collect{client.submit("1+1").all().get()}.toList();[] 

ClosedChannelExceptionを示しました。私はその後、Gremlin Serverのログから、オンラインにとどまっていたサーバーに送信されたリクエストの数を記録しました。その後、私は殺してしまったサーバを再起動し、Gremlin Consoleでリクエストの流れを再開しました。両方のリクエスト数を調べると、両方とも増加していました。これは、ドライバがダウンしたサーバーがオンラインに戻ったことを検出できたことを意味します。

あなたの質問から、ドライバが再接続していないことをどのように判断しているのかは分かりませんが、Clusterオブジェクトを作成して破壊していることに気付いています。 getImpactedComponentsIdsアプリケーションサービス。実際にはClusterオブジェクトを1回作成して再利用する必要があります。これは、ネットワークリソースプールの数が増加するため、オブジェクトの作成に費用がかかります。この作成/破棄のアプローチのため再接続していない可能性があります。

Clusterの作成/破棄のアプローチでは、再接続が起こっていないように見えるシナリオを想像することができましたが、ドライバの負荷分散アプローチでは、作成時に、ランダムな選択が、あなたが行ったすべての単一のテストで常に同じホストに移動することが大変不運だった場合を除き、少なくともある程度はダウンしたサーバーに接続しているはずです。

+0

はい、あなたは私の問題を理解しています。 私のアプリケーションを起動すると、2つのサーバーGremlinの出口で要求が表示されます。 ドライバがクラスタの他のノードに接続していないと判断しました。なぜなら、一度起動されると、すべてのトランザクションが1つのサーバにのみ送信されるからです。gremlin リクエストを正しく受信したサーバをオフにすると、 – lubican

+0

私の問題はクラスタオブジェクトの破壊と作成にあると思います。 このコードは私によって開発されていません。 LOCALHOSTに接続するために開発されました。私はクラスタに適応しています。 – lubican

+0

GremlinClusterはSpring Beanで、アプリケーションの起動時にのみ作成されます。デバッグモードでブレークポイントを設定してこれを確認します。 – lubican

関連する問題