Cassandra Session.execute无限阻塞问题求助
你描述的情况很典型——能成功建立连接,但执行查询时无限挂起,而cqlsh和DevCenter却能正常工作。结合你的Windows环境和Cassandra 3.8.0版本,我整理了几个常见的排查和解决方向:
首先先回顾下你的代码和程序输出:
你的连接代码
public class StartDriver { public static void main(String[] args) { Cluster cluster = null; try { cluster = Cluster.builder() // (1) .addContactPoint("127.0.0.1").withPort(9042).build(); SocketOptions socketOptions = cluster.getConfiguration().getSocketOptions(); socketOptions.setConnectTimeoutMillis(1000); System.out.println("Connection established"); Session session = cluster.connect(); // (2) System.out.println(session.getState().getConnectedHosts()); System.out.println("Try to execute Query"); ResultSet rs = session.execute("SELECT * FROM htw.student"); System.out.println("Query executed");// (3) Row row = rs.one(); // System.out.println(row.getString("release_version")); if (cluster != null) cluster.close(); } catch (Exception e) { e.printStackTrace(); } } }
程序输出
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Connection established
[/127.0.0.1:9042]
Try to execute Query
排查与解决方法
1. 显式设置查询的一致性级别
单节点Cassandra集群最容易出现这个问题:Java Driver默认的一致性级别(比如QUORUM)需要至少半数以上节点响应,但单节点无法满足这个条件,导致查询无限等待。你可以把一致性级别改为LOCAL_ONE(适合单节点场景):
import com.datastax.driver.core.ConsistencyLevel; import com.datastax.driver.core.SimpleStatement; // ... ResultSet rs = session.execute( SimpleStatement.builder("SELECT * FROM htw.student") .setConsistencyLevel(ConsistencyLevel.LOCAL_ONE) .build() );
2. 检查Cassandra的rpc_address配置
Windows环境下,Cassandra的rpc_address有时候会默认绑定到非本地回环地址,导致Driver虽然能建立连接,但无法正常通信。打开cassandra.yaml文件(一般在Cassandra安装目录的conf文件夹下),找到rpc_address配置项,确认它设置为127.0.0.1或者你的本地IP地址,修改后重启Cassandra服务。
3. 确保Driver版本与Cassandra兼容
Cassandra 3.8.0需要搭配3.x系列的Java Driver(比如3.11.x版本,尽量选和Cassandra版本接近的稳定版)。如果你的Driver是4.x系列,会和3.x的Cassandra存在兼容性问题,导致无响应。如果用Maven的话,可以调整依赖:
<dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-core</artifactId> <version>3.11.10</version> </dependency>
4. 添加读取超时配置
你已经设置了连接超时,但没有设置读取超时,这会导致程序无限挂起而不抛出异常。可以在构建Cluster时添加读取超时:
cluster = Cluster.builder() .addContactPoint("127.0.0.1") .withPort(9042) .withSocketOptions(new SocketOptions() .setConnectTimeoutMillis(1000) .setReadTimeoutMillis(5000)) // 5秒读取超时,超时会抛出异常 .build();
这样如果查询真的有问题,会抛出超时异常,方便你进一步排查。
5. 确认Keyspace和表的正确性
虽然你说cqlsh能正常操作,但还是要确认下代码里的htw.student是否存在,有没有大小写错误(Cassandra默认会把标识符转为小写,除非创建表时用双引号包裹了大写名称)。比如如果表是Student(带大写),而代码里写student,会找不到表,不过一般会直接报错,但也不排除特殊情况导致挂起。
内容的提问来源于stack exchange,提问作者Emlon

