我在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
}
}
}
这里的问题是,我无法关闭连接。因为我不知道特定核心什么时候完成它的执行。如果我最终关闭连接,只要一个核完成其任务,它就会关闭连接并导致所有其他核心因共享连接关闭而停止。
由于我没有在此处关闭连接,因此即使在任务完成后连接仍保持打开状态。如何使这个过程工作,以便我能够在所有核心完成任务后才能关闭连接。
答案 0 :(得分:0)
我使用Java实现了它,所以我可以给你一些线索。
在SingletonConnection类中,我创建了一个线程安全的累加器。每次打开连接时,累加器都会加一。并且每次关闭连接时,累加器都会减一,并检查累加器是否等于零。当蓄能器 等于零,则可以关闭连接。
当其他运行线程仍在使用连接时,这不会关闭连接。但这将使您创建的连接数量超出您的想象(分区数)。