2016-06-09 52 views
2

當試圖幾千條記錄一次插入到遠程卡桑德拉分貝,我重複地遇到超時(5〜6千的元素連接速度慢)與NoHostAvailableException處理幻象DSL

錯誤:

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

模型:

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) 

連接器:

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) 

我已經嘗試調整池選項,分開和一起。但是,即使加倍所有的REMOTE設置並沒有改變超時明顯

目前的解決方法,這是我想避免 - 分裂清單分成批次,等待每完成:

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) 
} 

會是什麼處理這個問題的好方法?

謝謝

編輯

的錯誤確實表明未能/超載集羣,但我懷疑這裏的網絡發揮了重要作用。上面提供的數字來自遠程機器。當同一個數據中心的機器提供相同的C *時,它們要高得多。另一個可疑的細節是,用quill餵養相同的C *實例不會遇到任何超時問題,遠程或不遠。

我真的不喜歡節流的是批量大小是隨機的和靜態的,而它們應該是適應性的。

回答

1

聽起來就像是在觸及羣集的極限。如果你想避免超時,你將需要增加更多容量來處理負載。如果你只是想突發寫入,你應該扼殺它們(就像你在做的那樣),因爲向太少的節點發送太多查詢會抑制性能。如果您想等到可以寫入,則還可以增加服務器端的超時(read_request_timeout_in_ms,write_request_timeout_in_ms,request_timeout_in_ms),但這不可取,因爲您不會隨時給Cassandra恢復並可能導致大量ParNew GC。

+0

IIUC你建議的方式去增加更多的機器?這可以完成,但我仍然想知道接受請求的數量很少。在上面添加了一些細節,也許你有一個想法。你可以分享一些合理的重試策略的細節嗎?什麼是集羣恢復的合理時間。已經嘗試過增加超時退出,但有時甚至在30秒後重試似乎要早。 – kostja

+0

使用羽毛筆時,您是否執行相同的查詢?這些例外情況肯定發生在超時客戶端,但是由於集羣花費太長時間來響應結果。你在服務器的日誌中看到很多GC嗎?如果羣集沒有出現CPU/IO明顯負載的情況,那麼您也可以增加客戶端的讀取超時 http://docs.datastax.com/en/drivers/java/2.1/com/datastax/驅動器/核心/ SocketOptions.html#setReadTimeoutMillis,內部 - – Kurt