【问题标题】:Storm Crashing after 23 hours风暴在 23 小时后坠毁
【发布时间】:2012-11-14 22:18:21
【问题描述】:

大家好,我有一个基本的 Storm 应用程序设置,它接收推文流并将它们存储在 MySQL 数据库中。该应用程序在前约 23 小时内运行良好,然后开始出现以下错误:

SQL Exception
SQL State: 08003

在它这样做几次之后它就死了。我正在使用标准 JBDC 连接器从 Java 连接到数据库。存储和建立DB连接的函数代码如下:

private String _db="";
private Connection conn = null;
private PreparedStatement pst = null;

public ArchiveBolt(String db){
    _db = db;
}

private void setupConnection() {
    //Connect to the database
    try {
        Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection("jdbc:mysql://localhost:8889/twitter_recording", "root", "root");
    } catch (Exception e){
        e.printStackTrace();
    }
}

public void execute(Tuple tuple, BasicOutputCollector collector) {

    Status s = (Status) tuple.getValue(0);

    //setup the connection on the first run through or if the connection got closed down
    try {
        setupConnection();
    } catch (Exception e) {
        // TODO: handle exception
        System.out.println(e.toString());
    }


    try {

        pst = conn.prepareStatement("INSERT INTO " + _db + " (tweet)" +
                                    "VALUES (?);");

        pst.setString(1, s.toString());

        //execute the SQL
        pst.executeUpdate();

    } catch (SQLException ex) {
        // handle any errors
        System.out.println("SQLException: " + ex.getMessage());
        System.out.println("SQLState: " + ex.getSQLState());
        System.out.println("VendorError: " + ex.getErrorCode());

        if(ex.getSQLState().equals("08003")){
            setupConnection();
        }

    } finally {
        try {
            conn.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

在很明显它由于 08003 错误而崩溃后,我决定如果它抛出该错误,它应该重试连接设置,但这也无济于事。谁能指出我解决这个问题的正确方向?

【问题讨论】:

  • 连接是否总是在一天中的同一时间断开?如果是这样,则连接可能被某些预定事件中断(例如,数据库每天都会重新启动)。
  • 是的,我知道这一点。这就是为什么在遇到此错误的情况下再次设置连接的原因。如上图catch (SQLException ex) { // handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); if(ex.getSQLState().equals("08003")){ setupConnection(); } }
  • 如果每天重启,数据库可能会宕机几分钟,尝试立即重新连接会失败。
  • 连接不会在每天的同一时间断开。从我开始它总是大约 23 小时。我控制数据库,在项目的这个阶段,它持续 24/7 持续运行。

标签: java mysql jdbc apache-storm


【解决方案1】:

在很明显它由于 08003 错误而崩溃后,我决定如果它抛出该错误,它应该重试连接设置,但这也无济于事。谁能指出我解决这个问题的正确方向?

这里基本上有两个问题需要解决:

  • 为什么连接会丢失?
  • 为什么您尝试重新连接没有成功?

对于第一个问题,您应该查看 MySQL 日志,看看那里是否有任何迹象。此外,在(重复的)“状态 080003”异常之前立即检查 SQL 异常。后者只是告诉您连接之前已断开。

我的猜测是问题出在以下之一:

  • MySQL 服务器由于不活动而导致连接超时。如果这是问题,您可以在 MySQL 配置中更改连接超时。

  • 您的应用程序可能会慢慢泄漏 JDBC 连接。

对于第二个问题,一般做法是正确的,但你的代码与描述不符。事实上,每次调用execute 方法时,它似乎总是 试图建立一个新的数据库连接。这使得异常处理程序中的重新连接调用毫无意义。 (OTOH,代码显示有人一直在“敲打它”试图让它工作......这很可能是问题的一部分。)

我会检查setupConnection 是否在需要时被调用,并寻找任何可能引发的异常。此外,您应该确保明确close() 死连接对象...并重新考虑/重新编码您的连接管理,使其不会泄漏。


作为记录,有一个名为“autoReconnect”的连接 URL 参数在遥远的过去用于“处理”丢失的连接。不幸的是,最初的实现是不安全的,所以他们有效地禁用了它;有关详细信息,请参阅此问题:Why does autoReconnect=true not seem to work?

【讨论】:

    猜你喜欢
    • 2014-12-30
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多