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.
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
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