【问题标题】:cassandra single node connection errorcassandra单节点连接错误
【发布时间】:2015-03-14 10:00:33
【问题描述】:

我正在尝试使用 cassandra 作为我正在开发的应用程序的数据库。该应用程序是 Netbeans 平台应用程序。 为了在我的本地主机上启动 cassandra 服务器,我发出 Runtime.getRuntime().exec(command) 其中 command 是启动 cassandra 服务器的字符串,然后我使用 datastax 驱动程序连接到 cassandra 服务器。但是我得到了错误:

com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query   failed (tried: /127.0.0.1:9042 (com.datastax.driver.core.TransportException: [/127.0.0.1:9042]  Cannot connect))
at com.datastax.driver.core.ControlConnection.reconnectInternal(ControlConnection.java:199)
at com.datastax.driver.core.ControlConnection.connect(ControlConnection.java:80)
at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1154)
at com.datastax.driver.core.Cluster.getMetadata(Cluster.java:318)
at org.dhviz.boot.DatabaseClient.connect(DatabaseClient.java:43)
at org.dhviz.boot.Installer.restored(Installer.java:67)
....

我发现服务器需要一些时间才能启动,所以我添加了 Thread.sleep(MAX_DELAY_SERVER) 行,这似乎可以解决问题。

有没有更优雅的方式来解决这个问题? 谢谢。

代码如下。

public class Installer extends ModuleInstall {

private final int MAX_DELAY_SERVER = 12000;

//private static final String pathSrc = "/org/dhviz/resources";
@Override
public void restored() {

    /*
     -*-*-*-*-*DESCRIPTION*-*-*-*-*-*
     IMPLEMENT THE CASSANDRA DATABASE
     *********************************
     */
    DatabaseClient d = new DatabaseClient();
    // launch an instance of the cassandra server 
    d.loadDatabaseServer();


    /*wait for MAX_DELAY_SERVER milliseconds before launching the other instructions. 
    */
    try {
        Thread.sleep(MAX_DELAY_SERVER);
        Logger.getLogger(Installer.class.getName()).log(Level.INFO, "wait for MAX_DELAY_SERVER milliseconds before the connect database");
    } catch (InterruptedException ex) {
        Exceptions.printStackTrace(ex);
        Logger.getLogger(Installer.class.getName()).log(Level.INFO, "exeption in thread sleep");
    }

    d.connect("127.0.0.1");

}
}



public class DatabaseClient {

private Cluster cluster;
private Session session;
private ShellCommand shellCommand;
private final String defaultKeyspace = "dhviz";

final private String LOAD_CASSANDRA = "launchctl load    /usr/local/Cellar/cassandra/2.1.2/homebrew.mxcl.cassandra.plist";

final private String UNLOAD_CASSANDRA = "launchctl unload /usr/local/Cellar/cassandra/2.1.2/homebrew.mxcl.cassandra.plist";

public DatabaseClient() {
    shellCommand = new ShellCommand();

}

public void connect(String node) {
//this connect to the cassandra database

    cluster = Cluster.builder()
            .addContactPoint(node).build();
//  cluster.getConfiguration().getSocketOptions().setConnectTimeoutMillis(12000);
    Metadata metadata = cluster.getMetadata();
    System.out.printf("Connected to cluster: %s\n",
            metadata.getClusterName());
    for (Host host
            : metadata.getAllHosts()) {
        System.out.printf("Datatacenter: %s; Host: %s; Rack: %s\n",
                host.getDatacenter(), host.getAddress(), host.getRack());

    }

        session = cluster.connect();


    Logger.getLogger(DatabaseClient.class.getName()).log(Level.INFO, "connected to server");
}

public void loadDatabaseServer() {
    if (shellCommand == null) {

        shellCommand = new ShellCommand();

    }
    shellCommand.executeCommand(LOAD_CASSANDRA);
    Logger.getLogger(DatabaseClient.class.getName()).log(Level.INFO, "database cassandra loaded");
}

public void unloadDatabaseServer() {
    if (shellCommand == null) {

        shellCommand = new ShellCommand();

    }

    shellCommand.executeCommand(UNLOAD_CASSANDRA);

    Logger.getLogger(DatabaseClient.class.getName()).log(Level.INFO, "database cassandra unloaded");
}

}

【问题讨论】:

  • 为什么不用cassandra驱动?github.com/datastax/java-driver终端连接会发生什么?
  • 根据提供的堆栈跟踪,这里似乎正在使用 java-driver

标签: java cassandra datastax-java-driver


【解决方案1】:

如果您在 Runtime.getRuntime().exec(command) 中不带任何参数调用 cassandra,这很可能是作为后台进程生成 cassandra 并在 cassandra 节点完全启动并正在侦听之前返回。

我不确定您为什么要尝试在您的应用中嵌入 cassandra,但您可能会发现使用 cassandra-unit 提供了一种在您的应用中嵌入 cassandra 的机制很有用。它主要用于运行需要 cassandra 实例的测试,但它也可能满足您的用例。

The wiki 提供了一个有用的示例,说明如何使用 cassandra-unit 启动嵌入式 cassandra 实例:

EmbeddedCassandraServerHelper.startEmbeddedCassandra();

根据我的经验,cassandra-unit 会等到服务器启动并监听后再返回。您还可以使用与this answer 相反的逻辑编写一个等待套接字使用的方法。

【讨论】:

  • 嗨,安迪。谢谢你的帮助。只是一个澄清。我对编码很陌生,对数据库非常熟悉。我有一个应用程序可以为许多对象生成年度时间序列,所以我想我会将它保存在 Cassandra 中,而不是将它们全部保存在内存中。在我看来,Cassandra 将作为运行应用程序的机器上的服务器运行。问题正是你所说的。在发出连接命令之前,服务器尚未侦听。但是我不确定如何使用您提到的示例。你能多指点一下吗?谢谢。
  • 通过我提到的示例,您指的是 EmbeddedCassandraHelper 还是我发布的答案的链接,该链接显示了如何检查套接字是否正在侦听? EmbeddedCassandraHelper 只是在您的 JVM 中启动一个嵌入式 cassandra 实例,这可能不是您想要的,因为它与您的应用程序正在执行的所有其他操作共享资源。现在我考虑一下,我链接的答案可能不是一个很好的例子。最好尝试打开一个到 localhost:9042 的套接字,而不是使用 ServerSocket。如果无法打开到 localhost:9042 的连接,则说明 cassandra 没有在监听。
  • 谢谢安迪。我没有设法让端口代码工作,但我从中获得灵感并更改了我的代码中的几行。感谢您的帮助!
【解决方案2】:

从下面的答案中获得灵感,我已将代码更改为以下内容。感谢您的帮助!

cluster = Cluster.builder()
            .addContactPoint(node).build();

    cluster.getConfiguration().getSocketOptions().setConnectTimeoutMillis(50000);

    boolean serverConnected = false;
    while (serverConnected == false) {
        try {
            try {
                Thread.sleep(MAX_DELAY_SERVER);

            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            }
            cluster = Cluster.builder()
                    .addContactPoint(node).build();

            cluster.getConfiguration().getSocketOptions().setConnectTimeoutMillis(50000);
            session = cluster.connect();
            serverConnected = true;

        } catch (NoHostAvailableException ex) {
            Logger.getLogger(DatabaseClient.class.getName()).log(Level.INFO, "trying connection to cassandra server...");
            serverConnected = false;
        }

    }                                                   

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 2016-10-12
    • 2016-12-13
    • 1970-01-01
    • 2020-04-27
    相关资源
    最近更新 更多