Cassandra NoHostAvailableException Java-CQLDriver

我正在使用Cassandra的CQL驱动程序在java中构建应用程序。 当我使用本地cassandra服务器时,我能够正常运行它。 但是,当我尝试运行时,相同的代码不适用于远程cassandra服务器。 初始化期间出现以下错误: –

以下是我用于CQL驱动程序的maven依赖: –

 com.datastax.cassandra cassandra-driver-core 2.1.3   com.datastax.cassandra cassandra-driver-mapping 2.1.2  

以下是错误: –

 com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: yyyy.yyy.yyy.yyy.yyy-yyy.net/yy.yy.yy.yy:9160 (com.datastax.driver.core.ConnectionException: [yyyy.yyy.yyy.yyy.yyy-yyy.net/yy.yy.yy.yy:9160] Unexpected error during transport initialization (com.datastax.driver.core.ConnectionException: [yyyy.yyy.yyy.yyy.yyy-yyy.net/yy.yy.yy.yy:9160] Operation timed out)), Unexpected error during transport initialization (com.datastax.driver.core.ConnectionException: [xxxx.xxx.xxx.xxx.xxx-xxx.net/xx.xx.xx.xx:9160] Operation timed out))) at com.datastax.driver.core.ControlConnection.reconnectInternal(ControlConnection.java:220) at com.datastax.driver.core.ControlConnection.connect(ControlConnection.java:78) at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1231) at com.datastax.driver.core.Cluster.init(Cluster.java:158) at com.datastax.driver.core.Cluster.connect(Cluster.java:246) 

一切正常的本地cassandra服务器是: –

 cqlsh 4.1.1, Cassandra 2.0.7 , CQL spec: 3.1.1, Thrift Protocol 19.39.0 

连接超时的远程cassandra服务器是: –

 cqlsh 3.1.8 | Cassandra 1.2.12 | CQL spec 3.0.0 | Thrift protocol 19.36.1 

我使用以下代码进行连接。 有人可以评论远程连接情况下出了什么问题吗?

 clusterOBJECT = Cluster.builder().addContactPointsWithPorts(addrs) .withQueryOptions(new QueryOptions().setConsistencyLevel(ConsistencyLevel.ONE)) .withProtocolVersion(1).withoutJMXReporting() .withPort(port) .withSocketOptions(options) .withRetryPolicy(DefaultRetryPolicy.INSTANCE) .withLoadBalancingPolicy(new TokenAwarePolicy(new DCAwareRoundRobinPolicy())).build(); session = clusterOBJECT.connect(); 

我在addContactPointsWithPorts中提供有效的主机名以及端口(9160)。 主机名也是可ping的。

PS: – cassandra.yaml中已设置以下属性。

 start_native_transport: true native_transport_port: 9042 

[编辑]将端口更改为9042后,我能够连接到Cassandra。 但是我发现很快就会被这个例外的连接丢掉。

 com.datastax.driver.core.TransportException: [/xx.xx.xxx.xx:9042] Cannot connect at com.datastax.driver.core.Connection.(Connection.java:106) at com.datastax.driver.core.PooledConnection.(PooledConnection.java:35) at com.datastax.driver.core.Connection$Factory.open(Connection.java:528) at com.datastax.driver.core.DynamicConnectionPool.(DynamicConnectionPool.java:74) at com.datastax.driver.core.HostConnectionPool.newInstance(HostConnectionPool.java:33) at com.datastax.driver.core.SessionManager.replacePool(SessionManager.java:270) at com.datastax.driver.core.SessionManager.access$400(SessionManager.java:39) at com.datastax.driver.core.SessionManager$3.call(SessionManager.java:303) at com.datastax.driver.core.SessionManager$3.call(SessionManager.java:295) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: java.net.ConnectException: Connection refused: /xx.xx.xxx.xx:9042 at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:739) at org.jboss.netty.channel.socket.nio.NioClientBoss.connect(NioClientBoss.java:150) at org.jboss.netty.channel.socket.nio.NioClientBoss.processSelectedKeys(NioClientBoss.java:105) at org.jboss.netty.channel.socket.nio.NioClientBoss.process(NioClientBoss.java:79) at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318) at org.jboss.netty.channel.socket.nio.NioClientBoss.run(NioClientBoss.java:42) ... 3 more 

谢谢。

“我在addContactPointsWithPorts中提供有效的主机名和端口(9160)。主机名也是可ping的。”

在你原来的post中阅读这一行,并仔细检查一些文档后,我想我知道这里发生了什么。 关于Java驱动程序文档明确指出:

Apache Cassandra的Java Driver 2.0专门使用Cassandra查询语言版本3(CQL3)和Cassandra的新二进制协议

连接要求部分还指出:

您已在cassandra.yaml中配置以下内容:

 start_native_transport : true rpc_address : IP address or hostname 

可从群集中的客户端计算机访问,可以接受端口9042上的连接。注意:可以使用cassandra.yaml中的native_transport_port配置客户端端口。

换句话说,您不应该使用Thrift(9160)通过Java-CQL驱动程序连接到Cassandra。 尝试不设置端口(在withPort或主机名中)。 它应该尝试自己使用9042。

编辑 :好的,我只是自己尝试使用.addContactPoints (没有使用主机名指定的端口)和.withPort(9160) ,并且它有效。 这似乎与我之前在post中提到的文档相矛盾。 在任何情况下,我仍然建议使用本机协议(9042),因为Thrift协议已被弃用。 此外,较新版本的Cassandra(2.1)和DataStax CQL驱动程序已经certificate可以胜过基于Thrift的驱动程序 。

我认为这里的关键是“本地”和“远程”。 我问了这个问题,但没有得到答案,但我怀疑有两个问题之一:

  1. 防火墙阻止客户端的端口9160和9042。 您是否尝试过telnet到端口9160和9042的节点?

  2. 存在私有/公共地址问题,通常在群集位于专用网络内部时观察到,并且客户端尝试使用外部IP地址访问群集。 在这种情况下,群集不知道由基础结构分配的公共IP。 在这种情况下,驱动程序有责任进行此地址转换。 例如,Java驱动程序有一个名为AddressTranslater的策略,您可以实现该策略以执行从内部IP到外部的转换 – 例如,通过使用AWS API。 http://www.datastax.com/drivers/java/2.0/com/datastax/driver/core/policies/AddressTranslater.html这是一个实现的链接(我自己没有用过): http:// docs.hazelcast.org/docs/3.3/javadoc/com/hazelcast/client/spi/impl/AwsAddressTranslator.html