如何在Spark Executor中关闭核心之间的共享单例连接

时间:2018-06-11 16:51:41

标签: multithreading scala apache-spark database-connection executor

我在Spark的单个执行程序的所有核心之间使用共享连接。基本上我已经创建了单独的连接对象,以便在单个执行器的内核之间共享,以便它在内核之间共享,每个执行器只有一个连接。

object SingletonConnection {

private var connection: Connection = null

def getConnection(url: String, username: String, password: String): Connection = synchronized {
if (connection == null) {
  connection = DriverManager.getConnection(url, username, password)
}
connection
}
}

Spark执行器代码:

dataFrame.foreachPartition { batch =>
  if (batch.nonEmpty) {
    lazy val dbConnection = SingletonConnection
    val dbc = dbConnection.getConnection(url, user, password)

    // do some operatoins


          st.addBatch()
        }
        st.executeBatch()
      }
    }
    catch {
      case exec: BatchUpdateException =>
        var ex: SQLException = exec
        while (ex != null) {
          ex.printStackTrace()
          ex = ex.getNextException
        }
        throw exec
    }

  }
}

这里的问题是,我无法关闭连接。因为我不知道特定核心什么时候完成它的执行。如果我最终关闭连接,只要一个核完成其任务,它就会关闭连接并导致所有其他核心因共享连接关闭而停止。

由于我没有在此处关闭连接,因此即使在任务完成后连接仍保持打开状态。如何使这个过程工作,以便我能够在所有核心完成任务后才能关闭连接。

1 个答案:

答案 0 :(得分:0)

我使用Java实现了它,所以我可以给你一些线索。

在SingletonConnection类中,我创建了一个线程安全的累加器。每次打开连接时,累加器都会加一。并且每次关闭连接时,累加器都会减一,并检查累加器是否等于零。当蓄能器 等于零,则可以关闭连接。

当其他运行线程仍在使用连接时,这不会关闭连接。但这将使您创建的连接数量超出您的想象(分区数)。