2016-06-09 8 views
2

Beim Versuch, in eine entfernte Cassandra db auf einmal mehrere tausend Datensätze einzufügen, I (mit 5-6000 Elemente über eine langsame Verbindung)mit NoHostAvailableException Umgang mit Phantom DSL

Fehler reproduzierbar in Timeouts laufen:

All host(s) tried for query failed (tried: /...:9042 
(com.datastax.driver.core.exceptions.OperationTimedOutException: [/...] 
Timed out waiting for server response)) 
com.datastax.driver.core.exceptions.NoHostAvailableException: 
All host(s) tried for query failed (tried: /...:9042 
(com.datastax.driver.core.exceptions.OperationTimedOutException: [/...] 
Timed out waiting for server response)) 

das Modell:

class RecordModel extends CassandraTable[ConcreteRecordModel, Record] { 

    object id extends StringColumn(this) with PartitionKey[String] 

... 
abstract class ConcreteRecordModel extends RecordModel 
    with RootConnector with ResultSetFutureHelper { 

def store(rec: Record): Future[ResultSet] = 
    insert.value(_.id, rec.id).value(...).future() 

def store(recs: List[Record]): Future[List[ResultSet]] = Future.traverse(recs)(store) 

der Verbinder:

val connector = ContactPoints(hosts).withClusterBuilder(
    _.withCredentials(
    config.getString("username"), 
    config.getString("password") 
).withPoolingOptions(
    new PoolingOptions().setCoreConnectionsPerHost(HostDistance.LOCAL, 4) 
     .setMaxConnectionsPerHost(HostDistance.LOCAL, 10) 
     .setCoreConnectionsPerHost(HostDistance.REMOTE, 2) 
     .setMaxConnectionsPerHost(HostDistance.REMOTE, 4) 
     .setMaxRequestsPerConnection(HostDistance.LOCAL, 32768) 
     .setMaxRequestsPerConnection(HostDistance.REMOTE, 2000) 
     .setPoolTimeoutMillis(10000) 
) 
).keySpace(keyspace) 

Ich habe versucht, die Pooling-Optionen getrennt und zusammen zu optimieren. Aber auch all die REMOTE Einstellungen Verdoppelung nicht den Timeout merklich

aktuelle Problemumgehung hat ändern, was ich vermeiden möchte - Aufspalten der Liste in Chargen und warten für die Fertigstellung der einzelnen:

def store(recs: List[Record]): Future[List[ResultSet]] = { 
    val rs: Iterator[List[ResultSet]] = recs.grouped(1000) map { slice => 
    Await.result(Future.traverse(slice)(store), 100 seconds) 
    } 
    Future.successful(rs.to[List].flatten) 
} 

Was wäre ein guter Weg, um mit diesem Problem umzugehen?

Danke

EDIT

Die Fehler schlagen/überlasteten Cluster Fehler, aber ich vermute Netz hier eine große Rolle spielt. Die oben angegebenen Nummern stammen von einem Remote-Computer. Sie sind VIEL höher, wenn dasselbe C * von einer Maschine im selben Rechenzentrum gespeist wird. Ein weiteres verdächtiges Detail besteht darin, dass das Eingeben der gleichen C * -Instanz mit quill keine Timeout-Probleme, entfernt oder nicht, verursacht.

Was ich wirklich an Throttling nicht mag, ist, dass die Batchgrößen zufällig und statisch sind, während sie adaptierbar sein sollten.

Antwort

1

Klingt, als würden Sie die Grenzen Ihres Clusters erreichen. Wenn Sie Zeitüberschreitungen vermeiden möchten, müssen Sie mehr Kapazität hinzufügen, um die Last bewältigen zu können. Wenn Sie nur Burst-Schreibvorgänge ausführen möchten, sollten Sie sie drosseln (wie Sie es tun), da das Senden zu vieler Abfragen an zu wenige Knoten die Leistung beeinträchtigt. Sie können auch die Timeouts auf der Serverseite verlängern (read_request_timeout_in_ms, write_request_timeout_in_ms, request_timeout_in_ms), wenn Sie warten wollen, bis Sie schreiben können, aber das ist nicht ratsam, da Sie Cassandra keine Zeit geben werden, sich zu erholen und wahrscheinlich große Mengen von ParNew GC verursachen.

+0

IIUC Sie schlagen vor, dass der Weg zu gehen mehr Maschinen hinzufügen würde? Das kann gemacht werden, aber ich wundere mich immer noch über die geringe Anzahl von akzeptierten Anfragen. Haben Sie oben einige Details hinzugefügt, vielleicht haben Sie eine Idee. Könnten Sie bitte einige Einzelheiten zu einer angemessenen Wiederholungsstrategie mitteilen? Was wäre eine angemessene Zeit für die Wiederherstellung des Clusters? Habe Versuche mit mehr Timeouts probiert, aber manchmal scheint es sogar nach 30sec zu früh zu sein. – kostja

+0

Wenn Sie eine Feder verwenden, führen Sie dieselben Abfragen aus? Diese Ausnahmen treten definitiv auf der Client-Seite der Timeouts auf, da der Cluster jedoch zu lange braucht, um mit den Ergebnissen zu antworten. Sehen Sie viele GC in den Protokollen auf den Servern? Wenn der Cluster CPU-/IO-weise nicht stark ausgelastet ist, könnten Sie auch das Lese-Timeout erhöhen. Clientseitig http://docs.datastax.com/de/drivers/java/2.1/com/datastax/ driver/core/SocketOptions.html # setReadTimeoutMillis-int- – Kurt